diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24476c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..3fdf532 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: android + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: ios + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: linux + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: macos + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: web + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: windows + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md index e69de29..9a223c4 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,16 @@ +# unit2 + +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..61b6c4d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# 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-lang.github.io/linter/lints/index.html. + # + # 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..be52da5 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,72 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion flutter.compileSdkVersion + ndkVersion "25.1.8937393" + + 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.unit2" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-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 { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..f26dc6f --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c3002df --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java b/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java new file mode 100644 index 0000000..752fc18 --- /dev/null +++ b/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java @@ -0,0 +1,25 @@ +// Generated file. +// +// If you wish to remove Flutter's multidex support, delete this entire file. +// +// Modifications to this file should be done in a copy under a different name +// as this file may be regenerated. + +package io.flutter.app; + +import android.app.Application; +import android.content.Context; +import androidx.annotation.CallSuper; +import androidx.multidex.MultiDex; + +/** + * Extension of {@link android.app.Application}, adding multidex support. + */ +public class FlutterMultiDexApplication extends Application { + @Override + @CallSuper + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); + } +} diff --git a/android/app/src/main/kotlin/com/example/unit2/MainActivity.kt b/android/app/src/main/kotlin/com/example/unit2/MainActivity.kt new file mode 100644 index 0000000..ecbd330 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/unit2/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.unit2 + +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/unit.png b/android/app/src/main/res/mipmap-hdpi/unit.png new file mode 100644 index 0000000..f8ecca0 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/unit.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/unit.png b/android/app/src/main/res/mipmap-mdpi/unit.png new file mode 100644 index 0000000..1467edc Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/unit.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/unit.png b/android/app/src/main/res/mipmap-xhdpi/unit.png new file mode 100644 index 0000000..15a1e02 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/unit.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/unit.png b/android/app/src/main/res/mipmap-xxhdpi/unit.png new file mode 100644 index 0000000..c1a8e83 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/unit.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/unit.png b/android/app/src/main/res/mipmap-xxxhdpi/unit.png new file mode 100644 index 0000000..d7c5bfe Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/unit.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/main/res/xml/file_provider_path.xml b/android/app/src/main/res/xml/file_provider_path.xml new file mode 100644 index 0000000..f592eef --- /dev/null +++ b/android/app/src/main/res/xml/file_provider_path.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..f26dc6f --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..dfce013 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.8.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.2' + 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') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +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..ee64223 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +android.enableDexingArtifactTransform=false +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/fail.mp3 b/assets/fail.mp3 new file mode 100644 index 0000000..6ad9241 Binary files /dev/null and b/assets/fail.mp3 differ diff --git a/assets/fonts/LexendDeca-Bold.ttf b/assets/fonts/LexendDeca-Bold.ttf new file mode 100644 index 0000000..f373a36 Binary files /dev/null and b/assets/fonts/LexendDeca-Bold.ttf differ diff --git a/assets/fonts/LexendDeca-Light.ttf b/assets/fonts/LexendDeca-Light.ttf new file mode 100644 index 0000000..df16a79 Binary files /dev/null and b/assets/fonts/LexendDeca-Light.ttf differ diff --git a/assets/fonts/LexendDeca-Medium.ttf b/assets/fonts/LexendDeca-Medium.ttf new file mode 100644 index 0000000..2c65634 Binary files /dev/null and b/assets/fonts/LexendDeca-Medium.ttf differ diff --git a/assets/fonts/LexendDeca-Regular.ttf b/assets/fonts/LexendDeca-Regular.ttf new file mode 100644 index 0000000..736bed8 Binary files /dev/null and b/assets/fonts/LexendDeca-Regular.ttf differ diff --git a/assets/fonts/LexendDeca-SemiBold.ttf b/assets/fonts/LexendDeca-SemiBold.ttf new file mode 100644 index 0000000..9ab8d35 Binary files /dev/null and b/assets/fonts/LexendDeca-SemiBold.ttf differ diff --git a/assets/fonts/LexendDeca-VariableFont_wght.ttf b/assets/fonts/LexendDeca-VariableFont_wght.ttf new file mode 100644 index 0000000..6405e15 Binary files /dev/null and b/assets/fonts/LexendDeca-VariableFont_wght.ttf differ diff --git a/assets/invalid.mp3 b/assets/invalid.mp3 new file mode 100644 index 0000000..b7c5d31 Binary files /dev/null and b/assets/invalid.mp3 differ diff --git a/assets/pngs/bg.png b/assets/pngs/bg.png new file mode 100644 index 0000000..b8afe26 Binary files /dev/null and b/assets/pngs/bg.png differ diff --git a/assets/pngs/emergency.png b/assets/pngs/emergency.png new file mode 100644 index 0000000..5a12015 Binary files /dev/null and b/assets/pngs/emergency.png differ diff --git a/assets/pngs/qr-scan.png b/assets/pngs/qr-scan.png new file mode 100644 index 0000000..2e534a2 Binary files /dev/null and b/assets/pngs/qr-scan.png differ diff --git a/assets/sounds/ScanFailed.mp3 b/assets/sounds/ScanFailed.mp3 new file mode 100644 index 0000000..7309226 Binary files /dev/null and b/assets/sounds/ScanFailed.mp3 differ diff --git a/assets/sounds/Successful.mp3 b/assets/sounds/Successful.mp3 new file mode 100644 index 0000000..5fe691d Binary files /dev/null and b/assets/sounds/Successful.mp3 differ diff --git a/assets/success.mp3 b/assets/success.mp3 new file mode 100644 index 0000000..7b8174a Binary files /dev/null and b/assets/success.mp3 differ diff --git a/assets/svgs/add_mobile.svg b/assets/svgs/add_mobile.svg new file mode 100644 index 0000000..83b7834 --- /dev/null +++ b/assets/svgs/add_mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/assign.svg b/assets/svgs/assign.svg new file mode 100644 index 0000000..3d521c0 --- /dev/null +++ b/assets/svgs/assign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/download.svg b/assets/svgs/download.svg new file mode 100644 index 0000000..feb7a4c --- /dev/null +++ b/assets/svgs/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/emergency.png b/assets/svgs/emergency.png new file mode 100644 index 0000000..5a12015 Binary files /dev/null and b/assets/svgs/emergency.png differ diff --git a/assets/svgs/empty.svg b/assets/svgs/empty.svg new file mode 100644 index 0000000..5834f68 --- /dev/null +++ b/assets/svgs/empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/error.svg b/assets/svgs/error.svg new file mode 100644 index 0000000..3fbbf17 --- /dev/null +++ b/assets/svgs/error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/female.svg b/assets/svgs/female.svg new file mode 100644 index 0000000..35fa415 --- /dev/null +++ b/assets/svgs/female.svg @@ -0,0 +1 @@ +female_avatar \ No newline at end of file diff --git a/assets/svgs/jpg.svg b/assets/svgs/jpg.svg new file mode 100644 index 0000000..f6e0591 --- /dev/null +++ b/assets/svgs/jpg.svg @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/assets/svgs/logo.svg b/assets/svgs/logo.svg new file mode 100644 index 0000000..81670ef --- /dev/null +++ b/assets/svgs/logo.svg @@ -0,0 +1,108 @@ + + + + + + + + diff --git a/assets/svgs/male.svg b/assets/svgs/male.svg new file mode 100644 index 0000000..a2b2d1e --- /dev/null +++ b/assets/svgs/male.svg @@ -0,0 +1 @@ +male_avatar \ No newline at end of file diff --git a/assets/svgs/no_module.svg b/assets/svgs/no_module.svg new file mode 100644 index 0000000..7d09b1e --- /dev/null +++ b/assets/svgs/no_module.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/pdf.svg b/assets/svgs/pdf.svg new file mode 100644 index 0000000..5226e09 --- /dev/null +++ b/assets/svgs/pdf.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/assets/svgs/png.svg b/assets/svgs/png.svg new file mode 100644 index 0000000..77671a4 --- /dev/null +++ b/assets/svgs/png.svg @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/assets/svgs/request_sos.svg b/assets/svgs/request_sos.svg new file mode 100644 index 0000000..f4cd5b8 --- /dev/null +++ b/assets/svgs/request_sos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/settings.svg b/assets/svgs/settings.svg new file mode 100644 index 0000000..b6f9644 --- /dev/null +++ b/assets/svgs/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/sos.svg b/assets/svgs/sos.svg new file mode 100644 index 0000000..6133f7f --- /dev/null +++ b/assets/svgs/sos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/switch.svg b/assets/svgs/switch.svg new file mode 100644 index 0000000..68521a8 --- /dev/null +++ b/assets/svgs/switch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svgs/timeout.svg b/assets/svgs/timeout.svg new file mode 100644 index 0000000..7638790 --- /dev/null +++ b/assets/svgs/timeout.svg @@ -0,0 +1 @@ +server down \ No newline at end of file diff --git a/assets/svgs/welcome.svg b/assets/svgs/welcome.svg new file mode 100644 index 0000000..1518990 --- /dev/null +++ b/assets/svgs/welcome.svg @@ -0,0 +1 @@ +welcome_cats \ No newline at end of file diff --git a/assets/svgs/workspace.svg b/assets/svgs/workspace.svg new file mode 100644 index 0000000..4f56391 --- /dev/null +++ b/assets/svgs/workspace.svg @@ -0,0 +1 @@ + \ No newline at end of file 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..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..88359b2 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..0bcedcc --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,185 @@ +PODS: + - assets_audio_player (0.0.1): + - Flutter + - assets_audio_player_web (0.0.1): + - Flutter + - audioplayers_darwin (0.0.1): + - Flutter + - barcode_scan2 (0.0.1): + - Flutter + - MTBBarcodeScanner + - SwiftProtobuf + - device_info (0.0.1): + - Flutter + - DKImagePickerController/Core (4.3.4): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.4) + - DKImagePickerController/PhotoGallery (4.3.4): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.4) + - DKPhotoGallery (0.0.17): + - DKPhotoGallery/Core (= 0.0.17) + - DKPhotoGallery/Model (= 0.0.17) + - DKPhotoGallery/Preview (= 0.0.17) + - DKPhotoGallery/Resource (= 0.0.17) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.17): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.17): + - SDWebImage + - SwiftyGif + - easy_app_installer (0.0.1): + - Flutter + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Flutter (1.0.0) + - fluttertoast (0.0.2): + - Flutter + - Toast + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - location (0.0.1): + - Flutter + - modal_progress_hud_nsn (0.0.1): + - Flutter + - MTBBarcodeScanner (5.0.11) + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.1.0): + - Flutter + - platform_device_id (0.0.1): + - Flutter + - rive_common (0.0.1): + - Flutter + - SDWebImage (5.17.0): + - SDWebImage/Core (= 5.17.0) + - SDWebImage/Core (5.17.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite (0.0.3): + - Flutter + - FMDB (>= 2.7.5) + - SwiftProtobuf (1.20.3) + - SwiftyGif (5.4.4) + - Toast (4.0.0) + +DEPENDENCIES: + - assets_audio_player (from `.symlinks/plugins/assets_audio_player/ios`) + - assets_audio_player_web (from `.symlinks/plugins/assets_audio_player_web/ios`) + - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) + - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`) + - device_info (from `.symlinks/plugins/device_info/ios`) + - easy_app_installer (from `.symlinks/plugins/easy_app_installer/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - Flutter (from `Flutter`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - location (from `.symlinks/plugins/location/ios`) + - modal_progress_hud_nsn (from `.symlinks/plugins/modal_progress_hud_nsn/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - platform_device_id (from `.symlinks/plugins/platform_device_id/ios`) + - rive_common (from `.symlinks/plugins/rive_common/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + +SPEC REPOS: + trunk: + - DKImagePickerController + - DKPhotoGallery + - FMDB + - MTBBarcodeScanner + - SDWebImage + - SwiftProtobuf + - SwiftyGif + - Toast + +EXTERNAL SOURCES: + assets_audio_player: + :path: ".symlinks/plugins/assets_audio_player/ios" + assets_audio_player_web: + :path: ".symlinks/plugins/assets_audio_player_web/ios" + audioplayers_darwin: + :path: ".symlinks/plugins/audioplayers_darwin/ios" + barcode_scan2: + :path: ".symlinks/plugins/barcode_scan2/ios" + device_info: + :path: ".symlinks/plugins/device_info/ios" + easy_app_installer: + :path: ".symlinks/plugins/easy_app_installer/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + Flutter: + :path: Flutter + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" + location: + :path: ".symlinks/plugins/location/ios" + modal_progress_hud_nsn: + :path: ".symlinks/plugins/modal_progress_hud_nsn/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/ios" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + platform_device_id: + :path: ".symlinks/plugins/platform_device_id/ios" + rive_common: + :path: ".symlinks/plugins/rive_common/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/ios" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + +SPEC CHECKSUMS: + assets_audio_player: edee322b9cb625571b830b35872ead1a295fd917 + assets_audio_player_web: 19826380c44375761aa0b9053665c1e3fbc3b86b + audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 + barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 + device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 + DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac + DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 + easy_app_installer: 29abe397da7d86721fee853281202f414373f45c + file_picker: ce3938a0df3cc1ef404671531facef740d03f920 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + location: 3a2eed4dd2fab25e7b7baf2a9efefe82b512d740 + modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e + path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 + permission_handler_apple: 8f116445eff3c0e7c65ad60f5fef5490aa94b4e4 + platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 + rive_common: 60ae7896ab40f9513974f36f015de33f70d2c5c5 + SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 + shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c + sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1 + SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.11.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1372ea9 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,583 @@ +// !$*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 */; }; + EC92729992AEB29D54ECE4AD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E04E4456FC969F34935C233 /* Pods_Runner.framework */; }; +/* End PBXBuildFile 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 = ""; }; + 2E04E4456FC969F34935C233 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4AF585336026D31B5D98E4A0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 9275E2137A20FFFC26EB3114 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + D017F5E329769A1D85398300 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EC92729992AEB29D54ECE4AD /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 53E3B75A4BA5D03DDDC74903 /* Pods */ = { + isa = PBXGroup; + children = ( + 9275E2137A20FFFC26EB3114 /* Pods-Runner.debug.xcconfig */, + 4AF585336026D31B5D98E4A0 /* Pods-Runner.release.xcconfig */, + D017F5E329769A1D85398300 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 661D3BDF849DD3A816B38E4C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2E04E4456FC969F34935C233 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 53E3B75A4BA5D03DDDC74903 /* Pods */, + 661D3BDF849DD3A816B38E4C /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + DF69B491CB3FE4E427DD5727 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + D82405DC020597FCACED184E /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 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 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 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 = ( + ); + 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"; + }; + D82405DC020597FCACED184E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DF69B491CB3FE4E427DD5727 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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 = 12.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; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 2WLSMMLG6W; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = "1.0.0 "; + PRODUCT_BUNDLE_IDENTIFIER = "unit-app"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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 = 12.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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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 = 12.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; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 2WLSMMLG6W; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = "1.0.0 "; + PRODUCT_BUNDLE_IDENTIFIER = "unit-app"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 2WLSMMLG6W; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = "1.0.0 "; + PRODUCT_BUNDLE_IDENTIFIER = "unit-app"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/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..c87d15a --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..9708f0a --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,13 @@ + + + + + + + + + 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..28c6bf0 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..2ccbfd9 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..f091b6b 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..4cde121 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..d0ef06e 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..dcdc230 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..2ccbfd9 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..c8f9ed8 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..a6d6b86 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..a6d6b86 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..75b2d16 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..c4df70d 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..6a84f41 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..d0e1f58 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..67bed1a --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,61 @@ + + + + +NSCameraUsageDescription + Camera permission is required for barcode scanning. + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Unit2 + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + unit2 + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSLocationAlwaysAndWhenInUseUsageDescription + Always and when in use! + NSLocationAlwaysUsageDescription + Can I have location always? + NSLocationUsageDescription + Older devices need location. + NSLocationWhenInUseUsageDescription + Need location when in use + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + 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/lib/bloc/docsms/docsms_bloc.dart b/lib/bloc/docsms/docsms_bloc.dart new file mode 100644 index 0000000..be473b2 --- /dev/null +++ b/lib/bloc/docsms/docsms_bloc.dart @@ -0,0 +1,28 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/docsms/docsms_service.dart'; + +import '../../model/docsms/document.dart'; + +part 'docsms_event.dart'; +part 'docsms_state.dart'; + +class DocsmsBloc extends Bloc { + DocsmsBloc() : super(DocsmsInitial()) { + Document? document; + on((event, emit)async { + emit(DocSmsLoadingState()); + try { + document = await AutoReceiveDocumentServices.instance.getDocument(event.documentId); + if(document != null){ + emit(DocumentLoaded(document: document!)); + }else{ + emit(const DocSmsErrorState(message: "Invalid Qr code")); + } + +} catch (e) { + emit(DocSmsErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/docsms/docsms_event.dart b/lib/bloc/docsms/docsms_event.dart new file mode 100644 index 0000000..190fd98 --- /dev/null +++ b/lib/bloc/docsms/docsms_event.dart @@ -0,0 +1,15 @@ +part of 'docsms_bloc.dart'; + +abstract class DocsmsEvent extends Equatable { + const DocsmsEvent(); + + @override + List get props => []; +} + +class LoadDocument extends DocsmsEvent{ +final String documentId; +const LoadDocument({required this.documentId}); + @override + List get props => []; +} diff --git a/lib/bloc/docsms/docsms_state.dart b/lib/bloc/docsms/docsms_state.dart new file mode 100644 index 0000000..c06433a --- /dev/null +++ b/lib/bloc/docsms/docsms_state.dart @@ -0,0 +1,28 @@ +part of 'docsms_bloc.dart'; + +abstract class DocsmsState extends Equatable { + const DocsmsState(); + + @override + List get props => []; +} + +class DocsmsInitial extends DocsmsState {} + +class DocSmsLoadingState extends DocsmsState{ + +} +class DocumentLoaded extends DocsmsState{ + final Document document; + const DocumentLoaded({required this.document}); + @override + List get props => [document]; + +} + +class DocSmsErrorState extends DocsmsState{ + final String message; + const DocSmsErrorState({required this.message}); + @override + List get props => [message]; +} diff --git a/lib/bloc/passo/barangay/barangay_bloc.dart b/lib/bloc/passo/barangay/barangay_bloc.dart new file mode 100644 index 0000000..f8ae3e7 --- /dev/null +++ b/lib/bloc/passo/barangay/barangay_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/barangay.dart'; +import 'package:unit2/sevices/passo/barangay.dart'; + +part 'barangay_event.dart'; +part 'barangay_state.dart'; + +class BarangayBloc extends Bloc { + BarangayBloc() : super(BarangayInitial()) { + on((event, emit) async { + emit(BarangayLoading()); + try { + final barangay = await BarangayServices.instance.fetch(event.id); + emit(BarangayLoaded(barangay)); + } catch (e) { + emit(BarangayErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/barangay/barangay_event.dart b/lib/bloc/passo/barangay/barangay_event.dart new file mode 100644 index 0000000..5012e1a --- /dev/null +++ b/lib/bloc/passo/barangay/barangay_event.dart @@ -0,0 +1,17 @@ +part of 'barangay_bloc.dart'; + +abstract class BarangayEvent extends Equatable { + const BarangayEvent(); + + @override + List get props => []; +} + +class LoadBarangay extends BarangayEvent { + final String id; + + const LoadBarangay({required this.id}); + + @override + List get props => [id]; +} diff --git a/lib/bloc/passo/barangay/barangay_state.dart b/lib/bloc/passo/barangay/barangay_state.dart new file mode 100644 index 0000000..bc36c1b --- /dev/null +++ b/lib/bloc/passo/barangay/barangay_state.dart @@ -0,0 +1,28 @@ +part of 'barangay_bloc.dart'; + +abstract class BarangayState extends Equatable { + const BarangayState(); + + @override + List get props => []; +} + +class BarangayInitial extends BarangayState {} + +class BarangayLoading extends BarangayState {} + +class BarangayLoaded extends BarangayState { + BarangayLoaded(this.brgy); + final List brgy; + + @override + List get props => [brgy]; +} + +class BarangayErrorState extends BarangayState { + BarangayErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/additional_item/additional_item_bloc.dart b/lib/bloc/passo/bulding/additional_item/additional_item_bloc.dart new file mode 100644 index 0000000..167c65e --- /dev/null +++ b/lib/bloc/passo/bulding/additional_item/additional_item_bloc.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/building/additional_items_services.dart'; + +part 'additional_item_event.dart'; +part 'additional_item_state.dart'; + +class AdditionalItemBloc + extends Bloc { + AdditionalItemBloc() : super(AdditionalItemsLoading()) { + List globalAdditionalItems = []; + on((event, emit) async { + emit(AdditionalItemsLoading()); + try { + // final tempID = await SharedPreferences.getInstance(); + // print(tempID.getInt('tempid')); + // final additionalItem = await GetAdditionalItems.getAdditionalItems( + // tempID.getInt('tempid')); + + emit(AdditionalItemsLoaded(globalAdditionalItems)); + } catch (e) { + emit(AdditionalItemsErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await AdditionalItemsServices.instance.add(event.items))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + AdditionalItems newAdditional = + AdditionalItems.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalAdditionalItems.add(newAdditional); + + emit(AdditionalItemsLoaded(globalAdditionalItems)); + } + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await AdditionalItemsServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalAdditionalItems + .removeWhere(((AdditionalItems element) => element.id == event.id)); + emit(AdditionalItemsDeletedState(success: true)); + } + }); + + on((event, emit) async { + emit(ShowAddItemsScreen()); + }); + } +} diff --git a/lib/bloc/passo/bulding/additional_item/additional_item_event.dart b/lib/bloc/passo/bulding/additional_item/additional_item_event.dart new file mode 100644 index 0000000..3922048 --- /dev/null +++ b/lib/bloc/passo/bulding/additional_item/additional_item_event.dart @@ -0,0 +1,37 @@ +part of 'additional_item_bloc.dart'; + +abstract class AdditionalItemEvent extends Equatable { + const AdditionalItemEvent(); + + @override + List get props => []; +} + +class LoadAdditionalItems extends AdditionalItemEvent { + final List items; + + const LoadAdditionalItems({this.items = const []}); + + @override + List get props => [items]; +} + +class AddAdditionalItems extends AdditionalItemEvent { + final AdditionalItems items; + + const AddAdditionalItems({required this.items}); + + @override + List get props => [items]; +} + +class DeleteAdditionalItems extends AdditionalItemEvent { + final int id; + + const DeleteAdditionalItems({required this.id}); + + @override + List get props => [id]; +} + +class ShowAdditionalItems extends AdditionalItemEvent {} diff --git a/lib/bloc/passo/bulding/additional_item/additional_item_state.dart b/lib/bloc/passo/bulding/additional_item/additional_item_state.dart new file mode 100644 index 0000000..d39fc65 --- /dev/null +++ b/lib/bloc/passo/bulding/additional_item/additional_item_state.dart @@ -0,0 +1,35 @@ +part of 'additional_item_bloc.dart'; + +abstract class AdditionalItemState extends Equatable { + const AdditionalItemState(); + + @override + List get props => []; +} + +class AdditionalItemsLoading extends AdditionalItemState {} + +class AdditionalItemsLoaded extends AdditionalItemState { + const AdditionalItemsLoaded(this.items); + final List items; + + @override + List get props => [items]; +} + +class ShowAddItemsScreen extends AdditionalItemState {} + +class AdditionalItemsErrorState extends AdditionalItemState { + const AdditionalItemsErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class AdditionalItemsDeletedState extends AdditionalItemState { + final bool success; + const AdditionalItemsDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart new file mode 100644 index 0000000..7d243c4 --- /dev/null +++ b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/building/additional_items_services.dart'; +part 'additional_items_edit_event.dart'; +part 'additional_items_edit_state.dart'; + +class AdditionalItemsEditBloc + extends Bloc { + AdditionalItemsEditBloc() : super(AdditionalItemsEditInitial()) { + List globalAdditionalItemsEdit = []; + on((event, emit) async { + if (globalAdditionalItemsEdit.isEmpty) { + emit(AdditionalItemsEditLoading()); + try { + final additionalItems = + await AdditionalItemsServices.instance.fetch(event.id); + + globalAdditionalItemsEdit + .addAll(additionalItems); // Append fetched data + emit(AdditionalItemsEditLoaded(globalAdditionalItemsEdit)); + } catch (e) { + emit(AdditionalItemsEditErrorState(e.toString())); + } + } else { + emit(AdditionalItemsEditLoaded(globalAdditionalItemsEdit)); + } + }); + + on((event, emit) async { + http.Response response = + (await AdditionalItemsServices.instance.add(event.items))!; + print(response.statusCode); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + AdditionalItems newAdditional = + AdditionalItems.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalAdditionalItemsEdit.add(newAdditional); + + emit(AdditionalItemsEditLoaded(globalAdditionalItemsEdit)); + } + }); + on((event, emit) async { + emit(ShowAddItemsScreenEdit()); + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await AdditionalItemsServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalAdditionalItemsEdit + .removeWhere(((AdditionalItems element) => element.id == event.id)); + emit(AdditionalItemsEditDeletedState(success: true)); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_event.dart b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_event.dart new file mode 100644 index 0000000..8b34fd0 --- /dev/null +++ b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_event.dart @@ -0,0 +1,38 @@ +part of 'additional_items_edit_bloc.dart'; + +abstract class AdditionalItemsEditEvent extends Equatable { + const AdditionalItemsEditEvent(); + + @override + List get props => []; +} + +class LoadAdditionalItemsEdit extends AdditionalItemsEditEvent { + final List items; + final int? id; + + const LoadAdditionalItemsEdit({required this.items, this.id}); + + @override + List get props => [items]; +} + +class AddAdditionalItemsEdit extends AdditionalItemsEditEvent { + final AdditionalItems items; + + const AddAdditionalItemsEdit({required this.items}); + + @override + List get props => [items]; +} + +class ShowAdditionalItemsEdit extends AdditionalItemsEditEvent {} + +class DeleteAdditionalItemsEdit extends AdditionalItemsEditEvent { + final int id; + + const DeleteAdditionalItemsEdit({required this.id}); + + @override + List get props => [id]; +} diff --git a/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_state.dart b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_state.dart new file mode 100644 index 0000000..4016b98 --- /dev/null +++ b/lib/bloc/passo/bulding/additional_items_edit/additional_items_edit_state.dart @@ -0,0 +1,37 @@ +part of 'additional_items_edit_bloc.dart'; + +abstract class AdditionalItemsEditState extends Equatable { + const AdditionalItemsEditState(); + + @override + List get props => []; +} + +class AdditionalItemsEditInitial extends AdditionalItemsEditState {} + +class AdditionalItemsEditLoading extends AdditionalItemsEditState {} + +class AdditionalItemsEditLoaded extends AdditionalItemsEditState { + const AdditionalItemsEditLoaded(this.items); + final List items; + + @override + List get props => [items]; +} + +class AdditionalItemsEditErrorState extends AdditionalItemsEditState { + const AdditionalItemsEditErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class ShowAddItemsScreenEdit extends AdditionalItemsEditState {} + +class AdditionalItemsEditDeletedState extends AdditionalItemsEditState { + final bool success; + const AdditionalItemsEditDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/bulding/class_components/class_components_bloc.dart b/lib/bloc/passo/bulding/class_components/class_components_bloc.dart new file mode 100644 index 0000000..084c0e3 --- /dev/null +++ b/lib/bloc/passo/bulding/class_components/class_components_bloc.dart @@ -0,0 +1,22 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/sevices/passo/class_components_services.dart'; + +part 'class_components_event.dart'; +part 'class_components_state.dart'; + +class ClassComponentsBloc + extends Bloc { + ClassComponentsBloc() : super(ClassComponentLoading()) { + on((event, emit) async { + emit(ClassComponentLoading()); + try { + final classs = await ClassComponentService.instance.fetch(); + emit(ClassComponentLoaded(classs)); + } catch (e) { + emit(ClassComponentErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/class_components/class_components_event.dart b/lib/bloc/passo/bulding/class_components/class_components_event.dart new file mode 100644 index 0000000..5efdac8 --- /dev/null +++ b/lib/bloc/passo/bulding/class_components/class_components_event.dart @@ -0,0 +1,17 @@ +part of 'class_components_bloc.dart'; + +abstract class ClassComponentsEvent extends Equatable { + const ClassComponentsEvent(); + + @override + List get props => []; +} + +class LoadClassComponents extends ClassComponentsEvent { + final List classes; + + const LoadClassComponents({this.classes = const []}); + + @override + List get props => [classes]; +} diff --git a/lib/bloc/passo/bulding/class_components/class_components_state.dart b/lib/bloc/passo/bulding/class_components/class_components_state.dart new file mode 100644 index 0000000..99beb14 --- /dev/null +++ b/lib/bloc/passo/bulding/class_components/class_components_state.dart @@ -0,0 +1,26 @@ +part of 'class_components_bloc.dart'; + +abstract class ClassComponentsState extends Equatable { + const ClassComponentsState(); + + @override + List get props => []; +} + +class ClassComponentLoading extends ClassComponentsState {} + +class ClassComponentLoaded extends ClassComponentsState { + ClassComponentLoaded(this.classes); + final List classes; + + @override + List get props => [classes]; +} + +class ClassComponentErrorState extends ClassComponentsState { + ClassComponentErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/general_description/general_description_bloc.dart b/lib/bloc/passo/bulding/general_description/general_description_bloc.dart new file mode 100644 index 0000000..0e0b213 --- /dev/null +++ b/lib/bloc/passo/bulding/general_description/general_description_bloc.dart @@ -0,0 +1,23 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/sevices/passo/building/general_description_services.dart'; + +part 'general_description_event.dart'; +part 'general_description_state.dart'; + +class GeneralDescriptionBloc + extends Bloc { + GeneralDescriptionBloc() : super(GenDescLoading()) { + on((event, emit) async { + emit(GenDescLoading()); + try { + final gendesc = + await GeneralDescriptionServices.instance.fetch(event.id); + emit(GenDescLoaded(gendesc)); + } catch (e) { + emit(GenDescErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/general_description/general_description_event.dart b/lib/bloc/passo/bulding/general_description/general_description_event.dart new file mode 100644 index 0000000..91cf288 --- /dev/null +++ b/lib/bloc/passo/bulding/general_description/general_description_event.dart @@ -0,0 +1,27 @@ +part of 'general_description_bloc.dart'; + +abstract class GeneralDescriptionEvent extends Equatable { + const GeneralDescriptionEvent(); + + @override + List get props => []; +} + +class LoadGenDesc extends GeneralDescriptionEvent { + final GeneralDesc gendesc; + final int? id; + + const LoadGenDesc({required this.gendesc, required this.id}); + + @override + List get props => [gendesc]; +} + +class UpdateGenDesc extends GeneralDescriptionEvent { + final GeneralDesc gendesc; + + const UpdateGenDesc(this.gendesc); + + @override + List get props => [gendesc]; +} diff --git a/lib/bloc/passo/bulding/general_description/general_description_state.dart b/lib/bloc/passo/bulding/general_description/general_description_state.dart new file mode 100644 index 0000000..9fb075a --- /dev/null +++ b/lib/bloc/passo/bulding/general_description/general_description_state.dart @@ -0,0 +1,26 @@ +part of 'general_description_bloc.dart'; + +abstract class GeneralDescriptionState extends Equatable { + const GeneralDescriptionState(); + + @override + List get props => []; +} + +class GenDescLoading extends GeneralDescriptionState {} + +class GenDescLoaded extends GeneralDescriptionState { + GenDescLoaded(this.gendesc); + final GeneralDesc gendesc; + + @override + List get props => [gendesc]; +} + +class GenDescErrorState extends GeneralDescriptionState { + GenDescErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/landref/landref_bloc.dart b/lib/bloc/passo/bulding/landref/landref_bloc.dart new file mode 100644 index 0000000..99fcc1b --- /dev/null +++ b/lib/bloc/passo/bulding/landref/landref_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/sevices/passo/building/landref_services.dart'; + +part 'landref_event.dart'; +part 'landref_state.dart'; + +class LandrefBloc extends Bloc { + LandrefBloc() : super(LandrefLoading()) { + on((event, emit) async { + emit(LandrefLoading()); + try { + final landRef = await LandRefServices.instance.fetch(event.id); + emit(LandrefLoaded(landRef)); + } catch (e) { + emit(LandrefErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/landref/landref_event.dart b/lib/bloc/passo/bulding/landref/landref_event.dart new file mode 100644 index 0000000..aaf2e78 --- /dev/null +++ b/lib/bloc/passo/bulding/landref/landref_event.dart @@ -0,0 +1,27 @@ +part of 'landref_bloc.dart'; + +abstract class LandrefEvent extends Equatable { + const LandrefEvent(); + + @override + List get props => []; +} + +class LoadLandref extends LandrefEvent { + final LandRef landRef; + final int? id; + + const LoadLandref({required this.landRef, required this.id}); + + @override + List get props => [landRef]; +} + +class UpdateLandref extends LandrefEvent { + final LandRef landRef; + + const UpdateLandref(this.landRef); + + @override + List get props => [landRef]; +} diff --git a/lib/bloc/passo/bulding/landref/landref_state.dart b/lib/bloc/passo/bulding/landref/landref_state.dart new file mode 100644 index 0000000..0832733 --- /dev/null +++ b/lib/bloc/passo/bulding/landref/landref_state.dart @@ -0,0 +1,26 @@ +part of 'landref_bloc.dart'; + +abstract class LandrefState extends Equatable { + const LandrefState(); + + @override + List get props => []; +} + +class LandrefLoading extends LandrefState {} + +class LandrefLoaded extends LandrefState { + LandrefLoaded(this.landRef); + final LandRef landRef; + + @override + List get props => [landRef]; +} + +class LandrefErrorState extends LandrefState { + LandrefErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/location/location_bloc.dart b/lib/bloc/passo/bulding/location/location_bloc.dart new file mode 100644 index 0000000..20aff1b --- /dev/null +++ b/lib/bloc/passo/bulding/location/location_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/sevices/passo/building/location_landref_services.dart'; + +part 'location_event.dart'; +part 'location_state.dart'; + +class LocationBloc extends Bloc { + LocationBloc() : super(LocationLoading()) { + on((event, emit) async { + emit(LocationLoading()); + try { + final bldgloc = await LocationLandrefServices.instance.fetch(event.id); + emit(LocationLoaded(bldgloc)); + } catch (e) { + emit(LocationErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/location/location_event.dart b/lib/bloc/passo/bulding/location/location_event.dart new file mode 100644 index 0000000..008f6db --- /dev/null +++ b/lib/bloc/passo/bulding/location/location_event.dart @@ -0,0 +1,27 @@ +part of 'location_bloc.dart'; + +abstract class LocationEvent extends Equatable { + const LocationEvent(); + + @override + List get props => []; +} + +class LoadLocation extends LocationEvent { + final BldgLoc bldgloc; + final int? id; + + const LoadLocation({required this.bldgloc, required this.id}); + + @override + List get props => [bldgloc]; +} + +class UpdateLocation extends LocationEvent { + final BldgLoc bldgloc; + + const UpdateLocation(this.bldgloc); + + @override + List get props => [bldgloc]; +} diff --git a/lib/bloc/passo/bulding/location/location_state.dart b/lib/bloc/passo/bulding/location/location_state.dart new file mode 100644 index 0000000..8281995 --- /dev/null +++ b/lib/bloc/passo/bulding/location/location_state.dart @@ -0,0 +1,26 @@ +part of 'location_bloc.dart'; + +abstract class LocationState extends Equatable { + const LocationState(); + + @override + List get props => []; +} + +class LocationLoading extends LocationState {} + +class LocationLoaded extends LocationState { + LocationLoaded(this.bldgloc); + final BldgLoc bldgloc; + + @override + List get props => [bldgloc]; +} + +class LocationErrorState extends LocationState { + LocationErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart new file mode 100644 index 0000000..e7953c2 --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart @@ -0,0 +1,45 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/building/property_appraisal_services.dart'; + +part 'property_appraisal_event.dart'; +part 'property_appraisal_state.dart'; + +class PropertyAppraisalBloc + extends Bloc { + PropertyAppraisalBloc() : super(PropertyAppraisalInitial()) { + List globalPropertyAppraisal = []; + on((event, emit) async { + emit(PropertyAppraisalLoading()); + try { + final appraisal = await PropertyAppraisalServices.instance.fetch(); + + emit(PropertyAppraisalLoaded(appraisal)); + } catch (e) { + emit(PropertyAppraisalErrorState(e.toString())); + } + }); + on((event, emit) async { + final tempID = await SharedPreferences.getInstance(); + + http.Response response = (await PropertyAppraisalServices.instance + .update(event.appraisal, tempID.getInt('tempid')! - 1))!; + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + PropertyAppraisal newAppraisal = + PropertyAppraisal.fromJson(jsonResponse['data']); + print("PA"); + print(newAppraisal); + print(response.statusCode); + + emit(PropertyAppraisalLoaded(newAppraisal)); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/property_appraisal/property_appraisal_event.dart b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_event.dart new file mode 100644 index 0000000..8eda5e3 --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_event.dart @@ -0,0 +1,26 @@ +part of 'property_appraisal_bloc.dart'; + +abstract class PropertyAppraisalEvent extends Equatable { + const PropertyAppraisalEvent(); + + @override + List get props => []; +} + +class LoadPropertyAppraisal extends PropertyAppraisalEvent { + final PropertyAppraisal appraisal; + + const LoadPropertyAppraisal({required this.appraisal}); + + @override + List get props => [appraisal]; +} + +class AddPropertyAppraisal extends PropertyAppraisalEvent { + final PropertyAppraisal appraisal; + + const AddPropertyAppraisal({required this.appraisal}); + + @override + List get props => [appraisal]; +} diff --git a/lib/bloc/passo/bulding/property_appraisal/property_appraisal_state.dart b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_state.dart new file mode 100644 index 0000000..2010d45 --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal/property_appraisal_state.dart @@ -0,0 +1,28 @@ +part of 'property_appraisal_bloc.dart'; + +abstract class PropertyAppraisalState extends Equatable { + const PropertyAppraisalState(); + + @override + List get props => []; +} + +class PropertyAppraisalInitial extends PropertyAppraisalState {} + +class PropertyAppraisalLoading extends PropertyAppraisalState {} + +class PropertyAppraisalLoaded extends PropertyAppraisalState { + PropertyAppraisalLoaded(this.appraisal); + final PropertyAppraisal appraisal; + + @override + List get props => [appraisal]; +} + +class PropertyAppraisalErrorState extends PropertyAppraisalState { + PropertyAppraisalErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart new file mode 100644 index 0000000..33e6443 --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/property_appraisal_edit.dart'; +import 'package:unit2/sevices/passo/building/property_appraisal_services.dart'; +import 'package:http/http.dart' as http; + +part 'property_appraisal_edit_event.dart'; +part 'property_appraisal_edit_state.dart'; + +class PropertyAppraisalEditBloc + extends Bloc { + PropertyAppraisalEditBloc() : super(PropertyAppraisalEditLoading()) { + on((event, emit) async { + emit(PropertyAppraisalEditLoading()); + try { + final appraisalEdit = + await PropertyAppraisalServices.instance.fetchEdit(event.id); + emit(PropertyAppraisalEditLoaded(appraisalEdit)); + } catch (e) { + emit(PropertyAppraisalEditErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = (await PropertyAppraisalServices.instance + .updateAppraisal(event.appraisalEdit!, event.id))!; + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + PropertyAppraisalEdit newAppraisal = + PropertyAppraisalEdit.fromJson(jsonResponse['data']); + print(response.statusCode); + emit(PropertyAppraisalEditLoaded(newAppraisal)); + + // emit(PropertyAppraisalLoaded(globalPropertyAppraisal)); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_event.dart b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_event.dart new file mode 100644 index 0000000..c1b5d75 --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_event.dart @@ -0,0 +1,28 @@ +part of 'property_appraisal_edit_bloc.dart'; + +abstract class PropertyAppraisalEditEvent extends Equatable { + const PropertyAppraisalEditEvent(); + + @override + List get props => []; +} + +class LoadPropertyAppraisalEdit extends PropertyAppraisalEditEvent { + final PropertyAppraisalEdit appraisalEdit; + final int? id; + + const LoadPropertyAppraisalEdit( + {required this.appraisalEdit, required this.id}); + + @override + List get props => [appraisalEdit]; +} + +class UpdatePropertyAppraisalEdit extends PropertyAppraisalEditEvent { + final PropertyAppraisalEdit? appraisalEdit; + final int? id; + const UpdatePropertyAppraisalEdit({this.appraisalEdit, required this.id}); + + @override + List get props => [appraisalEdit!]; +} diff --git a/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_state.dart b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_state.dart new file mode 100644 index 0000000..c6b812e --- /dev/null +++ b/lib/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_state.dart @@ -0,0 +1,26 @@ +part of 'property_appraisal_edit_bloc.dart'; + +abstract class PropertyAppraisalEditState extends Equatable { + const PropertyAppraisalEditState(); + + @override + List get props => []; +} + +class PropertyAppraisalEditLoading extends PropertyAppraisalEditState {} + +class PropertyAppraisalEditLoaded extends PropertyAppraisalEditState { + PropertyAppraisalEditLoaded(this.appraisalEdit); + final PropertyAppraisalEdit appraisalEdit; + + @override + List get props => [appraisalEdit]; +} + +class PropertyAppraisalEditErrorState extends PropertyAppraisalEditState { + PropertyAppraisalEditErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart b/lib/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart new file mode 100644 index 0000000..9bf078b --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/property_assessment.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/building/property_assessment_services.dart'; + +part 'property_assessment_event.dart'; +part 'property_assessment_state.dart'; + +class PropertyAssessmentBloc + extends Bloc { + PropertyAssessmentBloc() : super(PropertyAssessmentInitial()) { + List globalPropertyAssessment = []; + on((event, emit) async { + emit(PropertyAssessmentLoading()); + try { + final tempID = await SharedPreferences.getInstance(); + + final assessments = await PropertyAssessmentServices.instance + .fetch(tempID.getInt('tempid')! + 1); + + emit(PropertyAssessmentLoaded(assessments)); + } catch (e) { + emit(PropertyAssessmentErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await PropertyAssessmentServices.instance.add(event.assessments))!; + print('Assessment'); + print(response.statusCode); + print(response.body); + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + PropertyAssessment newAssessment = + PropertyAssessment.fromJson(jsonResponse['data']); + + globalPropertyAssessment.add(newAssessment); + + emit(PropertyAssessmentLoaded(globalPropertyAssessment)); + } + }); + on((event, emit) async { + final tempID = await SharedPreferences.getInstance(); + final tempID2 = tempID.getInt('tempid')! - 1; + http.Response response = (await PropertyAssessmentServices.instance + .update(event.assessment, tempID2))!; + print('assessment'); + print(response.statusCode); + print(response.body); + // if (response.statusCode == 201) { + // final faas = await PropertyInfoRepository.getUsers(); + // emit(FaasLoaded(faas)); + // } + }); + } +} diff --git a/lib/bloc/passo/bulding/property_assessment/property_assessment_event.dart b/lib/bloc/passo/bulding/property_assessment/property_assessment_event.dart new file mode 100644 index 0000000..3c7621c --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment/property_assessment_event.dart @@ -0,0 +1,38 @@ +part of 'property_assessment_bloc.dart'; + +abstract class PropertyAssessmentEvent extends Equatable { + const PropertyAssessmentEvent(); + + @override + List get props => []; +} + +class LoadPropertyAssessment extends PropertyAssessmentEvent { + final List assessments; + + const LoadPropertyAssessment( + {this.assessments = const []}); + + @override + List get props => [assessments]; +} + +class AddPropertyAssessment extends PropertyAssessmentEvent { + final PropertyAssessment assessments; + + const AddPropertyAssessment({required this.assessments}); + + @override + List get props => [assessments]; +} + +class UpdatePropertyAssessment extends PropertyAssessmentEvent { + // ignore: non_constant_identifier_names + final PropertyAssessment assessment; + + // ignore: non_constant_identifier_names + const UpdatePropertyAssessment({required this.assessment}); + + @override + List get props => [assessment]; +} diff --git a/lib/bloc/passo/bulding/property_assessment/property_assessment_state.dart b/lib/bloc/passo/bulding/property_assessment/property_assessment_state.dart new file mode 100644 index 0000000..6c88b75 --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment/property_assessment_state.dart @@ -0,0 +1,28 @@ +part of 'property_assessment_bloc.dart'; + +abstract class PropertyAssessmentState extends Equatable { + const PropertyAssessmentState(); + + @override + List get props => []; +} + +class PropertyAssessmentInitial extends PropertyAssessmentState {} + +class PropertyAssessmentLoading extends PropertyAssessmentState {} + +class PropertyAssessmentLoaded extends PropertyAssessmentState { + PropertyAssessmentLoaded(this.assessments); + final List assessments; + + @override + List get props => [assessments]; +} + +class PropertyAssessmentErrorState extends PropertyAssessmentState { + PropertyAssessmentErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart new file mode 100644 index 0000000..517d0fb --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/building/property_assessment_services.dart'; +part 'property_assessment_edit_event.dart'; +part 'property_assessment_edit_state.dart'; + +class PropertyAssessmentEditBloc + extends Bloc { + PropertyAssessmentEdit globalPropertyAssessmentEdit; + PropertyAssessmentEditBloc() + : globalPropertyAssessmentEdit = PropertyAssessmentEdit(), + super(PropertyAssessmentEditInitial()) { + on((event, emit) async { + emit(PropertyAssessmentEditLoading()); + try { + final tempID = await SharedPreferences.getInstance(); + + final assessments = + await PropertyAssessmentServices.instance.fetchEdit(event.id); + + emit(PropertyAssessmentEditLoaded(assessments)); + } catch (e) { + emit(PropertyAssessmentEditErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = (await PropertyAssessmentServices.instance + .addEdit(event.assessmentsEdit))!; + print('Assessment'); + print(response.statusCode); + print(response.body); + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + PropertyAssessmentEdit newAssessment = + PropertyAssessmentEdit.fromJson(jsonResponse['data']); + + globalPropertyAssessmentEdit = newAssessment; + + emit(PropertyAssessmentEditLoaded(globalPropertyAssessmentEdit)); + } + }); + on((event, emit) async { + final tempID = await SharedPreferences.getInstance(); + final tempID2 = tempID.getInt('tempid')! - 1; + http.Response response = (await PropertyAssessmentServices.instance + .updateEdit(event.assessmentsEdit, tempID2))!; + print('assessment'); + print(response.statusCode); + print(response.body); + // if (response.statusCode == 201) { + // final faas = await PropertyInfoRepository.getUsers(); + // emit(FaasLoaded(faas)); + // } + }); + } +} diff --git a/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_event.dart b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_event.dart new file mode 100644 index 0000000..4d478f4 --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_event.dart @@ -0,0 +1,39 @@ +part of 'property_assessment_edit_bloc.dart'; + +abstract class PropertyAssessmentEditEvent extends Equatable { + const PropertyAssessmentEditEvent(); + + @override + List get props => []; +} + +class LoadPropertyAssessmentEdit extends PropertyAssessmentEditEvent { + final PropertyAssessmentEdit assessmentsEdit; + final int? id; + + const LoadPropertyAssessmentEdit( + {required this.assessmentsEdit, required this.id}); + + @override + List get props => [assessmentsEdit]; +} + +class AddPropertyAssessmentEdit extends PropertyAssessmentEditEvent { + final PropertyAssessmentEdit assessmentsEdit; + + const AddPropertyAssessmentEdit({required this.assessmentsEdit}); + + @override + List get props => [assessmentsEdit]; +} + +class UpdatePropertyAssessmentEdit extends PropertyAssessmentEditEvent { + // ignore: non_constant_identifier_names + final PropertyAssessmentEdit assessmentsEdit; + + // ignore: non_constant_identifier_names + const UpdatePropertyAssessmentEdit({required this.assessmentsEdit}); + + @override + List get props => [assessmentsEdit]; +} diff --git a/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_state.dart b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_state.dart new file mode 100644 index 0000000..70d41a8 --- /dev/null +++ b/lib/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_state.dart @@ -0,0 +1,28 @@ +part of 'property_assessment_edit_bloc.dart'; + +abstract class PropertyAssessmentEditState extends Equatable { + const PropertyAssessmentEditState(); + + @override + List get props => []; +} + +class PropertyAssessmentEditInitial extends PropertyAssessmentEditState {} + +class PropertyAssessmentEditLoading extends PropertyAssessmentEditState {} + +class PropertyAssessmentEditLoaded extends PropertyAssessmentEditState { + PropertyAssessmentEditLoaded(this.assessmentsEdit); + final PropertyAssessmentEdit assessmentsEdit; + + @override + List get props => [assessmentsEdit]; +} + +class PropertyAssessmentEditErrorState extends PropertyAssessmentEditState { + PropertyAssessmentEditErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/property_info/property_info_bloc.dart b/lib/bloc/passo/bulding/property_info/property_info_bloc.dart new file mode 100644 index 0000000..37a75b9 --- /dev/null +++ b/lib/bloc/passo/bulding/property_info/property_info_bloc.dart @@ -0,0 +1,112 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/sevices/passo/building/general_description_services.dart'; +import 'package:unit2/sevices/passo/building/property_info_services.dart'; +import 'package:http/http.dart' as http; + +import 'package:unit2/sevices/passo/building/structural_material_services.dart'; + +part 'property_info_event.dart'; +part 'property_info_state.dart'; + +class PropertyInfoBloc extends Bloc { + PropertyInfoBloc() : super(PropertyInfoLoading()) { + on((event, emit) async { + emit(PropertyInfoLoading()); + try { + final property_info = await PropertyInfoService.instance.fetch(); + emit(PropertyInfoLoaded(property_info)); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + }); + on((event, emit) async { + final state = this.state; + try { + http.Response response = + (await PropertyInfoService.instance.add(event.property_info))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + final tempID = await SharedPreferences.getInstance(); + print(jsonResponse['data']); + await tempID.setInt('tempid', jsonResponse['data']['id'] + 1); + final faas = await PropertyInfoService.instance.fetch(); + emit(PropertyInfoLoaded(faas)); + } + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + }); + on(((event, emit) async { + final state = this.state; + try { + http.Response response = (await PropertyInfoService.instance + .update(event.property_info, event.property_info.id))!; + print('property_info'); + print(response.body); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + })); + on(((event, emit) async { + final state = this.state; + try { + http.Response response = (await PropertyInfoService.instance + .updateBldg(event.bldg_loc, event.bldg_loc.id))!; + print('bldgLoc'); + print(response.statusCode); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + })); + on( + (event, emit) async { + final state = this.state; + try { + http.Response response = (await PropertyInfoService.instance + .updateLandRef(event.land_ref, event.land_ref.id))!; + print('landref'); + print(response.body); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + }, + ); + + on((event, emit) async { + final state = this.state; + try { + http.Response response = (await PropertyInfoService.instance + .updateGenDesc(event.gen_desc, event.gen_desc.id))!; + print('genDesc'); + print(response.body); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + }); + + on((event, emit) async { + final state = this.state; + try { + final tempID = await SharedPreferences.getInstance(); + print(tempID.getInt('tempid')! - 1); + http.Response response = (await StrucMaterialServices.instance + .update(event.data, event.data.id))!; + print('struc Material'); + print(response.body); + } catch (e) { + emit(PropertyInfoErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/property_info/property_info_event.dart b/lib/bloc/passo/bulding/property_info/property_info_event.dart new file mode 100644 index 0000000..0b678c8 --- /dev/null +++ b/lib/bloc/passo/bulding/property_info/property_info_event.dart @@ -0,0 +1,75 @@ +part of 'property_info_bloc.dart'; + +abstract class PropertyInfoEvent extends Equatable { + const PropertyInfoEvent(); + + @override + List get props => []; +} + +class LoadPropertyInfo extends PropertyInfoEvent { + final List property_info; + + const LoadPropertyInfo({this.property_info = const []}); + + @override + List get props => [property_info]; +} + +class AddPropertyInfo extends PropertyInfoEvent { + final PropertyInfo property_info; + + const AddPropertyInfo({required this.property_info}); + + @override + List get props => [property_info]; +} + +class UpdatPropertyInfo extends PropertyInfoEvent { + // ignore: non_constant_identifier_names + final PropertyInfo property_info; + + // ignore: non_constant_identifier_names + const UpdatPropertyInfo({required this.property_info}); + + @override + List get props => [property_info]; +} + +class UpdateBldgLoc extends PropertyInfoEvent { + // ignore: non_constant_identifier_names + final BldgLoc bldg_loc; + + // ignore: non_constant_identifier_names + const UpdateBldgLoc({required this.bldg_loc}); + + @override + List get props => [bldg_loc]; +} + +class UpdateLandRef extends PropertyInfoEvent { + final LandRef land_ref; + + const UpdateLandRef({required this.land_ref}); + + @override + List get props => [land_ref]; +} + +class UpdateGeneralDesc extends PropertyInfoEvent { + final GeneralDesc gen_desc; + + const UpdateGeneralDesc({required this.gen_desc}); + + @override + List get props => [gen_desc]; +} + +class UpdateStrucMaterials extends PropertyInfoEvent { + final StructureMaterialsII data; + + const UpdateStrucMaterials({required this.data}); + + @override + List get props => [data]; +} diff --git a/lib/bloc/passo/bulding/property_info/property_info_state.dart b/lib/bloc/passo/bulding/property_info/property_info_state.dart new file mode 100644 index 0000000..b325da5 --- /dev/null +++ b/lib/bloc/passo/bulding/property_info/property_info_state.dart @@ -0,0 +1,26 @@ +part of 'property_info_bloc.dart'; + +abstract class PropertyInfoState extends Equatable { + const PropertyInfoState(); + + @override + List get props => []; +} + +class PropertyInfoLoading extends PropertyInfoState {} + +class PropertyInfoLoaded extends PropertyInfoState { + const PropertyInfoLoaded(this.property_info); + final List property_info; + + @override + List get props => [property_info]; +} + +class PropertyInfoErrorState extends PropertyInfoState { + const PropertyInfoErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/structural_material/structural_material_bloc.dart b/lib/bloc/passo/bulding/structural_material/structural_material_bloc.dart new file mode 100644 index 0000000..4d58461 --- /dev/null +++ b/lib/bloc/passo/bulding/structural_material/structural_material_bloc.dart @@ -0,0 +1,23 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/model/passo/structureMaterial.dart'; +import 'package:unit2/sevices/passo/building/structural_material_services.dart'; + +part 'structural_material_event.dart'; +part 'structural_material_state.dart'; + +class StructuralMaterialBloc + extends Bloc { + StructuralMaterialBloc() : super(StructuralMaterialInitial()) { + on((event, emit) async { + emit(StructuralMaterialsLoading()); + try { + final structure = await StrucMaterialServices.instance.fetch(event.id); + emit(StructuralMaterialsLoaded(structure)); + } catch (e) { + emit(StructuralMaterialsErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/structural_material/structural_material_event.dart b/lib/bloc/passo/bulding/structural_material/structural_material_event.dart new file mode 100644 index 0000000..f54301a --- /dev/null +++ b/lib/bloc/passo/bulding/structural_material/structural_material_event.dart @@ -0,0 +1,18 @@ +part of 'structural_material_bloc.dart'; + +class StructuralMaterialEvent extends Equatable { + const StructuralMaterialEvent(); + + @override + List get props => []; +} + +class LoadStructuralMaterial extends StructuralMaterialEvent { + final StructureMaterials structure; + final int? id; + + const LoadStructuralMaterial({required this.structure, required this.id}); + + @override + List get props => [structure]; +} diff --git a/lib/bloc/passo/bulding/structural_material/structural_material_state.dart b/lib/bloc/passo/bulding/structural_material/structural_material_state.dart new file mode 100644 index 0000000..b5c0609 --- /dev/null +++ b/lib/bloc/passo/bulding/structural_material/structural_material_state.dart @@ -0,0 +1,28 @@ +part of 'structural_material_bloc.dart'; + +class StructuralMaterialState extends Equatable { + const StructuralMaterialState(); + + @override + List get props => []; +} + +class StructuralMaterialInitial extends StructuralMaterialState {} + +class StructuralMaterialsLoading extends StructuralMaterialState {} + +class StructuralMaterialsLoaded extends StructuralMaterialState { + const StructuralMaterialsLoaded(this.structure); + final StructureMaterials structure; + + @override + List get props => [structure]; +} + +class StructuralMaterialsErrorState extends StructuralMaterialState { + const StructuralMaterialsErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart b/lib/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart new file mode 100644 index 0000000..02f0650 --- /dev/null +++ b/lib/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/sevices/passo/unit_construct_services.dart'; + +part 'unit_construct_event.dart'; +part 'unit_construct_state.dart'; + +class UnitConstructBloc extends Bloc { + UnitConstructBloc() : super(UnitConstructLoading()) { + on((event, emit) async { + emit(UnitConstructLoading()); + try { + final unit = await UnitConstructService.instance.fetch(); + emit(UnitConstructLoaded(unit)); + } catch (e) { + emit(UnitConstructErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/bulding/unit_construct/unit_construct_event.dart b/lib/bloc/passo/bulding/unit_construct/unit_construct_event.dart new file mode 100644 index 0000000..dfd9e83 --- /dev/null +++ b/lib/bloc/passo/bulding/unit_construct/unit_construct_event.dart @@ -0,0 +1,17 @@ +part of 'unit_construct_bloc.dart'; + +abstract class UnitConstructEvent extends Equatable { + const UnitConstructEvent(); + + @override + List get props => []; +} + +class LoadUnitConstruct extends UnitConstructEvent { + final List unit; + + const LoadUnitConstruct({this.unit = const []}); + + @override + List get props => [unit]; +} diff --git a/lib/bloc/passo/bulding/unit_construct/unit_construct_state.dart b/lib/bloc/passo/bulding/unit_construct/unit_construct_state.dart new file mode 100644 index 0000000..51adea0 --- /dev/null +++ b/lib/bloc/passo/bulding/unit_construct/unit_construct_state.dart @@ -0,0 +1,26 @@ +part of 'unit_construct_bloc.dart'; + +abstract class UnitConstructState extends Equatable { + const UnitConstructState(); + + @override + List get props => []; +} + +class UnitConstructLoading extends UnitConstructState {} + +class UnitConstructLoaded extends UnitConstructState { + UnitConstructLoaded(this.unit); + final List unit; + + @override + List get props => [unit]; +} + +class UnitConstructErrorState extends UnitConstructState { + UnitConstructErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart b/lib/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart new file mode 100644 index 0000000..b542dbf --- /dev/null +++ b/lib/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/land/land_appraisal.dart'; +part 'land_appraisal_event.dart'; +part 'land_appraisal_state.dart'; + +class LandAppraisalBloc extends Bloc { + LandAppraisalBloc() : super(LandAppraisalLoading()) { + List globalLandAppraisal = []; + on((event, emit) async { + emit(LandAppraisalLoading()); + try { + final tempID = await SharedPreferences.getInstance(); + print(tempID.getInt('landid')); + final additionalItems = + await LandAppraisalServices.instance.fetch(tempID.getInt('tempid')); + + globalLandAppraisal + .addAll(additionalItems); // Append all items to the list + emit(LandAppraisalLoaded(globalLandAppraisal)); + } catch (e) { + emit(LandAppraisalErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await LandAppraisalServices.instance.add(event.land_appr))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + LandAppr newAdditional = LandAppr.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalLandAppraisal.add(newAdditional); + + emit(LandAppraisalLoaded(globalLandAppraisal)); + } + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await LandAppraisalServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalLandAppraisal + .removeWhere(((LandAppr element) => element.id == event.id)); + emit(LandAppraisalDeletedState(success: true)); + } + }); + + on((event, emit) async { + emit(ShowAddLandAppraisalScreen()); + }); + } +} diff --git a/lib/bloc/passo/land/land_appraisal/land_appraisal_event.dart b/lib/bloc/passo/land/land_appraisal/land_appraisal_event.dart new file mode 100644 index 0000000..50c1007 --- /dev/null +++ b/lib/bloc/passo/land/land_appraisal/land_appraisal_event.dart @@ -0,0 +1,37 @@ +part of 'land_appraisal_bloc.dart'; + +class LandAppraisalEvent extends Equatable { + const LandAppraisalEvent(); + + @override + List get props => []; +} + +class LoadLandAppraisal extends LandAppraisalEvent { + final List land_appr; + + const LoadLandAppraisal({this.land_appr = const []}); + + @override + List get props => [land_appr]; +} + +class AddLandAppraisal extends LandAppraisalEvent { + final LandAppr land_appr; + + const AddLandAppraisal({required this.land_appr}); + + @override + List get props => [land_appr]; +} + +class DeleteLandAppraisal extends LandAppraisalEvent { + final int id; + + const DeleteLandAppraisal({required this.id}); + + @override + List get props => [id]; +} + +class ShowLandAppraisal extends LandAppraisalEvent {} diff --git a/lib/bloc/passo/land/land_appraisal/land_appraisal_state.dart b/lib/bloc/passo/land/land_appraisal/land_appraisal_state.dart new file mode 100644 index 0000000..d037ad6 --- /dev/null +++ b/lib/bloc/passo/land/land_appraisal/land_appraisal_state.dart @@ -0,0 +1,35 @@ +part of 'land_appraisal_bloc.dart'; + +class LandAppraisalState extends Equatable { + const LandAppraisalState(); + + @override + List get props => []; +} + +class LandAppraisalLoading extends LandAppraisalState {} + +class LandAppraisalLoaded extends LandAppraisalState { + const LandAppraisalLoaded(this.land_appr); + final List land_appr; + + @override + List get props => [land_appr]; +} + +class ShowAddLandAppraisalScreen extends LandAppraisalState {} + +class LandAppraisalErrorState extends LandAppraisalState { + const LandAppraisalErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class LandAppraisalDeletedState extends LandAppraisalState { + final bool success; + const LandAppraisalDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/land/land_classification/land_classification_bloc.dart b/lib/bloc/passo/land/land_classification/land_classification_bloc.dart new file mode 100644 index 0000000..cdecd0f --- /dev/null +++ b/lib/bloc/passo/land/land_classification/land_classification_bloc.dart @@ -0,0 +1,22 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/land_classification.dart'; +import 'package:unit2/sevices/passo/land/land_classification.dart'; + +part 'land_classification_event.dart'; +part 'land_classification_state.dart'; + +class LandClassificationBloc + extends Bloc { + LandClassificationBloc() : super(LandClassificationLoading()) { + on((event, emit) async { + emit(LandClassificationLoading()); + try { + final classs = await LandClassificationService.instance.fetch(); + emit(LandClassificationLoaded(classs)); + } catch (e) { + emit(LandClassificationErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/land/land_classification/land_classification_event.dart b/lib/bloc/passo/land/land_classification/land_classification_event.dart new file mode 100644 index 0000000..d0cea3e --- /dev/null +++ b/lib/bloc/passo/land/land_classification/land_classification_event.dart @@ -0,0 +1,18 @@ +part of 'land_classification_bloc.dart'; + +class LandClassificationEvent extends Equatable { + const LandClassificationEvent(); + + @override + List get props => []; +} + +class LoadLandClassification extends LandClassificationEvent { + final List land_classification; + + const LoadLandClassification( + {this.land_classification = const []}); + + @override + List get props => [land_classification]; +} diff --git a/lib/bloc/passo/land/land_classification/land_classification_state.dart b/lib/bloc/passo/land/land_classification/land_classification_state.dart new file mode 100644 index 0000000..eeef362 --- /dev/null +++ b/lib/bloc/passo/land/land_classification/land_classification_state.dart @@ -0,0 +1,26 @@ +part of 'land_classification_bloc.dart'; + +class LandClassificationState extends Equatable { + const LandClassificationState(); + + @override + List get props => []; +} + +class LandClassificationLoading extends LandClassificationState {} + +class LandClassificationLoaded extends LandClassificationState { + LandClassificationLoaded(this.land_classification); + final List land_classification; + + @override + List get props => [land_classification]; +} + +class LandClassificationErrorState extends LandClassificationState { + LandClassificationErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_ext/land_ext_bloc.dart b/lib/bloc/passo/land/land_ext/land_ext_bloc.dart new file mode 100644 index 0000000..7fa7292 --- /dev/null +++ b/lib/bloc/passo/land/land_ext/land_ext_bloc.dart @@ -0,0 +1,57 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/land_ext.dart'; +import 'package:unit2/sevices/passo/land/land_ext.dart'; +import 'package:http/http.dart' as http; +part 'land_ext_event.dart'; +part 'land_ext_state.dart'; + +class LandExtBloc extends Bloc { + LandExtBloc() : super(LandExtInitial()) { + List globalLandExt = []; + on((event, emit) async { + emit(LandExtLoading()); + try { + final tempID = await SharedPreferences.getInstance(); + + final assessments = + await LandExtServices.instance.fetch(tempID.getInt('tempid')! + 1); + + emit(LandExtLoaded(assessments)); + } catch (e) { + emit(LandExtErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await LandExtServices.instance.add(event.landext))!; + print('landext'); + print(response.statusCode); + print(response.body); + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + LandExt newAssessment = LandExt.fromJson(jsonResponse['data']); + + globalLandExt.add(newAssessment); + + emit(LandExtLoaded(globalLandExt)); + } + }); + on((event, emit) async { + final tempID = await SharedPreferences.getInstance(); + final tempID2 = tempID.getInt('tempid')! - 1; + http.Response response = + (await LandExtServices.instance.update(event.landext, tempID2))!; + print('landext'); + print(response.statusCode); + print(response.body); + // if (response.statusCode == 201) { + // final faas = await PropertyInfoRepository.getUsers(); + // emit(FaasLoaded(faas)); + // } + }); + } +} diff --git a/lib/bloc/passo/land/land_ext/land_ext_event.dart b/lib/bloc/passo/land/land_ext/land_ext_event.dart new file mode 100644 index 0000000..8aef275 --- /dev/null +++ b/lib/bloc/passo/land/land_ext/land_ext_event.dart @@ -0,0 +1,37 @@ +part of 'land_ext_bloc.dart'; + +class LandExtEvent extends Equatable { + const LandExtEvent(); + + @override + List get props => []; +} + +class LoadLandExt extends LandExtEvent { + final List landext; + + const LoadLandExt({this.landext = const []}); + + @override + List get props => [landext]; +} + +class AddLandExt extends LandExtEvent { + final LandExt landext; + + const AddLandExt({required this.landext}); + + @override + List get props => [landext]; +} + +class UpdateLandExt extends LandExtEvent { + // ignore: non_constant_identifier_names + final LandExt landext; + + // ignore: non_constant_identifier_names + const UpdateLandExt({required this.landext}); + + @override + List get props => [landext]; +} diff --git a/lib/bloc/passo/land/land_ext/land_ext_state.dart b/lib/bloc/passo/land/land_ext/land_ext_state.dart new file mode 100644 index 0000000..c59eec3 --- /dev/null +++ b/lib/bloc/passo/land/land_ext/land_ext_state.dart @@ -0,0 +1,28 @@ +part of 'land_ext_bloc.dart'; + +class LandExtState extends Equatable { + const LandExtState(); + + @override + List get props => []; +} + +class LandExtInitial extends LandExtState {} + +class LandExtLoading extends LandExtState {} + +class LandExtLoaded extends LandExtState { + LandExtLoaded(this.landext); + final List landext; + + @override + List get props => [landext]; +} + +class LandExtErrorState extends LandExtState { + LandExtErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart new file mode 100644 index 0000000..08d18b0 --- /dev/null +++ b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/land_property_assessment.dart'; +import 'package:unit2/sevices/passo/land/land_property_assessment.dart'; +import 'package:http/http.dart' as http; + +part 'land_property_assessment_event.dart'; +part 'land_property_assessment_state.dart'; + +class LandPropertyAssessmentBloc + extends Bloc { + LandPropertyAssessmentBloc() : super(LandPropertyAssessmentLoading()) { + List globalLandPropertyAssessment = []; + on((event, emit) async { + emit(LandPropertyAssessmentLoading()); + try { + final tempID = await SharedPreferences.getInstance(); + print(tempID.getInt('landid')); + final additionalItems = await LandPropertyAssessmentServices.instance + .fetch(tempID.getInt('tempid')); + + globalLandPropertyAssessment + .addAll(additionalItems); // Append all items to the list + emit(LandPropertyAssessmentLoaded(globalLandPropertyAssessment)); + } catch (e) { + emit(LandPropertyAssessmentErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = (await LandPropertyAssessmentServices.instance + .add(event.assessment))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + LandPropertyAssessment newAdditional = + LandPropertyAssessment.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalLandPropertyAssessment.add(newAdditional); + + emit(LandPropertyAssessmentLoaded(globalLandPropertyAssessment)); + } + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await LandPropertyAssessmentServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalLandPropertyAssessment.removeWhere( + ((LandPropertyAssessment element) => element.id == event.id)); + emit(LandPropertyAssessmentDeletedState(success: true)); + } + }); + + on((event, emit) async { + emit(ShowAddLandPropertyAssessmentScreen()); + }); + } +} diff --git a/lib/bloc/passo/land/land_property_assessment/land_property_assessment_event.dart b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_event.dart new file mode 100644 index 0000000..7eb84e0 --- /dev/null +++ b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_event.dart @@ -0,0 +1,38 @@ +part of 'land_property_assessment_bloc.dart'; + +class LandPropertyAssessmentEvent extends Equatable { + const LandPropertyAssessmentEvent(); + + @override + List get props => []; +} + +class LoadLandPropertyAssessment extends LandPropertyAssessmentEvent { + final List assessment; + + const LoadLandPropertyAssessment( + {this.assessment = const []}); + + @override + List get props => [assessment]; +} + +class AddLandPropertyAssessment extends LandPropertyAssessmentEvent { + final LandPropertyAssessment assessment; + + const AddLandPropertyAssessment({required this.assessment}); + + @override + List get props => [assessment]; +} + +class DeleteLandPropertyAssessment extends LandPropertyAssessmentEvent { + final int id; + + const DeleteLandPropertyAssessment({required this.id}); + + @override + List get props => [id]; +} + +class ShowLandPropertyAssessment extends LandPropertyAssessmentEvent {} diff --git a/lib/bloc/passo/land/land_property_assessment/land_property_assessment_state.dart b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_state.dart new file mode 100644 index 0000000..ce2d738 --- /dev/null +++ b/lib/bloc/passo/land/land_property_assessment/land_property_assessment_state.dart @@ -0,0 +1,35 @@ +part of 'land_property_assessment_bloc.dart'; + +class LandPropertyAssessmentState extends Equatable { + const LandPropertyAssessmentState(); + + @override + List get props => []; +} + +class LandPropertyAssessmentLoading extends LandPropertyAssessmentState {} + +class LandPropertyAssessmentLoaded extends LandPropertyAssessmentState { + const LandPropertyAssessmentLoaded(this.assessment); + final List assessment; + + @override + List get props => [assessment]; +} + +class ShowAddLandPropertyAssessmentScreen extends LandPropertyAssessmentState {} + +class LandPropertyAssessmentErrorState extends LandPropertyAssessmentState { + const LandPropertyAssessmentErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class LandPropertyAssessmentDeletedState extends LandPropertyAssessmentState { + final bool success; + const LandPropertyAssessmentDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart new file mode 100644 index 0000000..1abcfdc --- /dev/null +++ b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/land_property_boundaries.dart'; +import 'package:unit2/model/passo/land_property_loc.dart'; +import 'package:unit2/model/passo/land_property_owner.dart'; +import 'package:unit2/sevices/passo/land/land_boundaries.dart'; +import 'package:unit2/sevices/passo/land/land_location.dart'; +import 'package:unit2/sevices/passo/land/land_property_owner.dart'; +import 'package:http/http.dart' as http; +part 'land_property_owner_info_event.dart'; +part 'land_property_owner_info_state.dart'; + +class LandPropertyOwnerInfoBloc + extends Bloc { + LandPropertyOwnerInfoBloc() : super(LandLoading()) { + on((event, emit) async { + emit(LandLoading()); + try { + final faas = await LandServices.instance.fetch(); + emit(LandLoaded(faas)); + } catch (e) { + emit(LandErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = (await LandServices.instance.add(event.land))!; + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + var details = jsonResponse['data']['details']; + + if (details != null) { + var id = details['id']; + final tempID = await SharedPreferences.getInstance(); + print(id); + await tempID.setInt('landid', id + 1); + final faas = await LandServices.instance.fetch(); + emit(LandLoaded(faas)); + } else { + print("No 'details' object found in the response."); + // Handle the case when 'details' is missing + } + } + }); + + on((event, emit) async { + final state = this.state; + http.Response response = (await LandLocationService.instance + .update(event.land_loc, event.land_loc.id))!; + print('Land LOc'); + print(response.body); + }); + + on((event, emit) async { + final state = this.state; + http.Response response = (await LandBoundariesService.instance + .update(event.land_boundaries, event.land_boundaries.id))!; + print('Land Boundaries'); + print(response.body); + }); + } +} diff --git a/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_event.dart b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_event.dart new file mode 100644 index 0000000..c05cacf --- /dev/null +++ b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_event.dart @@ -0,0 +1,48 @@ +part of 'land_property_owner_info_bloc.dart'; + +class LandPropertyOwnerInfoEvent extends Equatable { + const LandPropertyOwnerInfoEvent(); + + @override + List get props => []; +} + +class LoadLand extends LandPropertyOwnerInfoEvent { + final List land; + + const LoadLand({this.land = const []}); + + @override + List get props => [land]; +} + +class AddPropertyOwnerLand extends LandPropertyOwnerInfoEvent { + final LandPropertyOwner land; + + const AddPropertyOwnerLand({required this.land}); + + @override + List get props => [land]; +} + +class UpdateLandLoc extends LandPropertyOwnerInfoEvent { + // ignore: non_constant_identifier_names + final LandPropertyLoc land_loc; + + // ignore: non_constant_identifier_names + const UpdateLandLoc({required this.land_loc}); + + @override + List get props => [land_loc]; +} + +class UpdateLandBoundaries extends LandPropertyOwnerInfoEvent { + // ignore: non_constant_identifier_names + final LandPropertyBoundaries land_boundaries; + + // ignore: non_constant_identifier_names + const UpdateLandBoundaries({required this.land_boundaries}); + + @override + List get props => [land_boundaries]; +} diff --git a/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_state.dart b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_state.dart new file mode 100644 index 0000000..ec64d5f --- /dev/null +++ b/lib/bloc/passo/land/land_property_owner_info/land_property_owner_info_state.dart @@ -0,0 +1,34 @@ +part of 'land_property_owner_info_bloc.dart'; + +class LandPropertyOwnerInfoState extends Equatable { + const LandPropertyOwnerInfoState(); + + @override + List get props => []; +} + +class LandLoading extends LandPropertyOwnerInfoState {} + +class LandLoaded extends LandPropertyOwnerInfoState { + const LandLoaded(this.land); + final List land; + + @override + List get props => [land]; +} + +// class PropertyAppraisalLoaded extends AssessorsState { +// PropertyAppraisalLoaded(this.appraisal); +// final List appraisal; + +// @override +// List get props => [appraisal]; +// } + +class LandErrorState extends LandPropertyOwnerInfoState { + const LandErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart b/lib/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart new file mode 100644 index 0000000..edca8e3 --- /dev/null +++ b/lib/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart @@ -0,0 +1,25 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/land_classification.dart'; +import 'package:unit2/model/passo/land_subclassification.dart'; +import 'package:unit2/sevices/passo/land/land_classification.dart'; +import 'package:unit2/sevices/passo/land/land_subclassification.dart'; + +part 'land_subclassification_event.dart'; +part 'land_subclassification_state.dart'; + +class LandSubClassificationBloc + extends Bloc { + LandSubClassificationBloc() : super(LandSubClassificationLoading()) { + on((event, emit) async { + emit(LandSubClassificationLoading()); + try { + final classs = await LandSubClassificationService.instance + .fetch(event.cityCode, event.classCode); + emit(LandSubClassificationLoaded(classs)); + } catch (e) { + emit(LandSubClassificationErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/land/land_subclassification/land_subclassification_event.dart b/lib/bloc/passo/land/land_subclassification/land_subclassification_event.dart new file mode 100644 index 0000000..dfd7a29 --- /dev/null +++ b/lib/bloc/passo/land/land_subclassification/land_subclassification_event.dart @@ -0,0 +1,19 @@ +part of 'land_subclassification_bloc.dart'; + +class LandSubClassificationEvent extends Equatable { + const LandSubClassificationEvent(); + + @override + List get props => []; +} + +class LoadLandSubClassification extends LandSubClassificationEvent { + final String cityCode; + final int classCode; + + const LoadLandSubClassification( + {required this.cityCode, required this.classCode}); + + @override + List get props => [cityCode, classCode]; +} diff --git a/lib/bloc/passo/land/land_subclassification/land_subclassification_state.dart b/lib/bloc/passo/land/land_subclassification/land_subclassification_state.dart new file mode 100644 index 0000000..d0f1be9 --- /dev/null +++ b/lib/bloc/passo/land/land_subclassification/land_subclassification_state.dart @@ -0,0 +1,26 @@ +part of 'land_subclassification_bloc.dart'; + +class LandSubClassificationState extends Equatable { + const LandSubClassificationState(); + + @override + List get props => []; +} + +class LandSubClassificationLoading extends LandSubClassificationState {} + +class LandSubClassificationLoaded extends LandSubClassificationState { + LandSubClassificationLoaded(this.land_subclassification); + final List land_subclassification; + + @override + List get props => [land_subclassification]; +} + +class LandSubClassificationErrorState extends LandSubClassificationState { + LandSubClassificationErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart new file mode 100644 index 0000000..6f270ab --- /dev/null +++ b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart @@ -0,0 +1,22 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/trees_improvements.dart'; +import 'package:unit2/sevices/passo/land/land_trees_improvements.dart'; + +part 'land_trees_improvements_event.dart'; +part 'land_trees_improvements_state.dart'; + +class LandTreesImprovementsBloc + extends Bloc { + LandTreesImprovementsBloc() : super(LandTreesImprovementsInitial()) { + on((event, emit) async { + emit(LandTreesImprovementsLoading()); + try { + final trees_imp = await LandTreesImprovementsServices.instance.fetch(); + emit(LandTreesImprovementsLoaded(trees_imp)); + } catch (e) { + emit(LandTreesImprovementsErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_event.dart b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_event.dart new file mode 100644 index 0000000..690977c --- /dev/null +++ b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_event.dart @@ -0,0 +1,17 @@ +part of 'land_trees_improvements_bloc.dart'; + +class LandTreesImprovementsEvent extends Equatable { + const LandTreesImprovementsEvent(); + + @override + List get props => []; +} + +class LoadLandTreesImprovements extends LandTreesImprovementsEvent { + final List trees_imp; + const LoadLandTreesImprovements( + {this.trees_imp = const []}); + + @override + List get props => [trees_imp]; +} diff --git a/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_state.dart b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_state.dart new file mode 100644 index 0000000..f11621a --- /dev/null +++ b/lib/bloc/passo/land/land_trees_improvements/land_trees_improvements_state.dart @@ -0,0 +1,28 @@ +part of 'land_trees_improvements_bloc.dart'; + +class LandTreesImprovementsState extends Equatable { + const LandTreesImprovementsState(); + + @override + List get props => []; +} + +class LandTreesImprovementsInitial extends LandTreesImprovementsState {} + +class LandTreesImprovementsLoading extends LandTreesImprovementsState {} + +class LandTreesImprovementsLoaded extends LandTreesImprovementsState { + LandTreesImprovementsLoaded(this.trees_imp); + final List trees_imp; + + @override + List get props => [trees_imp]; +} + +class LandTreesImprovementsErrorState extends LandTreesImprovementsState { + LandTreesImprovementsErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart new file mode 100644 index 0000000..7655903 --- /dev/null +++ b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/land_value_adjustment.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/sevices/passo/land/land_value_adjustment.dart'; +part 'land_value_adjustments_event.dart'; +part 'land_value_adjustments_state.dart'; + +class LandValueAdjustmentsBloc + extends Bloc { + LandValueAdjustmentsBloc() : super(LandValueAdjustmentsLoading()) { + List globalLandValueAdjustments = []; + on((event, emit) async { + emit(LandValueAdjustmentsLoading()); + try { + // final tempID = await SharedPreferences.getInstance(); + // print(tempID.getInt('tempid')); + // final additionalItem = await GetLandValueAdjustments.getLandValueAdjustments( + // tempID.getInt('tempid')); + + emit(LandValueAdjustmentsLoaded(globalLandValueAdjustments)); + } catch (e) { + emit(LandValueAdjustmentsErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await ValueAdjustmentsServices.instance.add(event.val_adj))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + ValueAdjustments newAdditional = + ValueAdjustments.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalLandValueAdjustments.add(newAdditional); + + emit(LandValueAdjustmentsLoaded(globalLandValueAdjustments)); + } + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await ValueAdjustmentsServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalLandValueAdjustments.removeWhere( + ((ValueAdjustments element) => element.id == event.id)); + emit(LandValueAdjustmentsDeletedState(success: true)); + } + }); + + on((event, emit) async { + emit(ShowAddLandValueAdjustmentsScreen()); + }); + } +} diff --git a/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_event.dart b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_event.dart new file mode 100644 index 0000000..857e6f8 --- /dev/null +++ b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_event.dart @@ -0,0 +1,37 @@ +part of 'land_value_adjustments_bloc.dart'; + +class LandValueAdjustmentsEvent extends Equatable { + const LandValueAdjustmentsEvent(); + + @override + List get props => []; +} + +class LoadLandValueAdjustments extends LandValueAdjustmentsEvent { + final List val_adj; + + const LoadLandValueAdjustments({this.val_adj = const []}); + + @override + List get props => [val_adj]; +} + +class AddLandValueAdjustments extends LandValueAdjustmentsEvent { + final ValueAdjustments val_adj; + + const AddLandValueAdjustments({required this.val_adj}); + + @override + List get props => [val_adj]; +} + +class DeleteLandValueAdjustments extends LandValueAdjustmentsEvent { + final int id; + + const DeleteLandValueAdjustments({required this.id}); + + @override + List get props => [id]; +} + +class ShowLandValueAdjustments extends LandValueAdjustmentsEvent {} diff --git a/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_state.dart b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_state.dart new file mode 100644 index 0000000..8f76eec --- /dev/null +++ b/lib/bloc/passo/land/land_value_adjustments/land_value_adjustments_state.dart @@ -0,0 +1,35 @@ +part of 'land_value_adjustments_bloc.dart'; + +class LandValueAdjustmentsState extends Equatable { + const LandValueAdjustmentsState(); + + @override + List get props => []; +} + +class LandValueAdjustmentsLoading extends LandValueAdjustmentsState {} + +class LandValueAdjustmentsLoaded extends LandValueAdjustmentsState { + const LandValueAdjustmentsLoaded(this.val_adj); + final List val_adj; + + @override + List get props => [val_adj]; +} + +class ShowAddLandValueAdjustmentsScreen extends LandValueAdjustmentsState {} + +class LandValueAdjustmentsErrorState extends LandValueAdjustmentsState { + const LandValueAdjustmentsErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class LandValueAdjustmentsDeletedState extends LandValueAdjustmentsState { + final bool success; + const LandValueAdjustmentsDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/land/other_improvements/other_improvements_bloc.dart b/lib/bloc/passo/land/other_improvements/other_improvements_bloc.dart new file mode 100644 index 0000000..3271961 --- /dev/null +++ b/lib/bloc/passo/land/other_improvements/other_improvements_bloc.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/other_improvements.dart'; +import 'package:unit2/sevices/passo/land/land_other_improvements.dart'; +import 'package:http/http.dart' as http; +part 'other_improvements_event.dart'; +part 'other_improvements_state.dart'; + +class OtherImprovementsBloc + extends Bloc { + OtherImprovementsBloc() : super(OtherImprovementLoading()) { + List globalOtherImprovement = []; + on((event, emit) async { + emit(OtherImprovementLoading()); + try { + // final tempID = await SharedPreferences.getInstance(); + // print(tempID.getInt('tempid')); + // final additionalItem = await GetOtherImprovement.getOtherImprovement( + // tempID.getInt('tempid')); + + emit(OtherImprovementLoaded(globalOtherImprovement)); + } catch (e) { + emit(OtherImprovementErrorState(e.toString())); + } + }); + on((event, emit) async { + http.Response response = + (await OtherImprovementServices.instance.add(event.other_imp))!; + print(response.body); + + if (response.statusCode == 201) { + var jsonResponse = jsonDecode(response.body); + OtherImprovements newAdditional = + OtherImprovements.fromJson(jsonResponse['data']); + print(jsonResponse['data']); + globalOtherImprovement.add(newAdditional); + + emit(OtherImprovementLoaded(globalOtherImprovement)); + } + }); + on((event, emit) async { + print(event.id); + http.Response response = + (await OtherImprovementServices.instance.remove(event.id)); + print(response.statusCode); + if (response.statusCode == 200) { + globalOtherImprovement.removeWhere( + ((OtherImprovements element) => element.id == event.id)); + emit(OtherImprovementDeletedState(success: true)); + } + }); + + on((event, emit) async { + emit(ShowAddOtherImprovementScreen()); + }); + } +} diff --git a/lib/bloc/passo/land/other_improvements/other_improvements_event.dart b/lib/bloc/passo/land/other_improvements/other_improvements_event.dart new file mode 100644 index 0000000..135746f --- /dev/null +++ b/lib/bloc/passo/land/other_improvements/other_improvements_event.dart @@ -0,0 +1,37 @@ +part of 'other_improvements_bloc.dart'; + +class OtherImprovementsEvent extends Equatable { + const OtherImprovementsEvent(); + + @override + List get props => []; +} + +class LoadOtherImprovement extends OtherImprovementsEvent { + final List other_imp; + + const LoadOtherImprovement({this.other_imp = const []}); + + @override + List get props => [other_imp]; +} + +class AddOtherImprovement extends OtherImprovementsEvent { + final OtherImprovements other_imp; + + const AddOtherImprovement({required this.other_imp}); + + @override + List get props => [other_imp]; +} + +class DeleteOtherImprovement extends OtherImprovementsEvent { + final int id; + + const DeleteOtherImprovement({required this.id}); + + @override + List get props => [id]; +} + +class ShowOtherImprovement extends OtherImprovementsEvent {} diff --git a/lib/bloc/passo/land/other_improvements/other_improvements_state.dart b/lib/bloc/passo/land/other_improvements/other_improvements_state.dart new file mode 100644 index 0000000..75b3b01 --- /dev/null +++ b/lib/bloc/passo/land/other_improvements/other_improvements_state.dart @@ -0,0 +1,35 @@ +part of 'other_improvements_bloc.dart'; + +class OtherImprovementsState extends Equatable { + const OtherImprovementsState(); + + @override + List get props => []; +} + +class OtherImprovementLoading extends OtherImprovementsState {} + +class OtherImprovementLoaded extends OtherImprovementsState { + const OtherImprovementLoaded(this.other_imp); + final List other_imp; + + @override + List get props => [other_imp]; +} + +class ShowAddOtherImprovementScreen extends OtherImprovementsState {} + +class OtherImprovementErrorState extends OtherImprovementsState { + const OtherImprovementErrorState(this.error); + final String error; + + @override + List get props => [error]; +} + +class OtherImprovementDeletedState extends OtherImprovementsState { + final bool success; + const OtherImprovementDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/passo/land/type_of_location/type_of_location_bloc.dart b/lib/bloc/passo/land/type_of_location/type_of_location_bloc.dart new file mode 100644 index 0000000..439e0e2 --- /dev/null +++ b/lib/bloc/passo/land/type_of_location/type_of_location_bloc.dart @@ -0,0 +1,22 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/type_of_location.dart'; +import 'package:unit2/sevices/passo/land/type_of_location.dart'; + +part 'type_of_location_event.dart'; +part 'type_of_location_state.dart'; + +class TypeOfLocationBloc + extends Bloc { + TypeOfLocationBloc() : super(TypeOfLocationInitial()) { + on((event, emit) async { + emit(TypeOfLocationLoading()); + try { + final locType = await TypeOfLocationServices.instance.fetch(); + emit(TypeOfLocationLoaded(locType)); + } catch (e) { + emit(TypeOfLocationErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/land/type_of_location/type_of_location_event.dart b/lib/bloc/passo/land/type_of_location/type_of_location_event.dart new file mode 100644 index 0000000..dfcd9b9 --- /dev/null +++ b/lib/bloc/passo/land/type_of_location/type_of_location_event.dart @@ -0,0 +1,17 @@ +part of 'type_of_location_bloc.dart'; + +class TypeOfLocationEvent extends Equatable { + const TypeOfLocationEvent(); + + @override + List get props => []; +} + +class LoadTypeOfLocation extends TypeOfLocationEvent { + final List locType; + + const LoadTypeOfLocation({this.locType = const []}); + + @override + List get props => [locType]; +} diff --git a/lib/bloc/passo/land/type_of_location/type_of_location_state.dart b/lib/bloc/passo/land/type_of_location/type_of_location_state.dart new file mode 100644 index 0000000..cbbb893 --- /dev/null +++ b/lib/bloc/passo/land/type_of_location/type_of_location_state.dart @@ -0,0 +1,28 @@ +part of 'type_of_location_bloc.dart'; + +class TypeOfLocationState extends Equatable { + const TypeOfLocationState(); + + @override + List get props => []; +} + +class TypeOfLocationInitial extends TypeOfLocationState {} + +class TypeOfLocationLoading extends TypeOfLocationState {} + +class TypeOfLocationLoaded extends TypeOfLocationState { + TypeOfLocationLoaded(this.loc_type); + final List loc_type; + + @override + List get props => [loc_type]; +} + +class TypeOfLocationErrorState extends TypeOfLocationState { + TypeOfLocationErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/land/type_of_road/type_of_road_bloc.dart b/lib/bloc/passo/land/type_of_road/type_of_road_bloc.dart new file mode 100644 index 0000000..555a75b --- /dev/null +++ b/lib/bloc/passo/land/type_of_road/type_of_road_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/type_of_road.dart'; +import 'package:unit2/sevices/passo/land/type_of_road.dart'; + +part 'type_of_road_event.dart'; +part 'type_of_road_state.dart'; + +class TypeOfRoadBloc extends Bloc { + TypeOfRoadBloc() : super(TypeOfRoadInitial()) { + on((event, emit) async { + emit(TypeOfRoadLoading()); + try { + final roadType = await TypeOfRoadServices.instance.fetch(); + emit(TypeOfRoadLoaded(roadType)); + } catch (e) { + emit(TypeOfRoadErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/land/type_of_road/type_of_road_event.dart b/lib/bloc/passo/land/type_of_road/type_of_road_event.dart new file mode 100644 index 0000000..1d3cdd3 --- /dev/null +++ b/lib/bloc/passo/land/type_of_road/type_of_road_event.dart @@ -0,0 +1,17 @@ +part of 'type_of_road_bloc.dart'; + +class TypeOfRoadEvent extends Equatable { + const TypeOfRoadEvent(); + + @override + List get props => []; +} + +class LoadTypeOfRoad extends TypeOfRoadEvent { + final List roadType; + + const LoadTypeOfRoad({this.roadType = const []}); + + @override + List get props => [roadType]; +} diff --git a/lib/bloc/passo/land/type_of_road/type_of_road_state.dart b/lib/bloc/passo/land/type_of_road/type_of_road_state.dart new file mode 100644 index 0000000..ad65a1c --- /dev/null +++ b/lib/bloc/passo/land/type_of_road/type_of_road_state.dart @@ -0,0 +1,28 @@ +part of 'type_of_road_bloc.dart'; + +class TypeOfRoadState extends Equatable { + const TypeOfRoadState(); + + @override + List get props => []; +} + +class TypeOfRoadInitial extends TypeOfRoadState {} + +class TypeOfRoadLoading extends TypeOfRoadState {} + +class TypeOfRoadLoaded extends TypeOfRoadState { + TypeOfRoadLoaded(this.road_type); + final List road_type; + + @override + List get props => [road_type]; +} + +class TypeOfRoadErrorState extends TypeOfRoadState { + TypeOfRoadErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/memoranda/memoranda_bloc.dart b/lib/bloc/passo/memoranda/memoranda_bloc.dart new file mode 100644 index 0000000..c1b1a31 --- /dev/null +++ b/lib/bloc/passo/memoranda/memoranda_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/memoranda.dart'; +import 'package:unit2/sevices/passo/memoranda.dart'; + +part 'memoranda_event.dart'; +part 'memoranda_state.dart'; + +class MemorandaBloc extends Bloc { + MemorandaBloc() : super(MemorandaInitial()) { + on((event, emit) async { + emit(MemorandaLoading()); + try { + final municipality = await MemorandaServices.instance.fetch(); + emit(MemorandaLoaded(municipality)); + } catch (e) { + emit(MemorandaErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/memoranda/memoranda_event.dart b/lib/bloc/passo/memoranda/memoranda_event.dart new file mode 100644 index 0000000..06ac2b6 --- /dev/null +++ b/lib/bloc/passo/memoranda/memoranda_event.dart @@ -0,0 +1,16 @@ +part of 'memoranda_bloc.dart'; + +class MemorandaEvent extends Equatable { + const MemorandaEvent(); + + @override + List get props => []; +} + +class LoadMemoranda extends MemorandaEvent { + final List memoranda; + const LoadMemoranda({this.memoranda = const []}); + + @override + List get props => [memoranda]; +} diff --git a/lib/bloc/passo/memoranda/memoranda_state.dart b/lib/bloc/passo/memoranda/memoranda_state.dart new file mode 100644 index 0000000..1803cd8 --- /dev/null +++ b/lib/bloc/passo/memoranda/memoranda_state.dart @@ -0,0 +1,28 @@ +part of 'memoranda_bloc.dart'; + +class MemorandaState extends Equatable { + const MemorandaState(); + + @override + List get props => []; +} + +class MemorandaInitial extends MemorandaState {} + +class MemorandaLoading extends MemorandaState {} + +class MemorandaLoaded extends MemorandaState { + MemorandaLoaded(this.memorada); + final List memorada; + + @override + List get props => [memorada]; +} + +class MemorandaErrorState extends MemorandaState { + MemorandaErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/municipality/municipality_bloc.dart b/lib/bloc/passo/municipality/municipality_bloc.dart new file mode 100644 index 0000000..3a6a246 --- /dev/null +++ b/lib/bloc/passo/municipality/municipality_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/city.dart'; +import 'package:unit2/sevices/passo/municipality.dart'; + +part 'municipality_event.dart'; +part 'municipality_state.dart'; + +class MunicipalityBloc extends Bloc { + MunicipalityBloc() : super(MunicipalityInitial()) { + on((event, emit) async { + emit(MunicipalityLoading()); + try { + final municipality = await MunicipalityServices.instance.fetch(); + emit(MunicipalityLoaded(municipality)); + } catch (e) { + emit(MunicipalityErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/municipality/municipality_event.dart b/lib/bloc/passo/municipality/municipality_event.dart new file mode 100644 index 0000000..4b7556f --- /dev/null +++ b/lib/bloc/passo/municipality/municipality_event.dart @@ -0,0 +1,17 @@ +part of 'municipality_bloc.dart'; + +class MunicipalityEvent extends Equatable { + const MunicipalityEvent(); + + @override + List get props => []; +} + +class LoadMunicipality extends MunicipalityEvent { + final List municipality; + + const LoadMunicipality({this.municipality = const []}); + + @override + List get props => [municipality]; +} diff --git a/lib/bloc/passo/municipality/municipality_state.dart b/lib/bloc/passo/municipality/municipality_state.dart new file mode 100644 index 0000000..25c1131 --- /dev/null +++ b/lib/bloc/passo/municipality/municipality_state.dart @@ -0,0 +1,28 @@ +part of 'municipality_bloc.dart'; + +class MunicipalityState extends Equatable { + const MunicipalityState(); + + @override + List get props => []; +} + +class MunicipalityInitial extends MunicipalityState {} + +class MunicipalityLoading extends MunicipalityState {} + +class MunicipalityLoaded extends MunicipalityState { + MunicipalityLoaded(this.municipality); + final List municipality; + + @override + List get props => [municipality]; +} + +class MunicipalityErrorState extends MunicipalityState { + MunicipalityErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/passo/signatories/signatories_bloc.dart b/lib/bloc/passo/signatories/signatories_bloc.dart new file mode 100644 index 0000000..8c55403 --- /dev/null +++ b/lib/bloc/passo/signatories/signatories_bloc.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/passo/signatories.dart'; +import 'package:unit2/sevices/passo/signatories_service.dart'; + +part 'signatories_event.dart'; +part 'signatories_state.dart'; + +class SignatoriesBloc extends Bloc { + SignatoriesBloc() : super(SignatoriesInitial()) { + on((event, emit) async { + emit(SignatoriesLoading()); + try { + final signatories = await SignatoriesServices.instance.fetch(); + emit(SignatoriesLoaded(signatories)); + } catch (e) { + emit(SignatoriesErrorState(e.toString())); + } + }); + } +} diff --git a/lib/bloc/passo/signatories/signatories_event.dart b/lib/bloc/passo/signatories/signatories_event.dart new file mode 100644 index 0000000..a1949cd --- /dev/null +++ b/lib/bloc/passo/signatories/signatories_event.dart @@ -0,0 +1,17 @@ +part of 'signatories_bloc.dart'; + +abstract class SignatoriesEvent extends Equatable { + const SignatoriesEvent(); + + @override + List get props => []; +} + +class LoadSignatories extends SignatoriesEvent { + final List signatories; + + const LoadSignatories({this.signatories = const []}); + + @override + List get props => [signatories]; +} diff --git a/lib/bloc/passo/signatories/signatories_state.dart b/lib/bloc/passo/signatories/signatories_state.dart new file mode 100644 index 0000000..a914bc9 --- /dev/null +++ b/lib/bloc/passo/signatories/signatories_state.dart @@ -0,0 +1,28 @@ +part of 'signatories_bloc.dart'; + +abstract class SignatoriesState extends Equatable { + const SignatoriesState(); + + @override + List get props => []; +} + +class SignatoriesInitial extends SignatoriesState {} + +class SignatoriesLoading extends SignatoriesState {} + +class SignatoriesLoaded extends SignatoriesState { + SignatoriesLoaded(this.signatories); + final List signatories; + + @override + List get props => [signatories]; +} + +class SignatoriesErrorState extends SignatoriesState { + SignatoriesErrorState(this.error); + final String error; + + @override + List get props => [error]; +} diff --git a/lib/bloc/profile/education/education_bloc.dart b/lib/bloc/profile/education/education_bloc.dart new file mode 100644 index 0000000..dd7374c --- /dev/null +++ b/lib/bloc/profile/education/education_bloc.dart @@ -0,0 +1,261 @@ +import 'dart:io'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/sevices/profile/education_services.dart'; +import 'package:unit2/utils/request_permission.dart'; + +import '../../../model/profile/attachment.dart'; +import '../../../utils/attachment_services.dart'; +import '../../../utils/urls.dart'; + +part 'education_event.dart'; +part 'education_state.dart'; + +class EducationBloc extends Bloc { + List educationalBackgrounds = []; + List schools = []; + List programs = []; + List honors = []; + int? profileId; + String? token; + List attachmentCategories = []; + EducationBloc() : super(EducationInitial()) { + on((event, emit) async { + profileId = event.profileId; + token = event.token; + emit(EducationalBackgroundLoadingState()); + try { + if (attachmentCategories.isEmpty) { + attachmentCategories = + await AttachmentServices.instance.getCategories(); + } + if (educationalBackgrounds.isEmpty) { + List educations = await EducationService + .instace + .getEducationalBackground(event.profileId, event.token); + educationalBackgrounds = educations; + emit(EducationalBackgroundLoadedState( + educationalBackground: educationalBackgrounds, + attachmentCategory: attachmentCategories)); + } else { + emit(EducationalBackgroundLoadedState( + educationalBackground: educationalBackgrounds, + attachmentCategory: attachmentCategories)); + } + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + //// SHOW ADD FORM + on((event, emit) async { + emit(EducationalBackgroundLoadingState()); + try { + if (schools.isEmpty) { + List newSchools = await EducationService.instace.getSchools(); + schools = newSchools; + } + if (programs.isEmpty) { + List newPrograms = + await EducationService.instace.getPrograms(); + programs = newPrograms; + } + if (honors.isEmpty) { + List newHonors = await EducationService.instace.getHonors(); + honors = newHonors; + } + emit(AddEducationState( + schools: schools, programs: programs, honors: honors)); + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + ////Add + on((event, emit) async { + Map status = await EducationService.instace.add( + honors: event.honors, + educationalBackground: event.educationalBackground, + token: event.token, + profileId: event.profileId); + if (status['success']) { + EducationalBackground educationalBackground = + EducationalBackground.fromJson(status['data']); + educationalBackgrounds.add(educationalBackground); + emit(EducationAddedState(response: status)); + } else { + emit(EducationAddedState(response: status)); + } + }); + ////Update + on((event, emit) async { + Map status = await EducationService.instace.edit( + honors: event.honors, + educationalBackground: event.educationalBackground, + token: event.token, + profileId: event.profileId); + if (status['success']) { + educationalBackgrounds.removeWhere( + (element) => event.educationalBackground.id == element.id); + EducationalBackground educationalBackground = + EducationalBackground.fromJson(status['data']); + educationalBackgrounds.add(educationalBackground); + emit(EditedEducationState(response: status)); + } else { + emit(EditedEducationState(response: status)); + } + }); + ////LOAD + on((event, emit) { + emit(EducationalBackgroundLoadedState( + educationalBackground: educationalBackgrounds, + attachmentCategory: attachmentCategories)); + }); + //// SHOW EDIT FORM + on((event, emit) async { + try { + if (schools.isEmpty) { + List newSchools = await EducationService.instace.getSchools(); + schools = newSchools; + } + if (programs.isEmpty) { + List newPrograms = + await EducationService.instace.getPrograms(); + programs = newPrograms; + } + if (honors.isEmpty) { + List newHonors = await EducationService.instace.getHonors(); + honors = newHonors; + } + emit(EditEducationState( + schools: schools, + programs: programs, + honors: honors, + educationalBackground: event.educationalBackground)); + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + ////delete + on((event, emit) async { + try { + final bool success = await EducationService.instace.delete( + profileId: event.profileId, + token: event.token, + educationalBackground: event.educationalBackground); + if (success) { + educationalBackgrounds.removeWhere( + (element) => element.id == event.educationalBackground.id); + emit(EducationDeletedState(success: success)); + } else { + emit(EducationDeletedState(success: success)); + } + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + ////Add attachment + on((event, emit) async { + emit(EducationalBackgroundLoadingState()); + EducationalBackground educationalBackground = + educationalBackgrounds.firstWhere( + (element) => element.id.toString() == event.attachmentModule); + List attachments = []; + try { + Map status = await AttachmentServices.instance + .attachment( + categoryId: event.categoryId, + module: event.attachmentModule, + paths: event.filePaths, + token: event.token, + profileId: event.profileId); + + if (status['success']) { + status['data'].forEach((element) { + Attachment newAttachment = Attachment.fromJson(element); + attachments.add(newAttachment); + }); + educationalBackground.attachments == null + ? educationalBackground.attachments = attachments + : educationalBackground.attachments = [ + ...educationalBackground.attachments!, + ...attachments + ]; + emit(EducationAddedState(response: status)); + } else { + emit(EducationAddedState(response: status)); + } + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(EducationalBackgroundLoadingState()); + try { + final bool success = await AttachmentServices.instance.deleteAttachment( + attachment: event.attachment, + moduleId: event.moduleId, + profileId: event.profileId.toString(), + token: event.token); + if (success) { + final EducationalBackground educationalBackground = + educationalBackgrounds + .firstWhere((element) => element.id == event.moduleId); + educationalBackground.attachments + ?.removeWhere((element) => element.id == event.attachment.id); + educationalBackgrounds + .removeWhere((element) => element.id == event.moduleId); + educationalBackgrounds.add(educationalBackground); + emit(EducationAttachmentDeletedState(success: success)); + } else { + emit(EducationAttachmentDeletedState(success: success)); + } + } catch (e) { + emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + on((event, emit) { + String fileUrl = + '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(EducationAttachmentViewState( + fileUrl: fileUrl, fileName: event.fileName)); + }); + on((event, emit) async { + emit(EducationalBackgroundLoadingState()); + Directory directory; + String? appDocumentPath; + if (await requestPermission(Permission.storage)) { + directory = await getApplicationDocumentsDirectory(); + appDocumentPath = directory.path; + } + try{ + final bool success = await AttachmentServices.instance.downloadAttachment( + filename: event.fileName, + source: event.source, + downLoadDir: appDocumentPath!); + if (success) { + final result = await Share.shareXFiles( + [XFile("$appDocumentPath/${event.fileName}")]); + if (result.status == ShareResultStatus.success) { + Fluttertoast.showToast(msg: "Attachment shared successful"); + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } else { + Fluttertoast.showToast(msg: "Attachment shared unsuccessful"); + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + } else { + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + }catch(e){ +emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/education/education_event.dart b/lib/bloc/profile/education/education_event.dart new file mode 100644 index 0000000..d2f57e6 --- /dev/null +++ b/lib/bloc/profile/education/education_event.dart @@ -0,0 +1,97 @@ +part of 'education_bloc.dart'; + +abstract class EducationEvent extends Equatable { + const EducationEvent(); + + @override + List get props => []; +} + +class GetEducationalBackground extends EducationEvent { + final int profileId; + final String token; + const GetEducationalBackground( + {required this.profileId, required this.token}); + @override + List get props => [profileId, token]; +} +////show add form +class ShowAddEducationForm extends EducationEvent {} +////show edit form +class ShowEditEducationForm extends EducationEvent { + final EducationalBackground educationalBackground; + final int profileId; + final String token; + const ShowEditEducationForm({required this.educationalBackground,required this.profileId, required this.token}); + @override + List get props => [educationalBackground]; +} +////load +class LoadEducations extends EducationEvent {} +////add +class AddEducation extends EducationEvent { + final List honors; + final EducationalBackground educationalBackground; + final int profileId; + final String token; + const AddEducation( + {required this.educationalBackground, + required this.profileId, + required this.token, required this.honors}); + @override + List get props => [educationalBackground, profileId, token]; +} +////update education +class UpdateEducation extends EducationEvent{ + final List honors; + final EducationalBackground educationalBackground; + final int profileId; + final String token; + const UpdateEducation( + {required this.educationalBackground, + required this.profileId, + required this.token,required this.honors}); + @override + List get props => [educationalBackground, profileId, token]; +} +////delete +class DeleteEducation extends EducationEvent{ + final int profileId; + final String token; + final EducationalBackground educationalBackground; + const DeleteEducation({required this.educationalBackground, required this.profileId, required this.token}); + @override + List get props => [educationalBackground, profileId, token]; +} +////Add attachment +class AddEducationAttachment extends EducationEvent{ + final String categoryId; + final String attachmentModule; + final List filePaths; + final String token; + final String profileId; + const AddEducationAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token}); + @override + List get props => [categoryId,attachmentModule,filePaths, token,profileId]; +} + +////Delete Attachment +class DeleteEducationAttachment extends EducationEvent{ + final int moduleId; + final Attachment attachment; + final String token; + final int profileId; + const DeleteEducationAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token}); +} + +class EducationViewAttachment extends EducationEvent{ + final String fileName; + final String source; + const EducationViewAttachment({required this.source,required this.fileName}); +} + +class ShareAttachment extends EducationEvent{ + final String fileName; + final String source; + const ShareAttachment({required this.fileName, required this.source}); +} diff --git a/lib/bloc/profile/education/education_state.dart b/lib/bloc/profile/education/education_state.dart new file mode 100644 index 0000000..d7fd394 --- /dev/null +++ b/lib/bloc/profile/education/education_state.dart @@ -0,0 +1,102 @@ +part of 'education_bloc.dart'; + +abstract class EducationState extends Equatable { + const EducationState(); + + @override + List get props => []; +} + +class EducationInitial extends EducationState {} + +class EducationalBackgroundLoadedState extends EducationState { + final List attachmentCategory; + final List educationalBackground; + const EducationalBackgroundLoadedState( + {required this.educationalBackground, required this.attachmentCategory}); + @override + List get props => [educationalBackground]; +} + +class EducationalBackgroundErrorState extends EducationState { + final String message; + const EducationalBackgroundErrorState({required this.message}); + @override + List get props => [message]; +} + +class EducationalBackgroundLoadingState extends EducationState {} + +////Add +class AddEducationState extends EducationState { + final List schools; + final List programs; + final List honors; + const AddEducationState( + {required this.honors, required this.programs, required this.schools}); + @override + List get props => [schools, programs, honors]; +} + +////Edit +class EditEducationState extends EducationState { + final EducationalBackground educationalBackground; + final List schools; + final List programs; + final List honors; + const EditEducationState({ + required this.educationalBackground, + required this.honors, + required this.programs, + required this.schools, + }); +} + +//// Added State +class EducationAddedState extends EducationState { + final Map response; + const EducationAddedState({required this.response}); + @override + List get props => [response]; +} + +//// Edited State +class EditedEducationState extends EducationState { + final Map response; + const EditedEducationState({required this.response}); + @override + List get props => [response]; +} + +////deleted State +class EducationDeletedState extends EducationState { + final bool success; + const EducationDeletedState({required this.success}); + @override + List get props => [success]; +} + +////Attachment AddedState +class EducationAttachmentAddedState extends EducationState { + final Map response; + const EducationAttachmentAddedState({required this.response}); +} + +////Attachment Deleted State State +class EducationAttachmentDeletedState extends EducationState { + final bool success; + const EducationAttachmentDeletedState({required this.success}); + @override + List get props => [success]; +} + +class EducationAttachmentViewState extends EducationState { + final String fileUrl; + final String fileName; + const EducationAttachmentViewState({required this.fileUrl, required this.fileName}); +} + +class EducationAttachmentShareState extends EducationState{ + final bool success; + const EducationAttachmentShareState({required this.success,}); +} diff --git a/lib/bloc/profile/eligibility/eligibility_bloc.dart b/lib/bloc/profile/eligibility/eligibility_bloc.dart new file mode 100644 index 0000000..a714bc9 --- /dev/null +++ b/lib/bloc/profile/eligibility/eligibility_bloc.dart @@ -0,0 +1,330 @@ +import 'dart:io'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:unit2/screens/profile/components/eligibility/eligibility_view_attachment.dart'; +import 'package:unit2/utils/attachment_services.dart'; +import '../../../model/location/city.dart'; +import '../../../model/location/country.dart'; +import '../../../model/location/provinces.dart'; +import '../../../model/location/region.dart'; +import '../../../model/profile/attachment.dart'; +import '../../../model/profile/eligibility.dart'; +import '../../../model/utils/eligibility.dart'; +import '../../../sevices/profile/eligibility_services.dart'; +import '../../../utils/location_utilities.dart'; +import '../../../utils/profile_utilities.dart'; +import '../../../utils/request_permission.dart'; +import '../../../utils/urls.dart'; +part 'eligibility_event.dart'; +part 'eligibility_state.dart'; + +class EligibilityBloc extends Bloc { + EligibilityBloc() : super(EligibilityInitial()) { + List globalCountries = []; + List globalRegions = []; + List globalEligibilities = []; + List eligibilities = []; + List attachmentCategories = []; +//// LOAD ELIGIBILTY + on((event, emit) { + emit(EligibilityLoadingState()); + emit(EligibilityLoaded( + eligibilities: eligibilities, + attachmentCategory: attachmentCategories)); + }); + + //// DELETE + on((event, emit) async { + try { + final bool success = await EligibilityService.instance.delete( + eligibilityId: event.eligibilityId, + profileId: int.parse(event.profileId), + token: event.token); + if (success) { + eligibilities.removeWhere( + ((EligibityCert element) => element.id == event.eligibilityId)); + emit(EligibilityDeletedState( + success: success, + )); + } else { + emit(EligibilityDeletedState(success: success)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + +//// GET ELIGIBILITY + on((event, emit) async { + emit(EligibilityLoadingState()); + try { + if (attachmentCategories.isEmpty) { + attachmentCategories = + await AttachmentServices.instance.getCategories(); + } + if (eligibilities.isNotEmpty) { + emit(EligibilityLoaded( + eligibilities: eligibilities, + attachmentCategory: attachmentCategories)); + } else { + emit(EligibilityLoadingState()); + eligibilities = await EligibilityService.instance + .getEligibilities(event.profileId, event.token); + emit(EligibilityLoaded( + eligibilities: eligibilities, + attachmentCategory: attachmentCategories)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); +//// SHOW EDIT FORM + on((event, emit) async { + try { + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalEligibilities.isEmpty) { + List eligibilities = + await ProfileUtilities.instance.getEligibilities(); + globalEligibilities = eligibilities; + } + Eligibility currentEligibility = globalEligibilities.firstWhere( + (Eligibility eligibility) => + event.eligibityCert.eligibility!.id == eligibility.id); + bool? isOverseas = event.eligibityCert.overseas; + Country currentCountry = globalCountries.firstWhere((Country country) => + event.eligibityCert.examAddress!.country!.code == country.code); + if (event.eligibityCert.examAddress?.cityMunicipality?.province + ?.region != + null) { + Region currrentRegion = globalRegions.firstWhere((Region region) => + event.eligibityCert.examAddress!.cityMunicipality!.province! + .region!.code == + region.code); + List provinces = await LocationUtils.instance + .getProvinces(regionCode: currrentRegion.code.toString()); + Province currentProvince = provinces.firstWhere((Province province) => + event.eligibityCert.examAddress!.cityMunicipality!.province! + .code == + province.code); + List cities = await LocationUtils.instance + .getCities(code: currentProvince.code.toString()); + CityMunicipality currentCity = cities.firstWhere( + (CityMunicipality cityMunicipality) => + event.eligibityCert.examAddress!.cityMunicipality!.code == + cityMunicipality.code); + + emit(EditEligibilityState( + currentCity: currentCity, + selectedCountry: currentCountry, + currentProvince: currentProvince, + currentRegion: currrentRegion, + currentEligibility: currentEligibility, + provinces: provinces, + cities: cities, + isOverseas: isOverseas!, + eligibityCert: event.eligibityCert, + countries: globalCountries, + regions: globalRegions, + eligibilities: globalEligibilities)); + } else { + emit(EditEligibilityState( + selectedCountry: currentCountry, + currentCity: null, + currentProvince: null, + currentRegion: null, + provinces: null, + cities: null, + currentEligibility: currentEligibility, + isOverseas: isOverseas!, + eligibityCert: event.eligibityCert, + countries: globalCountries, + regions: globalRegions, + eligibilities: globalEligibilities)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + + //// UPDATE + on((event, emit) async { + try { + Map status = await EligibilityService.instance.update( + eligibityCert: event.eligibityCert, + token: event.token, + profileId: int.parse(event.profileId), + oldEligibility: event.oldEligibility); + if (status['success']) { + EligibityCert newEligibility = EligibityCert.fromJson(status['data']); + eligibilities.removeWhere( + (EligibityCert element) => element.id == event.eligibityCert.id); + eligibilities.add(newEligibility); + emit(EligibilityEditedState(response: status)); + } else { + emit(EligibilityEditedState(response: status)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + //// SHOW ADD FORM + on((event, emit) async { + emit(EligibilityLoadingState()); + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalEligibilities.isEmpty) { + List eligibilities = + await ProfileUtilities.instance.getEligibilities(); + globalEligibilities = eligibilities; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + + emit(AddEligibilityState( + eligibilities: globalEligibilities, + regions: globalRegions, + countries: globalCountries)); + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + + //// ADD + on( + (event, emit) async { + try { + Map status = await EligibilityService.instance.add( + eligibityCert: event.eligibityCert, + token: event.token, + profileId: int.parse(event.profileId)); + if (status['success']) { + EligibityCert? eligibityCert = + EligibityCert.fromJson(status['data']); + eligibilities.add(eligibityCert); + emit(EligibilityAddedState(response: status)); + } else { + emit(EligibilityAddedState(response: status)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }, + ); + on((event, emit) { + emit(const EligibilityErrorState( + message: "Something went wrong. Please try again")); + }); + ////Add attachment + on((event, emit) async { + emit(EligibilityLoadingState()); + List attachments = []; + EligibityCert eligibityCert = eligibilities.firstWhere( + (element) => element.id.toString() == event.attachmentModule); + try { + Map status = await AttachmentServices.instance + .attachment( + categoryId: event.categoryId, + module: event.attachmentModule, + paths: event.filePaths, + token: event.token, + profileId: event.profileId); + if (status['success']) { + status['data'].forEach((element) { + Attachment newAttachment = Attachment.fromJson(element); + attachments.add(newAttachment); + }); + eligibityCert.attachments == null + ? eligibityCert.attachments = attachments + : eligibityCert.attachments = [ + ...eligibityCert.attachments!, + ...attachments + ]; + emit(EligibilityAttachmentAddedState(response: status)); + } else { + emit(EligibilityAttachmentAddedState(response: status)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + + on((event, emit) async { + emit(EligibilityLoadingState()); + try { + final bool success = await AttachmentServices.instance.deleteAttachment( + attachment: event.attachment, + moduleId: int.parse(event.moduleId), + profileId: event.profileId.toString(), + token: event.token); + if (success) { + final EligibityCert eligibityCert = eligibilities + .firstWhere((element) => element.id.toString() == event.moduleId); + eligibityCert.attachments + ?.removeWhere((element) => element.id == event.attachment.id); + eligibilities.removeWhere( + (element) => element.id.toString() == event.moduleId); + eligibilities.add(eligibityCert); + emit(EligibilitytAttachmentDeletedState(success: success)); + } else { + emit(EligibilitytAttachmentDeletedState(success: success)); + } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + on((event,emit){ + String fileUrl = '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(EligibilityAttachmentViewState(fileUrl: fileUrl,fileName: event.filename)); + }); + on((event, emit) async { + emit(EligibilityLoadingState()); + Directory directory; + String? appDocumentPath; + if (await requestPermission(Permission.storage)) { + directory = await getApplicationDocumentsDirectory(); + appDocumentPath = directory.path; + } + try{ + final bool success = await AttachmentServices.instance.downloadAttachment( + filename: event.fileName, + source: event.source, + downLoadDir: appDocumentPath!); + if (success) { + final result = await Share.shareXFiles( + [XFile("$appDocumentPath/${event.fileName}")]); + if (result.status == ShareResultStatus.success) { + Fluttertoast.showToast(msg: "Attachment shared successful"); + emit(EligibilityAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } else { + Fluttertoast.showToast(msg: "Attachment shared unsuccessful"); + emit(EligibilityAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + } else { + emit(EligibilityAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + }catch(e){ +emit(EligibilityErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/eligibility/eligibility_event.dart b/lib/bloc/profile/eligibility/eligibility_event.dart new file mode 100644 index 0000000..fab7746 --- /dev/null +++ b/lib/bloc/profile/eligibility/eligibility_event.dart @@ -0,0 +1,117 @@ +part of 'eligibility_bloc.dart'; + +abstract class EligibilityEvent extends Equatable { + const EligibilityEvent(); + + @override + List get props => []; +} + +class ShowAddEligibilityForm extends EligibilityEvent {} + +class GetEligibilities extends EligibilityEvent { + final int profileId; + final String token; + const GetEligibilities({required this.profileId, required this.token}); + @override + List get props => [profileId, token]; +} + +class AddEligibility extends EligibilityEvent { + final EligibityCert eligibityCert; + final String profileId; + final String token; + const AddEligibility( + {required this.eligibityCert, + required this.profileId, + required this.token}); + @override + List get props => [eligibityCert, profileId, token]; +} + +class UpdateEligibility extends EligibilityEvent { + final EligibityCert eligibityCert; + final String profileId; + final String token; + final int oldEligibility; + const UpdateEligibility( + {required this.eligibityCert, + required this.oldEligibility, + required this.profileId, + required this.token}); + + @override + List get props => [eligibityCert, profileId, token, oldEligibility]; +} + +class LoadEligibility extends EligibilityEvent { + const LoadEligibility(); + @override + List get props => []; +} + +class ShowEditEligibilityForm extends EligibilityEvent { + final EligibityCert eligibityCert; + const ShowEditEligibilityForm({required this.eligibityCert}); + @override + List get props => []; +} + +class DeleteEligibility extends EligibilityEvent { + final String profileId; + final int eligibilityId; + final String token; + + const DeleteEligibility( + {required this.eligibilityId, + required this.profileId, + required this.token}); + @override + List get props => [profileId, eligibilityId, token]; +} + +class CallErrorState extends EligibilityEvent {} + +////Add Attachment +class AddEligibiltyAttachment extends EligibilityEvent { + final String categoryId; + final String attachmentModule; + final List filePaths; + final String token; + final String profileId; + const AddEligibiltyAttachment( + {required this.attachmentModule, + required this.filePaths, + required this.categoryId, + required this.profileId, + required this.token}); + @override + List get props => + [categoryId, attachmentModule, filePaths, token, profileId]; +} + +////Delete Attachment +class DeleteEligibyAttachment extends EligibilityEvent { + final String profileId; + final String token; + final Attachment attachment; + final String moduleId; + const DeleteEligibyAttachment( + {required this.attachment, + required this.moduleId, + required this.profileId, + required this.token}); +} + + +class EligibiltyViewAttachmentEvent extends EligibilityEvent{ + final String source; + final String filename; + const EligibiltyViewAttachmentEvent({required this.source, required this.filename}); +} +class ShareAttachment extends EligibilityEvent{ + final String fileName; + final String source; + const ShareAttachment({required this.fileName, required this.source}); +} + diff --git a/lib/bloc/profile/eligibility/eligibility_state.dart b/lib/bloc/profile/eligibility/eligibility_state.dart new file mode 100644 index 0000000..9f6a005 --- /dev/null +++ b/lib/bloc/profile/eligibility/eligibility_state.dart @@ -0,0 +1,120 @@ +part of 'eligibility_bloc.dart'; + +abstract class EligibilityState extends Equatable { + const EligibilityState(); + + @override + List get props => []; +} + +class EligibilityInitial extends EligibilityState {} + +class EditEligibilityState extends EligibilityState { + final EligibityCert eligibityCert; + final List eligibilities; + final List countries; + final List regions; + final List? provinces; + final List? cities; + final bool isOverseas; + final Eligibility currentEligibility; + final Region? currentRegion; + final Province? currentProvince; + final CityMunicipality? currentCity; + final Country selectedCountry; + + const EditEligibilityState({ + required this.provinces, + required this.cities, + required this.currentProvince, + required this.currentCity, + required this.currentRegion, + required this.currentEligibility, + required this.isOverseas, + required this.eligibityCert, + required this.eligibilities, + required this.countries, + required this.regions, + required this.selectedCountry, + }); + @override + List get props => + [isOverseas, eligibityCert, eligibilities, regions, countries]; +} + +class EligibilityDeletedState extends EligibilityState { + final bool success; + const EligibilityDeletedState({required this.success}); + @override + List get props => [success]; +} + +class AddEligibilityState extends EligibilityState { + final List eligibilities; + final List countries; + final List regions; + const AddEligibilityState({ + required this.eligibilities, + required this.countries, + required this.regions, + }); + @override + List get props => [eligibilities, countries, regions]; +} + +class EligibilityEditedState extends EligibilityState { + final Map response; + const EligibilityEditedState({required this.response}); + @override + List get props => [response]; +} + +class EligibilityAddedState extends EligibilityState { + final Map response; + + const EligibilityAddedState({required this.response}); + @override + List get props => [response]; +} + +class EligibilityLoadingState extends EligibilityState {} + +class EligibilityErrorState extends EligibilityState { + final String message; + const EligibilityErrorState({required this.message}); + @override + List get props => [message]; +} + +class EligibilityLoaded extends EligibilityState { + final List< AttachmentCategory> attachmentCategory; + final List eligibilities; + const EligibilityLoaded({required this.eligibilities, required this.attachmentCategory}); + @override + List get props => [eligibilities]; +} + +////Attachment AddedState +class EligibilityAttachmentAddedState extends EligibilityState { + final Map response; + const EligibilityAttachmentAddedState({required this.response}); +} + +////Attachment Deleted State State +class EligibilitytAttachmentDeletedState extends EligibilityState { + final bool success; + const EligibilitytAttachmentDeletedState({required this.success}); + @override + List get props => [success]; +} + +class EligibilityAttachmentViewState extends EligibilityState { + final String fileName; + final String fileUrl; + const EligibilityAttachmentViewState({required this.fileUrl, required this.fileName}); +} +class EligibilityAttachmentShareState extends EligibilityState{ + final bool success; + const EligibilityAttachmentShareState({required this.success,}); +} + diff --git a/lib/bloc/profile/family/family_bloc.dart b/lib/bloc/profile/family/family_bloc.dart new file mode 100644 index 0000000..96b13f8 --- /dev/null +++ b/lib/bloc/profile/family/family_bloc.dart @@ -0,0 +1,127 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/profile/family_services.dart'; + +import '../../../model/profile/family_backround.dart'; + +part 'family_event.dart'; +part 'family_state.dart'; + +class FamilyBloc extends Bloc { + FamilyBloc() : super(FamilyInitial()) { + List families = []; + on((event, emit) async { + emit(FamilyLoadingState()); + try { + + if (families.isEmpty) { + List family = await FamilyService.instance + .getFamilies(event.profileId, event.token); + families = family; + } + emit(FamilyLoaded(families: families)); + } catch (e) { + emit(FamilyErrorState(message: e.toString())); + } + + + }); + ////Load + on((event, emit) { + emit(FamilyLoaded(families: families)); + }); + ////Add Family + on((event, emit) async { + try { + emit(FamilyLoadingState()); + Map status = await FamilyService.instance.add( + family: event.familyBackground, + relationshipId: event.relationshipId, + profileId: event.profileId, + token: event.token); + if (status['success']) { + FamilyBackground familyBackground = + FamilyBackground.fromJson(status['data']); + families.add(familyBackground); + emit(FamilyAddedState(response: status)); + } else { + emit(FamilyAddedState(response: status)); + } + } catch (e) { + emit(FamilyErrorState(message: e.toString())); + } + }); + //// Add Emergency + on((event, emit) async { + try { + emit(FamilyLoadingState()); + Map status = await FamilyService.instance + .addEmergency( + requestType: event.requestType, + relatedPersonId: event.relatedPersonId, + numberMail: event.numberMail, + contactInfoId: event.contactInfoId, + profileId: event.profileId, + token: event.token); + if (status['success']) { + families.removeWhere( + (element) => element.relatedPerson!.id == event.relatedPersonId); + FamilyBackground familyBackground = + FamilyBackground.fromJson(status['data']); + families.add(familyBackground); + emit(EmergencyContactEditedState(response: status)); + } else { + emit(EmergencyContactEditedState(response: status)); + } + } catch (e) { + emit(FamilyErrorState(message: e.toString())); + } + }); + ////update + on((event, emit) async { + try { + emit(FamilyLoadingState()); + Map status = await FamilyService.instance.update( + family: event.familyBackground, + relationshipId: event.relationshipId, + profileId: event.profileId, + token: event.token); + if (status['success']) { + families.removeWhere((element) => + element.relatedPerson!.id == + event.familyBackground.relatedPerson!.id); + FamilyBackground familyBackground = + FamilyBackground.fromJson(status['data']); + families.add(familyBackground); + emit(FamilyEditedState(response: status)); + } else { + emit(FamilyEditedState(response: status)); + } + } catch (e) { + emit(FamilyErrorState(message: e.toString())); + } + }); + + ////Delete + on((event, emit) async { + try { + final bool success = await FamilyService.instance.delete( + personRelatedId: event.id, + profileId: event.profileId, + token: event.token); + if (success) { + families + .removeWhere((element) => element.relatedPerson!.id == event.id); + emit(DeletedState(success: success)); + } else { + emit(DeletedState(success: success)); + } + } catch (e) { + emit(FamilyErrorState(message: e.toString())); + } + }); + on((event,emit){ + emit(FamilyErrorState(message: state.toString())); + }); + } +} diff --git a/lib/bloc/profile/family/family_event.dart b/lib/bloc/profile/family/family_event.dart new file mode 100644 index 0000000..a9fb8c5 --- /dev/null +++ b/lib/bloc/profile/family/family_event.dart @@ -0,0 +1,71 @@ +part of 'family_bloc.dart'; + +abstract class FamilyEvent extends Equatable { + const FamilyEvent(); + + @override + List get props => []; +} + +class GetFamilies extends FamilyEvent{ + final int profileId; + final String token; + const GetFamilies({required this.profileId, required this.token}); + + @override + List get props => [profileId,token]; +} + +class LoadFamily extends FamilyEvent{ + +} + +class ShowEditFamilyForm extends FamilyEvent{ + final FamilyBackground familyBackground; + const ShowEditFamilyForm({required this.familyBackground}); + @override + List get props => [familyBackground]; + +} +class AddFamily extends FamilyEvent{ + final int profileId; + final String token; + final int relationshipId; + final FamilyBackground familyBackground; + const AddFamily({required this.familyBackground, required this.profileId, required this.token, required this.relationshipId}); + @override + List get props => [profileId,token,familyBackground]; +} +class Updatefamily extends FamilyEvent{ + final int profileId; + final String token; + final int relationshipId; + + final FamilyBackground familyBackground; + const Updatefamily({required this.familyBackground, required this.profileId, required this.token, required this.relationshipId,}); + @override + List get props => [profileId,token,familyBackground]; +} + +class DeleteFamily extends FamilyEvent{ + final int id; + final int profileId; + final String token; + const DeleteFamily({required this.id, required this.profileId, required this.token}); +} +class AddEmergencyEvent extends FamilyEvent{ + final int profileId; + final int relatedPersonId; + final int? contactInfoId; + final String token; + final String? numberMail; + final String requestType; + const AddEmergencyEvent({required this.contactInfoId, required this.numberMail, required this.profileId, required this.relatedPersonId, required this.token, required this.requestType}); + @override + List get props => [profileId,token,relatedPersonId]; +} + +class CallErrorState extends FamilyEvent{ + final String message; + const CallErrorState({required this.message}); +} diff --git a/lib/bloc/profile/family/family_state.dart b/lib/bloc/profile/family/family_state.dart new file mode 100644 index 0000000..e7f3df3 --- /dev/null +++ b/lib/bloc/profile/family/family_state.dart @@ -0,0 +1,50 @@ +part of 'family_bloc.dart'; + +abstract class FamilyState extends Equatable { + const FamilyState(); + + @override + List get props => []; +} + +class FamilyInitial extends FamilyState {} + +class FamilyLoaded extends FamilyState{ + final List? families; + const FamilyLoaded({required this.families}); + + +} +class DeletedState extends FamilyState { + final bool success; + const DeletedState({required this.success}); + @override + List get props => [success]; +} +class FamilyAddedState extends FamilyState{ + final Map response; + const FamilyAddedState({required this.response}); + @override + List get props => [response]; +} +class EmergencyContactEditedState extends FamilyState{ + final Map response; + const EmergencyContactEditedState({required this.response}); + @override + List get props => [response]; +} +class FamilyEditedState extends FamilyState{ + final Map response; + const FamilyEditedState({required this.response}); + @override + List get props => [response]; +} +class FamilyErrorState extends FamilyState{ + final String message; + const FamilyErrorState({required this.message}); + @override + List get props => [message]; +} +class FamilyLoadingState extends FamilyState{ + +} diff --git a/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart b/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart new file mode 100644 index 0000000..ad53010 --- /dev/null +++ b/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart @@ -0,0 +1,375 @@ +import 'dart:io'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:unit2/model/location/country.dart'; +import 'package:unit2/model/location/region.dart'; +import 'package:unit2/sevices/profile/learningDevelopment_service.dart'; +import '../../../model/location/barangay.dart'; +import '../../../model/location/city.dart'; +import '../../../model/location/provinces.dart'; +import '../../../model/profile/attachment.dart'; +import '../../../model/profile/learning_development.dart'; +import '../../../model/utils/agency.dart'; +import '../../../model/utils/category.dart'; +import '../../../utils/attachment_services.dart'; +import '../../../utils/location_utilities.dart'; +import '../../../utils/profile_utilities.dart'; +import '../../../utils/request_permission.dart'; +import '../../../utils/urls.dart'; +part 'learning_development_event.dart'; +part 'learning_development_state.dart'; + +class LearningDevelopmentBloc + extends Bloc { + LearningDevelopmentBloc() : super(LearningDevelopmentInitial()) { + List learningsAndDevelopments = []; + List types = []; + List topics = []; + List globalCountries = []; + List globalRegions = []; + List globalProvinces = []; + List globalCities = []; + List globalBarangay = []; + List agencies = []; + List agencyCategory = []; + List attachmentCategories = []; + Region? currentRegion; + Country? currentCountry; + Province? currentProvince; + CityMunicipality? currentCity; + Barangay? currentBarangay; + + on((event, emit) async { + emit(LearningDevelopmentLoadingState()); + try { + if (attachmentCategories.isEmpty) { + attachmentCategories = + await AttachmentServices.instance.getCategories(); + } + List learnings = await LearningDevelopmentServices + .instance + .getLearningDevelopments(event.profileId, event.token); + learningsAndDevelopments = learnings; + emit(LearningDevelopmentLoadedState( + learningsAndDevelopment: learningsAndDevelopments,attachmentCategory: attachmentCategories)); + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + ////load + on((event, emit) { + emit(LearningDevelopmentLoadedState( + learningsAndDevelopment: learningsAndDevelopments,attachmentCategory: attachmentCategories)); + }); + //// show add form + on((event, emit) async { + try { + emit(LearningDevelopmentLoadingState()); + if (types.isEmpty) { + List newTypes = + await LearningDevelopmentServices.instance + .getLearningDevelopmentType(); + types = newTypes; + } + if (topics.isEmpty) { + List newTopics = + await LearningDevelopmentServices.instance.getTrainingTopics(); + topics = newTopics; + } + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + emit(LearningDevelopmentAddingState( + types: types, + topics: topics, + countries: globalCountries, + regions: globalRegions, + conductedBy: agencies, + sponsorAgencies: agencies, + agencyCategory: agencyCategory)); + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + ////Show edit form + on((event, emit) async { + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + currentCountry = globalCountries.firstWhere((Country country) => + event.learningDevelopment.conductedTraining!.venue!.country!.code == + country.code); + if (!event.isOverseas) { + //// if not overseas + currentRegion = globalRegions.firstWhere((Region region) => + event.learningDevelopment.conductedTraining!.venue! + .cityMunicipality!.province!.region!.code == + region.code); + + globalProvinces = await LocationUtils.instance + .getProvinces(regionCode: currentRegion!.code.toString()); + currentProvince = globalProvinces.firstWhere((Province province) => + event.learningDevelopment.conductedTraining!.venue! + .cityMunicipality!.province!.code == + province.code); + + globalCities = await LocationUtils.instance + .getCities(code: currentProvince!.code.toString()); + + currentCity = globalCities.firstWhere( + (CityMunicipality cityMunicipality) => + event.learningDevelopment.conductedTraining!.venue! + .cityMunicipality!.code == + cityMunicipality.code); + globalBarangay = await LocationUtils.instance + .getBarangay(code: currentCity!.code.toString()); + + if (event.learningDevelopment.conductedTraining?.venue?.barangay + ?.cityMunicipality != + null) { + currentBarangay = globalBarangay.firstWhere((Barangay barangay) => + event.learningDevelopment.conductedTraining!.venue!.barangay! + .code == + barangay.code); + } else { + currentBarangay = null; + } + } + if (topics.isEmpty) { + List newTopics = + await LearningDevelopmentServices.instance.getTrainingTopics(); + topics = newTopics; + } + if (types.isEmpty) { + List newTypes = + await LearningDevelopmentServices.instance + .getLearningDevelopmentType(); + types = newTypes; + } + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + emit(LearningDevelopmentUpdatingState( + cities: globalCities, + currentBarangay: currentBarangay, + barangay: globalBarangay, + provinces: globalProvinces, + types: types, + topics: topics, + training: event.learningDevelopment.conductedTraining!.title!, + learningDevelopement: event.learningDevelopment, + currentConductedBy: + event.learningDevelopment.conductedTraining!.conductedBy!, + currentSponsor: event.learningDevelopment.sponsoredBy, + conductedBy: agencies, + sponsorAgencies: agencies, + agencyCategory: agencyCategory, + countries: globalCountries, + regions: globalRegions, + currentRegion: currentRegion, + currentCountry: currentCountry!, + currentProvince: currentProvince, + currentCity: currentCity, + overseas: event.isOverseas)); + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + + ////Add + on((event, emit) async { + try { + Map status = + await LearningDevelopmentServices.instance.add( + learningDevelopement: event.learningDevelopement, + token: event.token, + profileId: event.profileId); + if (status['success']) { + LearningDevelopement learningDevelopement = + LearningDevelopement.fromJson(status['data']); + learningsAndDevelopments.add(learningDevelopement); + emit(LearningDevelopmentAddedState(response: status)); + } else { + emit(LearningDevelopmentAddedState(response: status)); + } + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + + ////Update + on((event, emit) async { + try { + Map status = + await LearningDevelopmentServices.instance.update( + learningDevelopement: event.learningDevelopement, + token: event.token, + profileId: event.profileId); + if (status['success']) { + learningsAndDevelopments.removeWhere((LearningDevelopement element) => + element.conductedTraining!.id == + event.learningDevelopement.conductedTraining!.id && + element.conductedTraining!.totalHours == + event.learningDevelopement.conductedTraining!.totalHours); + LearningDevelopement learningDevelopement = + LearningDevelopement.fromJson(status['data']); + learningsAndDevelopments.add(learningDevelopement); + emit(LearningDevelopmentUpdatedState(response: status)); + } else { + emit(LearningDevelopmentUpdatedState(response: status)); + } + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + ////delete + on((event, emit) async { + try { + final bool success = await LearningDevelopmentServices.instance.delete( + profileId: event.profileId, + token: event.token, + sponsorId: event.sponsorId, + totalHours: event.hours, + trainingId: event.trainingId); + if (success) { + learningsAndDevelopments.removeWhere((LearningDevelopement element) => + element.conductedTraining!.id == event.trainingId && + element.conductedTraining!.totalHours == event.hours); + emit(DeleteLearningDevelopmentState(success: success)); + } else { + emit(DeleteLearningDevelopmentState(success: success)); + } + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + //// call errror + on((event, emit) { + emit(LearningDevelopmentErrorState(message: event.message)); + }); + ////Add attachment + on((event, emit) async { + emit(LearningDevelopmentLoadingState()); + List attachments = []; + LearningDevelopement learningDevelopement = learningsAndDevelopments.firstWhere((element) => element.conductedTraining!.id.toString () == event.attachmentModule); + try { + Map status = await AttachmentServices.instance + .attachment( + categoryId: event.categoryId, + module: event.attachmentModule, + paths: event.filePaths, + token: event.token, + profileId: event.profileId); + if (status['success']) { + status['data'].forEach((element){ + Attachment newAttachment = Attachment.fromJson(element); + attachments.add(newAttachment); + }); + learningDevelopement.attachments == null? learningDevelopement.attachments = attachments:learningDevelopement.attachments = [...learningDevelopement.attachments!,...attachments]; + emit(LearningDevelopmentAddedState(response: status)); + } else { + emit(LearningDevelopmentAddedState(response: status)); + } + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + ////Delete Attachment + on((event, emit) async { + emit(LearningDevelopmentLoadingState()); + try { + final bool success = await AttachmentServices.instance.deleteAttachment( + attachment: event.attachment, + moduleId: event.moduleId, + profileId: event.profileId.toString(), + token: event.token); + if (success) { + final LearningDevelopement learningDevelopement = + learningsAndDevelopments + .firstWhere((element) => element.conductedTraining!.id == event.moduleId); + learningDevelopement.attachments + ?.removeWhere((element) => element.id == event.attachment.id); + learningsAndDevelopments + .removeWhere((element) => element.conductedTraining!.id == event.moduleId); + learningsAndDevelopments.add(learningDevelopement); + emit(LearningDevAttachmentDeletedState(success: success)); + } else { + emit(LearningDevAttachmentDeletedState(success: success)); + } + } catch (e) { + emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + on((event,emit){ + String fileUrl = '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(LearningAndDevelopmentAttachmentViewState(fileUrl: fileUrl, filename: event.filename)); + }); + on((event, emit) async { + emit(LearningDevelopmentLoadingState()); + Directory directory; + String? appDocumentPath; + if (await requestPermission(Permission.storage)) { + directory = await getApplicationDocumentsDirectory(); + appDocumentPath = directory.path; + } + try{ + final bool success = await AttachmentServices.instance.downloadAttachment( + filename: event.fileName, + source: event.source, + downLoadDir: appDocumentPath!); + if (success) { + final result = await Share.shareXFiles( + [XFile("$appDocumentPath/${event.fileName}")]); + if (result.status == ShareResultStatus.success) { + Fluttertoast.showToast(msg: "Attachment shared successful"); + emit(LearningAndDevelopmentAttachmentViewState( + fileUrl: event.source, filename: event.fileName)); + } else { + Fluttertoast.showToast(msg: "Attachment shared unsuccessful"); + emit(LearningAndDevelopmentAttachmentViewState( + fileUrl: event.source, filename: event.fileName)); + } + } else { + emit(LearningAndDevelopmentAttachmentViewState( + fileUrl: event.source, filename: event.fileName)); + } + }catch(e){ +emit(LearningDevelopmentErrorState(message: e.toString())); + } + }); + } + +} diff --git a/lib/bloc/profile/learningDevelopment/learning_development_event.dart b/lib/bloc/profile/learningDevelopment/learning_development_event.dart new file mode 100644 index 0000000..e134560 --- /dev/null +++ b/lib/bloc/profile/learningDevelopment/learning_development_event.dart @@ -0,0 +1,103 @@ +part of 'learning_development_bloc.dart'; + +abstract class LearningDevelopmentEvent extends Equatable { + const LearningDevelopmentEvent(); + + @override + List get props => []; +} + +class GetLearningDevelopments extends LearningDevelopmentEvent { + final int profileId; + final String token; + const GetLearningDevelopments({required this.profileId, required this.token}); + + @override + List get props => [profileId, token]; +} + +class ShowAddLearningDevelopmentForm extends LearningDevelopmentEvent{ + +} +class ShowEditLearningDevelopmentForm extends LearningDevelopmentEvent{ + final LearningDevelopement learningDevelopment; + final int profileId; + final String token; + final bool isOverseas; + const ShowEditLearningDevelopmentForm({required this.isOverseas, required this.learningDevelopment, required this.profileId, required this.token}); +} +class LoadLearniningDevelopment extends LearningDevelopmentEvent{ + +} +////delete +class DeleteLearningDevelopment extends LearningDevelopmentEvent { + final String token; + final int profileId; + final int? sponsorId; + final int trainingId; + final double hours; + const DeleteLearningDevelopment( + {required this.profileId, required this.token, required this.hours,required this.sponsorId, required this.trainingId}); + @override + List get props => [profileId, token, hours,trainingId]; +} + +////add +class AddLearningAndDevelopment extends LearningDevelopmentEvent{ + final LearningDevelopement learningDevelopement; + final int profileId; + final String token; + const AddLearningAndDevelopment({required this.learningDevelopement, required this.profileId, required this.token}); + @override + List get props => [profileId, token,learningDevelopement]; +} + +////update +class UpdateLearningDevelopment extends LearningDevelopmentEvent{ + final LearningDevelopement learningDevelopement; + final int profileId; + final String token; + const UpdateLearningDevelopment({required this.learningDevelopement, required this.profileId, required this.token}); + @override + List get props => [profileId, token,learningDevelopement]; +} + +class CallErrorState extends LearningDevelopmentEvent{ + final String message; + const CallErrorState({required this.message}); +} + +////Add Attachment +class AddALearningDevttachment extends LearningDevelopmentEvent{ + final String categoryId; + final String attachmentModule; + final List filePaths; + final String token; + final String profileId; + const AddALearningDevttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token}); + @override + List get props => [categoryId,attachmentModule,filePaths, token,profileId]; +} + +//// Delete Attachment +class DeleteLearningDevAttachment extends LearningDevelopmentEvent{ + final int moduleId; + final Attachment attachment; + final String token; + final int profileId; + const DeleteLearningDevAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token}); +} + +class LearningDevelopmentViewAttachmentEvent extends LearningDevelopmentEvent{ + final String filename; + final String source; + const LearningDevelopmentViewAttachmentEvent({required this.source, required this.filename}); +} + +class ShareAttachment extends LearningDevelopmentEvent{ + final String fileName; + final String source; + const ShareAttachment({required this.fileName, required this.source}); +} + + diff --git a/lib/bloc/profile/learningDevelopment/learning_development_state.dart b/lib/bloc/profile/learningDevelopment/learning_development_state.dart new file mode 100644 index 0000000..a5dbb78 --- /dev/null +++ b/lib/bloc/profile/learningDevelopment/learning_development_state.dart @@ -0,0 +1,146 @@ +part of 'learning_development_bloc.dart'; + +abstract class LearningDevelopmentState extends Equatable { + const LearningDevelopmentState(); + + @override + List get props => []; +} + +class LearningDevelopmentInitial extends LearningDevelopmentState {} + +class LearningDevelopmentLoadedState extends LearningDevelopmentState { + final List attachmentCategory; + final List learningsAndDevelopment; + const LearningDevelopmentLoadedState( + {required this.learningsAndDevelopment, + required this.attachmentCategory}); + @override + List get props => [learningsAndDevelopment]; +} + +class LearningDevelopmentLoadingState extends LearningDevelopmentState {} + +////added State +class LearningDevelopmentAddedState extends LearningDevelopmentState { + final Map response; + const LearningDevelopmentAddedState({required this.response}); + @override + List get props => [response]; +} + +////Updated State +class LearningDevelopmentUpdatedState extends LearningDevelopmentState { + final Map response; + const LearningDevelopmentUpdatedState({required this.response}); + @override + List get props => [response]; +} + +//// Deleted State +class DeleteLearningDevelopmentState extends LearningDevelopmentState { + final bool success; + const DeleteLearningDevelopmentState({required this.success}); + @override + List get props => [success]; +} + +////Update State +class LearningDevelopmentUpdatingState extends LearningDevelopmentState { + final List types; + final List topics; + final LearningDevelopmentType training; + final LearningDevelopement learningDevelopement; + final Agency currentConductedBy; + final Agency? currentSponsor; + final List conductedBy; + final List sponsorAgencies; + final List agencyCategory; + final List countries; + final List regions; + final List provinces; + final List barangay; + final List cities; + final Region? currentRegion; + final Country currentCountry; + final Province? currentProvince; + final CityMunicipality? currentCity; + final Barangay? currentBarangay; + final bool overseas; + + const LearningDevelopmentUpdatingState( + {required this.currentBarangay, + required this.cities, + required this.barangay, + required this.provinces, + required this.types, + required this.topics, + required this.training, + required this.learningDevelopement, + required this.currentConductedBy, + required this.currentSponsor, + required this.conductedBy, + required this.sponsorAgencies, + required this.agencyCategory, + required this.countries, + required this.regions, + required this.currentRegion, + required this.currentCountry, + required this.currentProvince, + required this.currentCity, + required this.overseas}); +} + +////Adding State +class LearningDevelopmentAddingState extends LearningDevelopmentState { + final List types; + final List topics; + final List conductedBy; + final List sponsorAgencies; + final List countries; + final List regions; + final List agencyCategory; + + const LearningDevelopmentAddingState( + {required this.types, + required this.topics, + required this.countries, + required this.regions, + required this.conductedBy, + required this.sponsorAgencies, + required this.agencyCategory}); +} + +class LearningDevelopmentErrorState extends LearningDevelopmentState { + final String message; + const LearningDevelopmentErrorState({required this.message}); +} + +////Attachment AddedState +class LearningDevAttachmentAddedState extends LearningDevelopmentState { + final Map response; + const LearningDevAttachmentAddedState({required this.response}); + @override + List get props => [response]; +} + + + +////Attachment Deleted State State +class LearningDevAttachmentDeletedState extends LearningDevelopmentState { + final bool success; + const LearningDevAttachmentDeletedState({required this.success}); + @override + List get props => [success]; +} + + +class LearningAndDevelopmentAttachmentViewState extends LearningDevelopmentState { + final String filename; + final String fileUrl; + const LearningAndDevelopmentAttachmentViewState({required this.fileUrl, required this.filename}); +} +class LearningDevelopmentAttachmentShareState extends LearningDevelopmentState{ + final bool success; + const LearningDevelopmentAttachmentShareState({required this.success,}); +} diff --git a/lib/bloc/profile/other_information/hobbies/hoobies_bloc.dart b/lib/bloc/profile/other_information/hobbies/hoobies_bloc.dart new file mode 100644 index 0000000..f9034da --- /dev/null +++ b/lib/bloc/profile/other_information/hobbies/hoobies_bloc.dart @@ -0,0 +1,118 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/skillshobbies_services.dart'; + +import '../../../../model/profile/other_information/skills_and_hobbies.dart'; + +part 'hoobies_event.dart'; +part 'hoobies_state.dart'; + +class HoobiesBloc extends Bloc { + HoobiesBloc() : super(HoobiesInitial()) { + List skillsAndHobbies = []; + List allSkillsAndHobbies = []; + List mySkillsAndHobbies = []; + on((event, emit) async { + emit(HobbiesLoadingState()); + try { + if(skillsAndHobbies.isEmpty){ + List hobbies = await SkillsHobbiesServices.instance + .getSkillsHobbies(event.profileId, event.token); + skillsAndHobbies = hobbies; + } + emit(HobbiesLoadedState(skillsAndHobbies: skillsAndHobbies)); + } catch (e) { + emit(HobbiesErrorState(message: e.toString())); + } + }); + on((event,emit){ + skillsAndHobbies = event.skillsHobbies; + emit(HobbiesLoadedState(skillsAndHobbies: skillsAndHobbies)); + }); + ////SHOW ADD FORM + on((event, emit) async { + emit(HobbiesLoadingState()); + try { + ////get all skills and hobbies + if (allSkillsAndHobbies.isEmpty) { + allSkillsAndHobbies = + await SkillsHobbiesServices.instance.getAllSkillsHobbies(); + } + for (var element in skillsAndHobbies) { + mySkillsAndHobbies.add(element.name!); + } + allSkillsAndHobbies.sort((a, b) => a.name!.compareTo(b.name!)); + emit(AddHobbySkillState( + mySkillsAndHobbiesString: mySkillsAndHobbies, + allSkillsAndHobbies: allSkillsAndHobbies, + mySkillsAndHobbiesObject: skillsAndHobbies)); + } catch (e) { + emit(HobbiesErrorState(message: e.toString())); + } + }); + ////GET ADDED SKILLS HOBBIES + on((event, emit) { + emit(HobbiesLoadingState()); + List added = event.addedHobbiesSkills.split(","); + + for (var element in added) { + if (element.isNotEmpty) { + SkillsHobbies newSkillsHobbies = + SkillsHobbies(id: null, name: element.toUpperCase()); + skillsAndHobbies.add(newSkillsHobbies); + allSkillsAndHobbies.add(newSkillsHobbies); + } + } + for (var element in skillsAndHobbies) { + mySkillsAndHobbies.add(element.name!); + } + allSkillsAndHobbies.sort((a, b) => a.name!.compareTo(b.name!)); + emit(AddHobbySkillState( + mySkillsAndHobbiesString: mySkillsAndHobbies, + allSkillsAndHobbies: allSkillsAndHobbies, + mySkillsAndHobbiesObject: skillsAndHobbies)); + }); + ////SHOW ADD MODAL + on((event, emit) { + emit(ShowAddModalState()); + }); + + //// ADD + on((event, emit) async { + emit(HobbiesLoadingState()); + Map response = await SkillsHobbiesServices.instance.add( + skillsHobbies: event.skillsHobbies, + profileId: event.profileId, + token: event.token); + List newSkillsHobbies = []; + if (response['success']) { + if (response['data']['skill_hobby'] != null) { + for (var element in response['data']['skill_hobby']) { + newSkillsHobbies.add(SkillsHobbies.fromJson(element)); + } + } + skillsAndHobbies = newSkillsHobbies; + emit(HobbiesAndSkillsAddedState( + mySkillsAndHobbies: skillsAndHobbies, status: response)); + } else { + emit(HobbiesAndSkillsAddedState( + mySkillsAndHobbies: skillsAndHobbies, status: response)); + } + }); + ////DELETE + on((event,emit)async{ + emit(HobbiesLoadingState()); + // try{ + bool success = await SkillsHobbiesServices.instance.delete(profileId: event.profileId, token: event.token, skillsHobbies: event.skillsHobbies); + if(success){ + skillsAndHobbies.removeWhere((element) => element.id == event.skillsHobbies[0].id); + emit(HobbiesAndSkillsDeletedState(skillsHobbies: skillsAndHobbies, success: success)); + }else{ + emit(HobbiesAndSkillsDeletedState(skillsHobbies: skillsAndHobbies, success: success)); + } + // }catch(e){ + // emit (HobbiesErrorState(message: e.toString())); + // } + }); + } +} diff --git a/lib/bloc/profile/other_information/hobbies/hoobies_event.dart b/lib/bloc/profile/other_information/hobbies/hoobies_event.dart new file mode 100644 index 0000000..7a9abb5 --- /dev/null +++ b/lib/bloc/profile/other_information/hobbies/hoobies_event.dart @@ -0,0 +1,52 @@ +part of 'hoobies_bloc.dart'; + +abstract class HobbiesEvent extends Equatable { + const HobbiesEvent(); + + @override + List get props => []; +} + +class GetSkillsHobbies extends HobbiesEvent{ + final int profileId; + final String token; + const GetSkillsHobbies({required this.profileId, required this.token}); + @override + List get props => [profileId,token]; +} +class ShowHobbySkillAddForm extends HobbiesEvent{ + + const ShowHobbySkillAddForm(); + +} +class AddHobbyAndSkills extends HobbiesEvent{ + final int profileId; + final String token; + final List skillsHobbies; + const AddHobbyAndSkills({required this.profileId,required this.token, required this.skillsHobbies}); + @override + List get props => [profileId,token]; +} + +class GetAddedHobbiesSkills extends HobbiesEvent{ + final String addedHobbiesSkills; + + + const GetAddedHobbiesSkills({required this.addedHobbiesSkills}); + @override + List get props => [addedHobbiesSkills]; +} +class ShowAddModal extends HobbiesEvent{ + +} + +class LoadHobbiesSkills extends HobbiesEvent{ + final List skillsHobbies; + const LoadHobbiesSkills({required this.skillsHobbies}); +} +class DeleteSkillHobbies extends HobbiesEvent{ + final int profileId; + final String token; + final List skillsHobbies; + const DeleteSkillHobbies({required this.profileId, required this.skillsHobbies, required this.token}); +} \ No newline at end of file diff --git a/lib/bloc/profile/other_information/hobbies/hoobies_state.dart b/lib/bloc/profile/other_information/hobbies/hoobies_state.dart new file mode 100644 index 0000000..858fd3a --- /dev/null +++ b/lib/bloc/profile/other_information/hobbies/hoobies_state.dart @@ -0,0 +1,58 @@ +part of 'hoobies_bloc.dart'; + +abstract class HobbiesState extends Equatable { + const HobbiesState(); + + @override + List get props => []; +} + +class HoobiesInitial extends HobbiesState {} + +class HobbiesLoadedState extends HobbiesState{ + final List skillsAndHobbies; + const HobbiesLoadedState({required this.skillsAndHobbies}); + @override + List get props => [skillsAndHobbies]; +} +class HobbiesErrorState extends HobbiesState{ + final String message; + const HobbiesErrorState({required this.message}); + + @override + List get props => [message]; + +} +class AddHobbySkillState extends HobbiesState{ + final List mySkillsAndHobbiesString; + final List allSkillsAndHobbies; + final List mySkillsAndHobbiesObject; + + const AddHobbySkillState({required this.mySkillsAndHobbiesString,required this.allSkillsAndHobbies,required this.mySkillsAndHobbiesObject}); + @override + List get props => [mySkillsAndHobbiesString,allSkillsAndHobbies,mySkillsAndHobbiesObject]; +} + +class HobbiesLoadingState extends HobbiesState{ + +} + +//// show add modal for adding new skills and hobbies +class ShowAddModalState extends HobbiesState{ + +} +//// hobbies and skills already added +class HobbiesAndSkillsAddedState extends HobbiesState{ + final List mySkillsAndHobbies; + final Map status; + const HobbiesAndSkillsAddedState({required this.mySkillsAndHobbies, required this.status}); + @override + List get props => [mySkillsAndHobbies,status]; +} +class HobbiesAndSkillsDeletedState extends HobbiesState{ + final bool success; + final List skillsHobbies; + const HobbiesAndSkillsDeletedState({required this.skillsHobbies,required this.success}); +} + + diff --git a/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart new file mode 100644 index 0000000..3806f7f --- /dev/null +++ b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart @@ -0,0 +1,168 @@ +import 'dart:math'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/profile/non_academic_services.dart'; + +import '../../../../model/profile/other_information/non_acedimic_recognition.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../utils/profile_utilities.dart'; + +part 'non_academic_recognition_event.dart'; +part 'non_academic_recognition_state.dart'; + +class NonAcademicRecognitionBloc + extends Bloc { + NonAcademicRecognitionBloc() : super(NonAcademicRecognitionInitial()) { + List nonAcademicRecognitions = []; + List agencies = []; + List agencyCategory = []; + ////GET + on((event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + if (nonAcademicRecognitions.isEmpty) { + List recognitions = + await NonAcademicRecognitionServices.instance + .getNonAcademicRecognition(event.profileId!, event.token!); + nonAcademicRecognitions = recognitions; + } + + emit(NonAcademicRecognitionLoadedState( + nonAcademicRecognition: nonAcademicRecognitions)); + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }); + + ////LOAD + on((event,emit){ + + emit(NonAcademicRecognitionLoadedState(nonAcademicRecognition: nonAcademicRecognitions)); + }); +////SHOW ADD FORM + on( + (event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (agencyCategory.isEmpty) { + List newAgencyCategories = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = newAgencyCategories; + } + emit(AddNonAcademeRecognitionState( + agencies: agencies, agencyCategories: agencyCategory)); + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }, + ); + ////SHOW EDIT FORM + on((event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (agencyCategory.isEmpty) { + List newAgencyCategories = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = newAgencyCategories; + } + emit(EditNonAcademeRecognitionState( + agencies: agencies, + agencyCategories: agencyCategory, + nonAcademicRecognition: event.nonAcademicRecognition)); + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }); + ////ADD + on((event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + Map status = + await NonAcademicRecognitionServices.instance.add( + token: event.token, + profileId: event.profileId, + nonAcademicRecognition: event.nonAcademicRecognition); + if (status['success']) { + NonAcademicRecognition nonAcademicRecognition = + NonAcademicRecognition.fromJson(status['data']); + nonAcademicRecognitions.add(nonAcademicRecognition); + emit(NonAcademeRecognitionAddedState( + response: status, + nonAcademicRecognition: nonAcademicRecognitions)); + } else { + emit(NonAcademeRecognitionAddedState( + response: status, + nonAcademicRecognition: nonAcademicRecognitions)); + } + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }); +////EDIT + on((event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + Map status = + await NonAcademicRecognitionServices.instance.update( + nonAcademicRecognition: event.nonAcademicRecognition, + profileId: event.profileId, + token: event.token); + if (status['success']) { + NonAcademicRecognition newNonAcademeRecognition = + NonAcademicRecognition.fromJson(status['data']); + nonAcademicRecognitions.removeWhere( + (element) => element.id == event.nonAcademicRecognition.id); + nonAcademicRecognitions.add(newNonAcademeRecognition); + emit(NonAcademeRecognitionEditedState( + nonAcademicRecognitions: nonAcademicRecognitions, + response: status)); + }else{ + emit(NonAcademeRecognitionEditedState( + nonAcademicRecognitions: nonAcademicRecognitions, + response: status)); + } + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }); + + ////DELETE + on((event, emit) async { + emit(NonAcademicRecognitionLoadingState()); + try { + final bool success = await NonAcademicRecognitionServices.instance + .delete( + title: event.nonAcademicRecognition.title!, + id: event.nonAcademicRecognition.id!, + token: event.token, + profileId: event.profileId); + if (success) { + event.nonAcademicRecognitions.removeWhere( + (element) => element.id == event.nonAcademicRecognition.id); + nonAcademicRecognitions = event.nonAcademicRecognitions; + emit(NonAcademeRecognitionDeletedState( + nonAcademicRecognitions: nonAcademicRecognitions, + success: success)); + } else { + emit(NonAcademeRecognitionDeletedState( + nonAcademicRecognitions: nonAcademicRecognitions, + success: success)); + } + } catch (e) { + emit(NonAcademicRecognitionErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_event.dart b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_event.dart new file mode 100644 index 0000000..27dee89 --- /dev/null +++ b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_event.dart @@ -0,0 +1,67 @@ +part of 'non_academic_recognition_bloc.dart'; + +abstract class NonAcademicRecognitionEvent extends Equatable { + const NonAcademicRecognitionEvent(); + + @override + List get props => []; +} +//// GET EVENT +class GetNonAcademicRecognition extends NonAcademicRecognitionEvent{ + final int? profileId; + final String? token; + const GetNonAcademicRecognition({ this.profileId, this.token}); +} +////LOAD EVENT +class LoadNonAcademeRecognition extends NonAcademicRecognitionEvent{ + + const LoadNonAcademeRecognition(); + @override + List get props => []; +} + +////SHOW ADD FORM EVENT +class ShowAddNonAcademeRecognitionForm extends NonAcademicRecognitionEvent{ + +} + +//// SHOW EDIT FORM +class ShowEditNonAcademicRecognitionForm extends NonAcademicRecognitionEvent{ + final NonAcademicRecognition nonAcademicRecognition; + const ShowEditNonAcademicRecognitionForm({required this.nonAcademicRecognition}); + @override + List get props => [nonAcademicRecognition]; +} + +//// ADD EVENT +class AddNonAcademeRecognition extends NonAcademicRecognitionEvent{ + final int profileId; + final String token; + final NonAcademicRecognition nonAcademicRecognition; + const AddNonAcademeRecognition({required this.nonAcademicRecognition, required this.profileId, required this.token}); + @override + List get props => [nonAcademicRecognition,profileId,token]; +} + +//// EDIT EVENT +class EditNonAcademeRecognition extends NonAcademicRecognitionEvent{ + final NonAcademicRecognition nonAcademicRecognition; + final String token; + final int profileId; + const EditNonAcademeRecognition({required this.nonAcademicRecognition, required this.profileId, required this.token}); + @override + List get props => [nonAcademicRecognition,profileId,token]; +} + +//// DELETE EVENT +class DeleteNonAcademeRecognition extends NonAcademicRecognitionEvent{ + final int profileId; + final String token; + final List nonAcademicRecognitions; + final NonAcademicRecognition nonAcademicRecognition; + const DeleteNonAcademeRecognition({required this.nonAcademicRecognitions, required this.nonAcademicRecognition,required this.profileId,required this.token}); + @override + List get props => [profileId,token,nonAcademicRecognition,nonAcademicRecognitions]; + +} + diff --git a/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_state.dart b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_state.dart new file mode 100644 index 0000000..f09e17e --- /dev/null +++ b/lib/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_state.dart @@ -0,0 +1,79 @@ +part of 'non_academic_recognition_bloc.dart'; + +abstract class NonAcademicRecognitionState extends Equatable { + const NonAcademicRecognitionState(); + + @override + List get props => []; +} + +class NonAcademicRecognitionInitial extends NonAcademicRecognitionState {} + +////LOADING STATE +class NonAcademicRecognitionLoadingState extends NonAcademicRecognitionState {} + +////LOADED STATE +class NonAcademicRecognitionLoadedState extends NonAcademicRecognitionState { + final List nonAcademicRecognition; + const NonAcademicRecognitionLoadedState( + {required this.nonAcademicRecognition}); + @override + List get props => []; +} + +////DELETED STATE +class NonAcademeRecognitionDeletedState extends NonAcademicRecognitionState { + final List nonAcademicRecognitions; + final bool success; + const NonAcademeRecognitionDeletedState( + {required this.nonAcademicRecognitions, required this.success}); + @override + List get props => [nonAcademicRecognitions, success]; +} + +class NonAcademeRecognitionEditedState extends NonAcademicRecognitionState{ + final List nonAcademicRecognitions; + final Map response; + const NonAcademeRecognitionEditedState( + {required this.nonAcademicRecognitions, required this.response}); + @override + List get props => [nonAcademicRecognitions, response]; +} + +////ADDED STATE +class NonAcademeRecognitionAddedState extends NonAcademicRecognitionState { + final List nonAcademicRecognition; + final Map response; + const NonAcademeRecognitionAddedState( + {required this.nonAcademicRecognition, required this.response}); + @override + List get props => [nonAcademicRecognition, response]; +} + +////ADDING STATE +class AddNonAcademeRecognitionState extends NonAcademicRecognitionState { + final List agencies; + final List agencyCategories; + const AddNonAcademeRecognitionState( + {required this.agencies, required this.agencyCategories}); + @override + List get props => [agencies, agencyCategories]; +} + +class EditNonAcademeRecognitionState extends NonAcademicRecognitionState { + final List agencies; + final List agencyCategories; + final NonAcademicRecognition nonAcademicRecognition; + const EditNonAcademeRecognitionState({required this.agencies, required this.agencyCategories,required this.nonAcademicRecognition}); + @override + List get props => [agencies, agencyCategories,nonAcademicRecognition]; +} + +////ERROR STATE +class NonAcademicRecognitionErrorState extends NonAcademicRecognitionState { + final String message; + const NonAcademicRecognitionErrorState({required this.message}); + + @override + List get props => []; +} diff --git a/lib/bloc/profile/other_information/org_membership/organization_membership_bloc.dart b/lib/bloc/profile/other_information/org_membership/organization_membership_bloc.dart new file mode 100644 index 0000000..5d27e0b --- /dev/null +++ b/lib/bloc/profile/other_information/org_membership/organization_membership_bloc.dart @@ -0,0 +1,94 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/category.dart'; +import 'package:unit2/sevices/profile/orgmembership_services.dart'; +import 'package:unit2/utils/profile_utilities.dart'; + +import '../../../../model/profile/other_information/organization_memberships.dart'; + +part 'organization_membership_event.dart'; +part 'organization_membership_state.dart'; + +class OrganizationMembershipBloc + extends Bloc { + List agencies = []; + List agencyCategory = []; + OrganizationMembershipBloc() : super(OrganizationMembershipInitial()) { + List organizationMemberships = []; + on((event, emit) async { + emit(OrgmembershipLoadingState()); + try { + if (organizationMemberships.isEmpty) { + List orgs = + await OrganizationMembershipServices.instance + .getOrgMemberships(event.profileId!, event.token!); + organizationMemberships = orgs; + } + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (agencyCategory.isEmpty) { + List newAgencyCategories = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = newAgencyCategories; + } + emit(OrganizationMembershipLoaded( + orgMemberships: organizationMemberships, + agencies: agencies, + agencyCategory: agencyCategory)); + } catch (e) { + emit(OrganizationMembershipErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(OrganizationMembershipLoaded( + orgMemberships: organizationMemberships, + agencies: agencies, + agencyCategory: agencyCategory)); + }); + //// ADD ORGMEMBERSHIP + on((event, emit) async { + try { + emit(OrgmembershipLoadingState()); + Map status = + await OrganizationMembershipServices.instance.add( + agency: event.agency, + token: event.token, + profileId: event.profileId.toString()); + if (status["success"]) { + OrganizationMembership organizationMembership = + OrganizationMembership.fromJson(status["data"]); + organizationMemberships.add(organizationMembership); + emit(OrgMembershipAddedState(response: status)); + } else { + emit(OrgMembershipAddedState(response: status)); + } + } catch (e) { + emit(OrganizationMembershipErrorState(message: e.toString())); + } + }); + ////DELETE ORGMEMBERSHIP + on((event, emit) async { + emit(OrgmembershipLoadingState()); + try { + final bool success = await OrganizationMembershipServices.instance + .delete( + agency: event.org.agency!, + profileId: event.profileId, + token: event.token); + if (success) { + organizationMemberships.removeWhere( + (element) => element.agency!.id == event.org.agency!.id); + emit(OrgMembershipDeletedState(success: success)); + } else { + emit(OrgMembershipDeletedState(success: success)); + } + } catch (e) { + emit(OrganizationMembershipErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/other_information/org_membership/organization_membership_event.dart b/lib/bloc/profile/other_information/org_membership/organization_membership_event.dart new file mode 100644 index 0000000..a85a91a --- /dev/null +++ b/lib/bloc/profile/other_information/org_membership/organization_membership_event.dart @@ -0,0 +1,43 @@ +part of 'organization_membership_bloc.dart'; + +abstract class OrganizationMembershipEvent extends Equatable { + const OrganizationMembershipEvent(); + + @override + List get props => []; +} + +class LoadOrganizationMemberships extends OrganizationMembershipEvent{ + + @override + List get props => []; +} + +class GetOrganizationMembership extends OrganizationMembershipEvent{ + final int? profileId; + final String? token; + const GetOrganizationMembership({this.profileId, this.token}); + +} +class ShowAddOrgMembershipForm extends OrganizationMembershipEvent{ + +} +class AddOrgMembership extends OrganizationMembershipEvent{ + final int profileId; + final String token; + final Agency agency; + const AddOrgMembership({required this.agency, required this.profileId, required this.token}); + @override + List get props => [profileId,token,agency]; +} + +class DeleteOrgMemberShip extends OrganizationMembershipEvent{ + final int profileId; + final String token; + final OrganizationMembership org; + + const DeleteOrgMemberShip({required this.profileId, required this.token, required this.org,}); + @override + List get props => [profileId,token,org]; + +} diff --git a/lib/bloc/profile/other_information/org_membership/organization_membership_state.dart b/lib/bloc/profile/other_information/org_membership/organization_membership_state.dart new file mode 100644 index 0000000..15d4ff5 --- /dev/null +++ b/lib/bloc/profile/other_information/org_membership/organization_membership_state.dart @@ -0,0 +1,52 @@ +part of 'organization_membership_bloc.dart'; + +abstract class OrganizationMembershipState extends Equatable { + const OrganizationMembershipState(); + + @override + List get props => []; +} + +class OrganizationMembershipInitial extends OrganizationMembershipState {} + +class OrganizationMembershipLoaded extends OrganizationMembershipState { + final List orgMemberships; + final List agencies; + final List agencyCategory; + const OrganizationMembershipLoaded( + {required this.orgMemberships, + required this.agencies, + required this.agencyCategory}); + @override + List get props => [orgMemberships]; +} + +class OrganizationMembershipErrorState extends OrganizationMembershipState { + final String message; + const OrganizationMembershipErrorState({required this.message}); + @override + List get props => [message]; +} + +class OrgmembershipLoadingState extends OrganizationMembershipState {} + +class OrgMembershipDeletedState extends OrganizationMembershipState { + final bool success; + const OrgMembershipDeletedState({required this.success}); + @override + List get props => [success]; +} + +class OrgMembershipAddedState extends OrganizationMembershipState { + final Map response; + const OrgMembershipAddedState({required this.response}); + @override + List get props => [response]; +} + +class AddOrgMembershipState extends OrganizationMembershipState { + final List agencies; + final List agencyCategories; + const AddOrgMembershipState( + {required this.agencies, required this.agencyCategories}); +} diff --git a/lib/bloc/profile/primary_information/address/address_bloc.dart b/lib/bloc/profile/primary_information/address/address_bloc.dart new file mode 100644 index 0000000..5bcdd5c --- /dev/null +++ b/lib/bloc/profile/primary_information/address/address_bloc.dart @@ -0,0 +1,205 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/location/subdivision.dart'; +import 'package:unit2/sevices/profile/address_service.dart'; + +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/profile/basic_information/adress.dart'; +import '../../../../utils/location_utilities.dart'; + +part 'address_event.dart'; +part 'address_state.dart'; + +class AddressBloc extends Bloc { + AddressBloc() : super(AddressInitial()) { + List globalCountries = []; + List globalRegions = []; + List addresses = []; + List provinces = []; + List cities = []; + List barangays = []; + Region? currentRegion; + Country currentCountry; + Province? currentProvince; + CityMunicipality? currentCity; + Barangay? currentBarangay; + on((event, emit) { + emit(AddressLoadingState()); + try { + addresses = event.addresses; + emit(AddressLoadedState(addresses: addresses)); + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); + ////Load + on((event, emit) { + emit(AddressLoadedState(addresses: addresses)); + }); + + //// show add form + on((event, emit) async { + emit(AddressLoadingState()); + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + + emit(AddAddressState( + countries: globalCountries, regions: globalRegions)); + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); + + //// Show Edit Form + on((event, emit) async { + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + currentCountry = globalCountries.firstWhere((Country country) => + event.address.address!.country!.code == country.code); + + if (!event.overseas) { + //// if not overseas + currentRegion = globalRegions.firstWhere((Region region) => + event.address.address!.cityMunicipality!.province!.region!.code == + region.code); + provinces = await LocationUtils.instance + .getProvinces(regionCode: currentRegion!.code.toString()); + currentProvince = provinces.firstWhere((Province province) => + event.address.address!.cityMunicipality!.province!.code == + province.code); + + cities = await LocationUtils.instance + .getCities(code: currentProvince!.code.toString()); + + currentCity = cities.firstWhere((CityMunicipality cityMunicipality) => + event.address.address!.cityMunicipality!.code == + cityMunicipality.code); + barangays = await LocationUtils.instance + .getBarangay(code: currentCity!.code.toString()); + if (event.address.address?.barangay != null) { + currentBarangay = barangays.firstWhere((Barangay barangay) => + event.address.address?.barangay?.code == barangay.code); + } else { + currentBarangay = null; + } + } + + emit(EditAddressState( + countries: globalCountries, + regions: globalRegions, + address: event.address, + baragays: barangays, + cities: cities, + currentCity: currentCity, + currentCountry: currentCountry, + currentProvince: currentProvince, + currentRegion: currentRegion, + overseas: event.overseas, + provinces: provinces, + currentBarangay: currentBarangay)); + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); + ////Add + on( + (event, emit) async { + try { + Map status = await AddressService.instance.add( + address: event.address, + categoryId: event.categoryId, + token: event.token, + details: event.details, + blockNumber: event.blockNumber, + lotNumber: event.lotNumber, + profileId: event.profileId); + if (status['success']) { + AddressClass addressClass = AddressClass.fromJson(status['data']['address']); + Subdivision? subdivision = status['data']['subdivision'] !=null? Subdivision.fromJson(status['data']['subdivision']):null; + MainAdress address = MainAdress(address: addressClass,subdivision: subdivision,id: status['data']['id'],details: status['data']['details']); + addresses.add(address); + emit(AddressAddedState(response: status)); + } else { + emit(AddressAddedState(response: status)); + } + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }, + ); + ////update + on( + (event, emit) async { + try { + Map status = await AddressService.instance.update( + address: event.address, + categoryId: event.categoryId, + token: event.token, + details: event.details, + blockNumber: event.blockNumber, + lotNumber: event.lotNumber, + profileId: event.profileId); + if (status['success']) { + AddressClass addressClass = AddressClass.fromJson(status['data']['address']); + Subdivision? subdivision = status['data']['subdivision'] !=null? Subdivision.fromJson(status['data']['subdivision']):null; + MainAdress address = MainAdress(address: addressClass,subdivision: subdivision,id: status['data']['id'],details: status['data']['details']); + addresses.add(address); + + addresses.removeWhere((address)=>address.id == event.address.id); + addresses.add(address); + + emit(AddressUpdatedState(response: status)); + } else { + emit(AddressUpdatedState(response: status)); + } + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }, + ); + +////Delete + on((event, emit) async { + try { + final bool success = await AddressService.instance.delete( + addressId: event.id, + profileId: int.parse(event.profileId), + token: event.token); + if (success) { + addresses + .removeWhere(((MainAdress element) => element.id == event.id)); + emit(AddressDeletedState( + success: success, + )); + } else { + emit(AddressDeletedState(success: success)); + } + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); + ////call error state + on((event, emit) { + emit(const AddressErrorState( + message: "Something went wrong. Please try again")); + }); + } +} diff --git a/lib/bloc/profile/primary_information/address/address_event.dart b/lib/bloc/profile/primary_information/address/address_event.dart new file mode 100644 index 0000000..193fc74 --- /dev/null +++ b/lib/bloc/profile/primary_information/address/address_event.dart @@ -0,0 +1,84 @@ +part of 'address_bloc.dart'; + +abstract class AddressEvent extends Equatable { + const AddressEvent(); + + @override + List get props => []; +} + +class GetAddress extends AddressEvent { + final List addresses; + const GetAddress({required this.addresses}); + @override + List get props => [addresses]; +} + +class ShowAddAddressForm extends AddressEvent {} + +class ShowEditAddressForm extends AddressEvent { + final bool overseas; + final MainAdress address; + const ShowEditAddressForm({required this.address, required this.overseas}); +} + +class CallErrorState extends AddressEvent {} + +class AddAddress extends AddressEvent { + final AddressClass address; + final int categoryId; + final String? details; + final int? blockNumber; + final int? lotNumber; + final String token; + final int profileId; + const AddAddress( + {required this.address, + required this.profileId, + required this.token, + required this.blockNumber, + required this.categoryId, + required this.details, + required this.lotNumber}); + @override + List get props => [address, token, profileId,categoryId]; +} + +class UpdateAddress extends AddressEvent { + final AddressClass address; + final int categoryId; + final String? details; + final int? blockNumber; + final int? lotNumber; + final String token; + final int profileId; + const UpdateAddress( + {required this.address, + required this.profileId, + required this.token, + required this.blockNumber, + required this.categoryId, + required this.details, + required this.lotNumber}); + @override + List get props => [address, token, profileId,categoryId]; +} + + +class LoadAddress extends AddressEvent{ + +} + +class DeleteAddress extends AddressEvent { + final String profileId; + final int id; + final String token; + const DeleteAddress( + { + required this.id, + required this.profileId, + required this.token}); + @override + List get props => [ profileId, id, token]; +} + diff --git a/lib/bloc/profile/primary_information/address/address_state.dart b/lib/bloc/profile/primary_information/address/address_state.dart new file mode 100644 index 0000000..efef785 --- /dev/null +++ b/lib/bloc/profile/primary_information/address/address_state.dart @@ -0,0 +1,97 @@ +part of 'address_bloc.dart'; + +abstract class AddressState extends Equatable { + const AddressState(); + + @override + List get props => []; +} + +class AddressInitial extends AddressState {} + +//// LOADED STATE +class AddressLoadedState extends AddressState { + final List addresses; + const AddressLoadedState({required this.addresses}); + @override + List get props => [addresses]; +} + +////ERROR STATE +class AddressErrorState extends AddressState { + final String message; + const AddressErrorState({required this.message}); + @override + List get props => [message]; +} + +//// LOADING STATE +class AddressLoadingState extends AddressState {} + +////ADD ADDRESS STATE +class AddAddressState extends AddressState { + final List countries; + final List regions; + const AddAddressState({required this.countries, required this.regions}); + @override + List get props => [ + countries, + regions, + ]; +} + +//// DeletedState +class AddressDeletedState extends AddressState { + final bool success; + const AddressDeletedState({required this.success}); + @override + List get props => [success]; +} + +////AddedState +class AddressAddedState extends AddressState { + final Map response; + const AddressAddedState({required this.response}); + @override + List get props => [response]; +} + +////Edited State +class AddressUpdatedState extends AddressState { + final Map response; + const AddressUpdatedState({required this.response}); + @override + List get props => [response]; +} + +class EditAddressState extends AddressState { + final MainAdress address; + final List countries; + final List regions; + final List provinces; + final List cities; + final List baragays; + final Region? currentRegion; + final Country currentCountry; + final Province? currentProvince; + final CityMunicipality? currentCity; + final Barangay? currentBarangay; + final bool overseas; + + const EditAddressState( + {required this.address, + required this.countries, + required this.regions, + required this.baragays, + required this.cities, + required this.currentCity, + required this.currentCountry, + required this.currentProvince, + required this.currentRegion, + required this.overseas, + required this.provinces, + required this.currentBarangay + }); + @override + List get props => [countries, regions, address]; +} diff --git a/lib/bloc/profile/primary_information/citizenship/citizenship_bloc.dart b/lib/bloc/profile/primary_information/citizenship/citizenship_bloc.dart new file mode 100644 index 0000000..b50c916 --- /dev/null +++ b/lib/bloc/profile/primary_information/citizenship/citizenship_bloc.dart @@ -0,0 +1,106 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/location/country.dart'; +import 'package:unit2/model/profile/basic_information/citizenship.dart'; +import 'package:unit2/sevices/profile/citizenship_services.dart'; +import 'package:unit2/utils/location_utilities.dart'; + +part 'citizenship_event.dart'; +part 'citizenship_state.dart'; + +class CitizenshipBloc extends Bloc { + List citizenships = []; + List countries = []; + CitizenshipBloc() : super(CitizenshipInitial()) { + on((event, emit) async { + emit(CitizenshipLoadingState()); + try { + countries = await LocationUtils.instance.getCountries(); + citizenships = event.citizenship; + emit(CitizenshipLoaded( + citizenships: event.citizenship, countries: countries)); + } catch (e) { + emit(CitizenshipErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(CitizenshipLoaded(citizenships: citizenships, countries: countries)); + }); + on((event, emit) async { + try { + emit(CitizenshipLoadingState()); + Map responseStatus = + await CitizenshipServices.instance.add( + profileId: event.profileId, + token: event.token, + countryId: event.coiuntryId, + naturalBorn: event.naturalBorn); + if (responseStatus['success']) { + Country newCountry = + Country.fromJson(responseStatus['data']['country']); + Citizenship citizenship = Citizenship( + country: newCountry, + naturalBorn: responseStatus['data']['natural_born']); + citizenships.add(citizenship); + emit(CitizenshipAddedState( + responseStatus: responseStatus, citizenships: citizenships)); + } else { + emit(CitizenshipAddedState( + responseStatus: responseStatus, citizenships: citizenships)); + } + } catch (e) { + emit(CitizenshipErrorState(message: e.toString())); + } + }); + + on((event, emit) async { + try { + emit(CitizenshipLoadingState()); + Map responseStatus = + await CitizenshipServices.instance.update( + profileId: event.profileId, + token: event.token, + citizenship: event.citizenship, + oldCountry: event.oldCountryId); + if (responseStatus['success'] != null && responseStatus['success']) { + citizenships.removeWhere((element) => + element.country!.id == event.citizenship.country!.id && + element.naturalBorn == event.citizenship.naturalBorn); + Country newCountry = + Country.fromJson(responseStatus['data']['country']); + Citizenship citizenship = Citizenship( + country: newCountry, + naturalBorn: responseStatus['data']['natural_born']); + citizenships.add(citizenship); + emit(CitizenshipEditedState( + responseStatus: responseStatus, citizenships: citizenships)); + } else { + emit(CitizenshipEditedState( + responseStatus: responseStatus, citizenships: citizenships)); + } + } catch (e) { + emit(CitizenshipErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(CitizenshipLoadingState()); + try { + final bool success = await CitizenshipServices.instance.delete( + profileId: event.profileId, + token: event.token, + countryId: event.coiuntryId, + naturalBorn: event.naturalBorn); + if (success) { + citizenships.removeWhere((element) => + element.country!.id == event.coiuntryId && + element.naturalBorn == event.naturalBorn); + emit(CitizenshipDeleltedState(succcess: success)); + } else { + emit(CitizenshipDeleltedState(succcess: success)); + } + } catch (e) { + emit(CitizenshipErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/primary_information/citizenship/citizenship_event.dart b/lib/bloc/profile/primary_information/citizenship/citizenship_event.dart new file mode 100644 index 0000000..a5c8cc4 --- /dev/null +++ b/lib/bloc/profile/primary_information/citizenship/citizenship_event.dart @@ -0,0 +1,42 @@ +part of 'citizenship_bloc.dart'; + +abstract class CitizenshipEvent extends Equatable { + const CitizenshipEvent(); + + @override + List get props => []; +} + +class GetCitizenship extends CitizenshipEvent{ + final List citizenship; + const GetCitizenship({required this.citizenship}); +} +class ShowAddCitizenshipForm extends CitizenshipEvent{ + const ShowAddCitizenshipForm(); +} +class LoadCitizenship extends CitizenshipEvent{ + const LoadCitizenship(); +} + +class EditCitizenship extends CitizenshipEvent{ + final Citizenship citizenship; + final int profileId; + final String token; + final int oldCountryId; + const EditCitizenship({required this.citizenship, required this.oldCountryId, required this.profileId, required this.token}); +} +class AddCitizenship extends CitizenshipEvent{ + final int profileId; + final String token; + final int coiuntryId; + final bool naturalBorn; + const AddCitizenship({required this.coiuntryId, required this.naturalBorn, required this.profileId, required this.token}); +} + +class DeleteCitizenship extends CitizenshipEvent{ + final int profileId; + final String token; + final int coiuntryId; + final bool naturalBorn; + const DeleteCitizenship({required this.coiuntryId, required this.naturalBorn, required this.profileId, required this.token}); +} diff --git a/lib/bloc/profile/primary_information/citizenship/citizenship_state.dart b/lib/bloc/profile/primary_information/citizenship/citizenship_state.dart new file mode 100644 index 0000000..e342492 --- /dev/null +++ b/lib/bloc/profile/primary_information/citizenship/citizenship_state.dart @@ -0,0 +1,47 @@ +part of 'citizenship_bloc.dart'; + +abstract class CitizenshipState extends Equatable { + const CitizenshipState(); + + @override + List get props => []; +} + +class CitizenshipInitial extends CitizenshipState {} + +class CitizenshipLoaded extends CitizenshipState{ + final List citizenships; + final List countries; + const CitizenshipLoaded({required this.citizenships,required this.countries}); +} +class CitizenshipAddingState extends CitizenshipState{ + final List countries; + const CitizenshipAddingState({required this.countries}); +} +class CitizenshipLoadingState extends CitizenshipState{ + +} +class CitizenshipAddedState extends CitizenshipState{ + final Map responseStatus; + final List citizenships; + const CitizenshipAddedState({required this.responseStatus, required this.citizenships}); + +} + +class CitizenshipEditedState extends CitizenshipState{ + final Map responseStatus; + final List citizenships; + const CitizenshipEditedState({required this.responseStatus, required this.citizenships}); + +} +class CitizenshipErrorState extends CitizenshipState{ + final String message; + const CitizenshipErrorState({required this.message}); +} + +class CitizenshipDeleltedState extends CitizenshipState{ + final bool succcess; + const CitizenshipDeleltedState({required this.succcess}); + @override + List get props => [succcess]; +} \ No newline at end of file diff --git a/lib/bloc/profile/primary_information/contact/contact_bloc.dart b/lib/bloc/profile/primary_information/contact/contact_bloc.dart new file mode 100644 index 0000000..2d34f51 --- /dev/null +++ b/lib/bloc/profile/primary_information/contact/contact_bloc.dart @@ -0,0 +1,137 @@ +import 'dart:math'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/utils/profile_utilities.dart'; + +import '../../../../model/profile/basic_information/contact_information.dart'; + +part 'contact_event.dart'; +part 'contact_state.dart'; + +class ContactBloc extends Bloc { + ContactBloc() : super(ContactInitial()) { + List contactInformations = []; + List serviceTypes = []; + //// get all contacts + on((event, emit) { + emit(ContactLoadingState()); + try { + contactInformations = event.contactInformations; + emit(ContactLoadedState(contactInformation: contactInformations)); + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + //// Load Contacts + on((event, emit) { + emit(ContactLoadedState(contactInformation: contactInformations)); + }); + //// show add form + on((event, emit) async { + try { + emit(ContactLoadingState()); + if (serviceTypes.isEmpty) { + serviceTypes = await ProfileUtilities.instance.getServiceType(); + } + emit(ContactAddingState(serviceTypes: serviceTypes)); + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + ///// Show edit form + on((event, emit) async { + ServiceType serviceType; + List commServiceProvivers; + CommService serviceProvider; + try { + if (serviceTypes.isEmpty) { + serviceTypes = await ProfileUtilities.instance.getServiceType(); + } + serviceType = serviceTypes.firstWhere((ServiceType element) { + return element.id == event.contactInfo.commService!.serviceType!.id; + }); + commServiceProvivers = await ContactService.instance + .getServiceProvider(serviceTypeId: serviceType.id!); + serviceProvider = commServiceProvivers.firstWhere( + (CommService element) => + element.id == event.contactInfo.commService!.id); + emit(ContactEditingState( + serviceTypes: serviceTypes, + selectedServiceType: serviceType, + commServiceProviders: commServiceProvivers, + selectedProvider: serviceProvider, + contactInfo: event.contactInfo)); + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + ////edit contact + on((event, emit) async { + try { + Map responseStatus = await ContactService.instance + .update( + profileId: event.profileId, + token: event.token, + contactInfo: event.contactInfo); + if (responseStatus['success']) { + ContactInfo contactInfo = + ContactInfo.fromJson(responseStatus['data']['contact_info']); + contactInformations.removeWhere( + (ContactInfo element) => element.id == event.contactInfo.id); + contactInformations.add(contactInfo); + emit(ContactEditedState(response: responseStatus)); + } else { + emit(ContactEditedState(response: responseStatus)); + } + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(ContactErrorState(message: event.message)); + }); + + //// add contact + + on((event, emit) async { + try { + Map responseStatus = await ContactService.instance + .add( + profileId: event.profileId, + token: event.token, + contactInfo: event.contactInfo); + if (responseStatus['success']) { + ContactInfo contactInfo = + ContactInfo.fromJson(responseStatus['data']['contact_info']); + contactInformations.add(contactInfo); + emit(ContactAddedState(response: responseStatus)); + } else { + emit(ContactAddedState(response: responseStatus)); + } + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + //// delete contact + on((event, emit) async { + try { + final bool success = await ContactService.instance.deleteContact( + profileId: event.profileId, + token: event.token, + contactInfo: event.contactInfo); + if (success) { + contactInformations + .removeWhere((element) => element.id == event.contactInfo.id); + emit(ContactDeletedState(succcess: success)); + } else { + emit(ContactDeletedState(succcess: success)); + } + } catch (e) { + emit(ContactErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/primary_information/contact/contact_event.dart b/lib/bloc/profile/primary_information/contact/contact_event.dart new file mode 100644 index 0000000..48a1692 --- /dev/null +++ b/lib/bloc/profile/primary_information/contact/contact_event.dart @@ -0,0 +1,78 @@ +part of 'contact_bloc.dart'; + +abstract class ContactEvent extends Equatable { + const ContactEvent(); + + @override + List get props => []; +} + +////get contacts +class GetContacts extends ContactEvent { + final List contactInformations; + const GetContacts({required this.contactInformations}); + @override + List get props => []; +} + +//// load contacts +class LoadContacts extends ContactEvent { + @override + List get props => []; +} + +//// show add form +class ShowAddForm extends ContactEvent {} + +class CallErrorEvent extends ContactEvent { + final String message; + const CallErrorEvent({required this.message}); +} + +//// show edit form +class ShowEditForm extends ContactEvent { + final ContactInfo contactInfo; + const ShowEditForm({required this.contactInfo}); + @override + List get props => [contactInfo]; +} + +////add event +class AddContactInformation extends ContactEvent { + final int profileId; + final String token; + final ContactInfo contactInfo; + const AddContactInformation( + {required this.contactInfo, + required this.profileId, + required this.token}); + @override + List get props => [profileId, token, contactInfo]; +} + +////edit event +class EditContactInformation extends ContactEvent { + final int profileId; + final String token; + final ContactInfo contactInfo; + const EditContactInformation( + {required this.contactInfo, + required this.profileId, + required this.token}); + @override + List get props => [profileId, token, contactInfo]; +} + +//// delete event + +class DeleteContactInformation extends ContactEvent { + final int profileId; + final String token; + final ContactInfo contactInfo; + const DeleteContactInformation( + {required this.contactInfo, + required this.profileId, + required this.token}); + @override + List get props => [profileId, token, contactInfo]; +} diff --git a/lib/bloc/profile/primary_information/contact/contact_state.dart b/lib/bloc/profile/primary_information/contact/contact_state.dart new file mode 100644 index 0000000..f8f7f2c --- /dev/null +++ b/lib/bloc/profile/primary_information/contact/contact_state.dart @@ -0,0 +1,76 @@ +part of 'contact_bloc.dart'; + +abstract class ContactState extends Equatable { + const ContactState(); + + @override + List get props => []; +} + +class ContactInitial extends ContactState {} + +////loaded state +class ContactLoadedState extends ContactState{ + final List contactInformation; + const ContactLoadedState({required this.contactInformation}); + @override + List get props => []; +} +////loading state +class ContactLoadingState extends ContactState{ + +} +//// adding state +class ContactAddingState extends ContactState{ + final List serviceTypes; + const ContactAddingState({ required this.serviceTypes}); + @override + List get props => [serviceTypes]; +} +//// Editing state +class ContactEditingState extends ContactState{ + final List serviceTypes; + final List commServiceProviders; + final CommService selectedProvider; + final ServiceType selectedServiceType; + final ContactInfo contactInfo; + const ContactEditingState({ required this.serviceTypes, required this.selectedServiceType, required this.selectedProvider, required this.commServiceProviders, required this.contactInfo}); + @override + List get props => [serviceTypes]; +} + + +//// added state +class ContactAddedState extends ContactState{ + + final Map response; + const ContactAddedState({ required this.response}); + @override + List get props => [response]; +} +//// edited state +class ContactEditedState extends ContactState{ + + final Map response; + const ContactEditedState({ required this.response}); + @override + List get props => [response]; +} +////deleted state +class ContactDeletedState extends ContactState{ + final bool succcess; + const ContactDeletedState({required this.succcess}); + @override + List get props => [succcess]; +} + +////error state +class ContactErrorState extends ContactState{ + final String message; + const ContactErrorState({required this.message}); + @override + List get props => [message]; +} + + + diff --git a/lib/bloc/profile/primary_information/identification/identification_bloc.dart b/lib/bloc/profile/primary_information/identification/identification_bloc.dart new file mode 100644 index 0000000..d4ee0b8 --- /dev/null +++ b/lib/bloc/profile/primary_information/identification/identification_bloc.dart @@ -0,0 +1,207 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/identification/edit_modal.dart'; +import 'package:unit2/sevices/profile/identification_services.dart'; + +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/profile/basic_information/identification_information.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/profile_utilities.dart'; + +part 'identification_event.dart'; +part 'identification_state.dart'; + +class IdentificationBloc + extends Bloc { + IdentificationBloc() : super(IdentificationInitial()) { + List identificationInformations = []; + List agencies = []; + List addedAgencies = []; + List agencyCategory = []; + List globalCountries = []; + List globalRegions = []; + List provinces = []; + List cities = []; + Region? currentRegion; + Country currentCountry; + Province? currentProvince; + CityMunicipality? currentCity; + ////get + on((event, emit) { + try { + identificationInformations = event.identificationInformation; + emit(IdentificationLoadedState( + identificationInformation: identificationInformations)); + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////load + on((event, emit) { + emit(IdentificationLoadedState( + identificationInformation: identificationInformations)); + }); + //// show add form + on((event, emit) async { + addedAgencies.clear(); + try { + emit(IdentificationLoadingState()); + if (identificationInformations.isNotEmpty) { + for (var element in identificationInformations) { + addedAgencies.add(element.agency!); + } + } + /////AGENCIES------------------------------------------ + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + /////Category Agency------------------------------------------ + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + ////regions + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + //// country + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + emit(IdentificationAddingState( + addedAgencies: addedAgencies, + agencyCategory: agencyCategory, + agencies: agencies, + countries: globalCountries, + regions: globalRegions)); + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////show edit form + on((event, emit) async { + try { + ////regions + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + //// country + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + currentCountry = globalCountries.firstWhere((Country country) => + event.identification.issuedAt!.country!.code == country.code); + if (!event.overseas) { + currentRegion = globalRegions.firstWhere((Region region) => + event.identification.issuedAt!.cityMunicipality!.province!.region! + .code == + region.code); + provinces = await LocationUtils.instance + .getProvinces(regionCode: currentRegion!.code.toString()); + currentProvince = provinces.firstWhere((Province province) => + event.identification.issuedAt!.cityMunicipality!.province!.code == + province.code); + + cities = await LocationUtils.instance + .getCities(code: currentProvince!.code.toString()); + + currentCity = cities.firstWhere((CityMunicipality cityMunicipality) => + event.identification.issuedAt!.cityMunicipality!.code == + cityMunicipality.code); + } + emit(IdentificationEditingState( + cities: cities, + countries: globalCountries, + currentCity: currentCity, + currentCountry: currentCountry, + currentProvince: currentProvince, + currentRegion: currentRegion, + identification: event.identification, + overseas: event.overseas, + provinces: provinces, + regions: globalRegions)); + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////add + on((event, emit) async { + try { + emit(IdentificationLoadingState()); + Map status = await IdentificationServices.instance + .add( + identification: event.identification, + profileId: event.profileId, + token: event.token); + if (status['success']) { + Identification identification = + Identification.fromJson(status['data']); + identificationInformations.add(identification); + emit(IdentificationAddedState(response: status)); + } else { + emit(IdentificationAddedState(response: status)); + } + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////update + on((event, emit) async { + try { + emit(IdentificationLoadingState()); + Map status = await IdentificationServices.instance + .update( + identification: event.identification, + profileId: event.profileId, + token: event.token); + if (status['success']) { + identificationInformations + .removeWhere((element) => element.id == event.identification.id); + Identification identification = + Identification.fromJson(status['data']); + identificationInformations.add(identification); + emit(IdentificationEditedState(response: status)); + } else { + emit(IdentificationEditedState(response: status)); + } + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////delete + on((event, emit) async { + try { + final bool success = await IdentificationServices.instance.delete( + identificationId: event.identificationId, + token: event.token, + profileId: event.profileId); + if (success) { + identificationInformations.removeWhere( + (Identification element) => element.id == event.identificationId); + emit(IdentificationDeletedState(success: success)); + } else { + emit(IdentificationDeletedState(success: success)); + } + } catch (e) { + emit(IdenficationErrorState(message: e.toString())); + } + }); + ////show error state + on((event, emit) { + emit(IdenficationErrorState(message: event.message)); + }); + } +} diff --git a/lib/bloc/profile/primary_information/identification/identification_event.dart b/lib/bloc/profile/primary_information/identification/identification_event.dart new file mode 100644 index 0000000..97bfefc --- /dev/null +++ b/lib/bloc/profile/primary_information/identification/identification_event.dart @@ -0,0 +1,68 @@ +part of 'identification_bloc.dart'; + +abstract class IdentificationEvent extends Equatable { + const IdentificationEvent(); + + @override + List get props => []; +} +////get +class GetIdentifications extends IdentificationEvent{ + final List identificationInformation; + const GetIdentifications({required this.identificationInformation}); + @override + List get props => [identificationInformation]; +} +////load +class LoadIdentifications extends IdentificationEvent{ + @override + List get props => []; +} + +////show add form +class ShowAddIdentificationForm extends IdentificationEvent{ + +} +//// show edit form +class ShowEditIdentificationForm extends IdentificationEvent{ + final bool overseas; + final Identification identification; + final int profileId; + final String token; + const ShowEditIdentificationForm({required this.identification, required this.profileId, required this.token, required this.overseas}); + @override + List get props => [identification,profileId,token,overseas]; +} +class DeleteIdentification extends IdentificationEvent{ + final int identificationId; + final int profileId; + final String token; + const DeleteIdentification({required this.identificationId, required this.profileId, required this.token}); + +} + +//// add +class AddIdentification extends IdentificationEvent{ + final Identification identification; + final int profileId; + final String token; + const AddIdentification({required this.identification, required this.profileId, required this.token}); + @override + List get props => [identification,profileId,token]; +} + +//// update +class UpdateIdentifaction extends IdentificationEvent{ + final Identification identification; + final int profileId; + final String token; + const UpdateIdentifaction({required this.identification, required this.profileId, required this.token}); + @override + List get props => [identification,profileId,token]; +} + +class ShowErrorState extends IdentificationEvent { + final String message; + const ShowErrorState({required this.message}); +} + diff --git a/lib/bloc/profile/primary_information/identification/identification_state.dart b/lib/bloc/profile/primary_information/identification/identification_state.dart new file mode 100644 index 0000000..71ca194 --- /dev/null +++ b/lib/bloc/profile/primary_information/identification/identification_state.dart @@ -0,0 +1,74 @@ +part of 'identification_bloc.dart'; + +abstract class IdentificationState extends Equatable { + const IdentificationState(); + + @override + List get props => []; +} + +class IdentificationInitial extends IdentificationState {} + +class IdentificationLoadedState extends IdentificationState{ + final List identificationInformation; + const IdentificationLoadedState({required this.identificationInformation}); + @override + List get props => [identificationInformation]; +} + +class IdenficationErrorState extends IdentificationState{ + final String message; + const IdenficationErrorState({required this.message}); + @override + List get props => [message]; +} + +class IdentificationLoadingState extends IdentificationState{ + +} +class IdentificationDeletedState extends IdentificationState{ + final bool success; + const IdentificationDeletedState({required this.success}); + @override + List get props => [success]; +} + +class IdentificationAddedState extends IdentificationState{ + final Map response; + const IdentificationAddedState({required this.response}); + @override + List get props => [response]; +} + +class IdentificationEditedState extends IdentificationState{ + final Map response; + const IdentificationEditedState({required this.response}); + @override + List get props => [response]; +} + +class IdentificationAddingState extends IdentificationState{ + final List agencies; + final List addedAgencies; + final List countries; + final List regions; + final List agencyCategory; + const IdentificationAddingState({required this.agencies, required this.countries, required this.regions,required this.agencyCategory, required this.addedAgencies}); + @override + List get props => [agencies,countries,regions,agencyCategory]; +} + +class IdentificationEditingState extends IdentificationState{ + final Identification identification; + final List countries; + final List regions; + final List provinces; + final List cities; + final Region? currentRegion; + final Country currentCountry; + final Province? currentProvince; + final CityMunicipality? currentCity; + final bool overseas; + const IdentificationEditingState({required this.cities,required this.countries, required this.currentCity, required this.currentCountry, required this.currentProvince, required this.currentRegion, required this.identification, required this.overseas, required this.provinces, required this.regions}); + +} diff --git a/lib/bloc/profile/profile_bloc.dart b/lib/bloc/profile/profile_bloc.dart new file mode 100644 index 0000000..2384265 --- /dev/null +++ b/lib/bloc/profile/profile_bloc.dart @@ -0,0 +1,143 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/profile/profileInfomation.dart'; +import 'package:unit2/sevices/profile/profile_other_info.dart'; +import 'package:unit2/sevices/profile/profile_service.dart'; + +import '../../model/profile/basic_information/primary-information.dart'; +import '../../screens/profile/components/basic_information/profile_other_info.dart'; +part 'profile_event.dart'; +part 'profile_state.dart'; + +class ProfileBloc extends Bloc { + ProfileBloc() : super(ProfileInitial()) { + Profile? currentProfileInformation; + List religions = []; + List ethnicities = []; + List indigencies = []; + List disabilities = []; + List genders = []; + List bloodType = ["A+", "B+", "A-", "B-", "AB+", "AB-", "O+", "O-"]; + List nameExtensions = [ + "NONE", + "N/A", + "SR.", + "JR.", + "I", + "II", + "III", + "IV", + "V", + "VI", + "VII", + "VIII", + "IX", + "X" + ]; + List sexes = ["MALE", "FEMALE"]; + List civilStatus = [ + "NONE", + "SINGLE", + "MARRIED", + "SEPARATED", + "WIDOWED" + ]; + + ProfileInformation? globalProfileInformation; + on((event, emit) async { + emit(ProfileLoading()); + try { + if (globalProfileInformation == null) { + ProfileInformation? profileInformation = await ProfileService.instance + .getProfile(event.token, event.userID); + globalProfileInformation = profileInformation; + } + + emit(ProfileLoaded(profileInformation: globalProfileInformation!)); + } catch (e) { + emit(ProfileErrorState(mesage: e.toString())); + } + }); + on((event, emit) { + currentProfileInformation = event.primaryBasicInformation; + emit(BasicInformationProfileLoaded( + primaryBasicInformation: event.primaryBasicInformation)); + }); + on((event, emit) { + emit(BasicInformationProfileLoaded( + primaryBasicInformation: currentProfileInformation!)); + }); + on((event, emit) async { + try { + emit(BasicPrimaryInformationLoadingState()); + if (religions.isEmpty) { + religions = await ProfileOtherInfoServices.instace + .getReligions(token: event.token); + religions.insert( + 0, ProfileOtherInfo(id: null, name: "NONE", description: null)); + } + if (genders.isEmpty) { + genders = await ProfileOtherInfoServices.instace + .getGenders(token: event.token); + + genders.insert( + 0, ProfileOtherInfo(id: null, name: "NONE", description: null)); + } + if (ethnicities.isEmpty) { + ethnicities = await ProfileOtherInfoServices.instace + .getEthnicity(token: event.token); + + ethnicities.insert( + 0, ProfileOtherInfo(id: null, name: "NONE", description: null)); + } + if (disabilities.isEmpty) { + disabilities = await ProfileOtherInfoServices.instace + .getDisability(token: event.token); + disabilities.insert( + 0, ProfileOtherInfo(id: null, name: "NONE", description: null)); + } + if (indigencies.isEmpty) { + indigencies = await ProfileOtherInfoServices.instace + .getIndigency(token: event.token); + indigencies.insert( + 0, ProfileOtherInfo(id: null, name: "NONE", description: null)); + } + emit(BasicInformationEditingState( + primaryInformation: currentProfileInformation!, + extensions: nameExtensions, + sexes: sexes, + bloodTypes: bloodType, + genders: genders, + civilStatus: civilStatus, + disability: disabilities, + ethnicity: ethnicities, + indigenous: indigencies, + religion: religions)); + } catch (e) { + emit(BasicPrimaryInformationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + Map status = await ProfileService.instance + .updateBasicProfileInfo( + token: event.token, + profileId: event.profileId, + profileInfo: event.profileInformation, + genderId: event.genderId, + indigencyId: event.indigencyId, + disabilityId: event.disabilityId, + ethnicityId: event.ethnicityId, + reqligionId: event.religionId); + if (status['success']) { + Profile profile = Profile.fromJson(status['data']); + currentProfileInformation = profile; + emit(BasicProfileInfoEditedState(response: status)); + } + emit(BasicProfileInfoEditedState(response: status)); + } catch (e) { + emit(BasicPrimaryInformationErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/profile_event.dart b/lib/bloc/profile/profile_event.dart new file mode 100644 index 0000000..864edc2 --- /dev/null +++ b/lib/bloc/profile/profile_event.dart @@ -0,0 +1,47 @@ +part of 'profile_bloc.dart'; + +abstract class ProfileEvent extends Equatable { + const ProfileEvent(); + + @override + List get props => []; +} + +class LoadProfile extends ProfileEvent { + final String token; + final int userID; + const LoadProfile({required this.token, required this.userID}); + @override + List get props => [token, userID]; +} + +class LoadProfileInformation extends ProfileEvent { + @override + List get props => []; +} +class GetPrimaryBasicInfo extends ProfileEvent{ + final Profile primaryBasicInformation; + const GetPrimaryBasicInfo({required this.primaryBasicInformation}); +} +class LoadBasicPrimaryInfo extends ProfileEvent{ + +} + +class ShowPrimaryInfoEditForm extends ProfileEvent{ + final String token; + const ShowPrimaryInfoEditForm({required this.token}); +} +class EditBasicProfileInformation extends ProfileEvent{ +final Profile profileInformation; +final int profileId; +final String token; +final int? genderId; +final int? indigencyId; +final int? disabilityId; +final int? religionId; +final int? ethnicityId; +const EditBasicProfileInformation({required this.disabilityId,required this.ethnicityId, required this.genderId, required this.indigencyId, required this.profileId,required this.profileInformation,required this.religionId,required this.token}); +} + + + diff --git a/lib/bloc/profile/profile_state.dart b/lib/bloc/profile/profile_state.dart new file mode 100644 index 0000000..811c9a1 --- /dev/null +++ b/lib/bloc/profile/profile_state.dart @@ -0,0 +1,62 @@ +part of 'profile_bloc.dart'; + +abstract class ProfileState extends Equatable { + const ProfileState(); + + @override + List get props => []; +} + +class ProfileInitial extends ProfileState {} + +class ProfileLoaded extends ProfileState { + final ProfileInformation profileInformation; + const ProfileLoaded({required this.profileInformation}); + @override + List get props => [profileInformation]; +} + +class ProfileErrorState extends ProfileState { + final String mesage; + const ProfileErrorState({required this.mesage}); + @override + List get props => [mesage]; +} +class BasicInformationEditingState extends ProfileState{ + final Profile primaryInformation; + final List religion; +final List ethnicity; +final List disability; +final List indigenous; +final List genders; +final Listsexes; +final List bloodTypes; +final List civilStatus; +final List extensions; +const BasicInformationEditingState( {required this.genders, required this.extensions, required this.primaryInformation, required this.sexes, required this.bloodTypes, required this.civilStatus, required this.disability,required this.ethnicity,required this.indigenous,required this.religion}); +} +////Edited State +class BasicProfileInfoEditedState extends ProfileState{ + final Map response; + const BasicProfileInfoEditedState({required this.response}); + @override + List get props => [response]; +} + +class BasicInformationProfileLoaded extends ProfileState{ + final Profile primaryBasicInformation; + const BasicInformationProfileLoaded({required this.primaryBasicInformation}); + +} +class BasicPrimaryInformationLoadingState extends ProfileState{ + +} +class BasicPrimaryInformationErrorState extends ProfileState{ + final String message; + const BasicPrimaryInformationErrorState({required this.message}); +} + +class ProfileLoading extends ProfileState {} + + + diff --git a/lib/bloc/profile/references/references_bloc.dart b/lib/bloc/profile/references/references_bloc.dart new file mode 100644 index 0000000..ba9fe6c --- /dev/null +++ b/lib/bloc/profile/references/references_bloc.dart @@ -0,0 +1,213 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/location/city.dart'; +import 'package:unit2/model/location/country.dart'; +import 'package:unit2/model/location/region.dart'; +import 'package:unit2/sevices/profile/references_services.dart'; +import '../../../model/location/provinces.dart'; +import '../../../model/profile/references.dart'; +import '../../../utils/location_utilities.dart'; + +part 'references_event.dart'; +part 'references_state.dart'; + +class ReferencesBloc extends Bloc { + List references = []; + List globalCountries = []; + List globalRegions = []; + List globalCategories = []; + + ReferencesBloc() : super(ReferencesInitial()) { + on((event, emit) async { + emit(ReferencesLoadingState()); + try { + if (references.isEmpty) { + List refs = await ReferencesServices.instace + .getRefences(event.profileId, event.token); + references = refs; + emit(ReferencesLoadedState(references: references)); + } + + } catch (e) { + emit( ReferencesErrorState(message: e.toString())); + } + }); +////SHOW FORM FOR ADDING REFERENCES + + on((event, emit) async { + emit(ReferencesLoadingState()); + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + if (globalCategories.isEmpty) { + List categories = + await LocationUtils.instance.getAddressCategory(); + globalCategories = categories; + } + emit(AddReferenceState( + countries: globalCountries, + regions: globalRegions, + categories: globalCategories)); + } catch (e) { + emit(ReferencesErrorState(message: e.toString())); + } + ////SHOW EDIT FORM + }); + on((event, emit) async { + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedCity; + AddressCategory? selectedCategory; + Country selectedCountry; + Barangay? selectedBarangay; + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + if (globalCategories.isEmpty) { + List categories = + await LocationUtils.instance.getAddressCategory(); + globalCategories = categories; + } +//// checck if address is overseas + bool overseas = + event.personalReference.address!.country!.id! != 175 ? true : false; + selectedCategory = globalCategories.firstWhere( + (AddressCategory element) => + event.personalReference.address!.addressCategory!.id == + element.id); + ////if address is not overseas set initial values for address + if (!overseas) { + selectedRegion = globalRegions.firstWhere((Region element) => + event.personalReference.address!.cityMunicipality!.province! + .region!.code == + element.code); + List provinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion.code.toString()); + selectedProvince = provinces.firstWhere((Province province) => + event.personalReference.address!.cityMunicipality!.province! + .code == + province.code); + List cities = await LocationUtils.instance + .getCities(code: selectedProvince.code!); + selectedCity = cities.firstWhere((CityMunicipality city) => + event.personalReference.address!.cityMunicipality!.code == + city.code); + List barangays = await LocationUtils.instance + .getBarangay(code: selectedCity.code.toString()); + if (event.personalReference.address?.barangay != null) { + selectedBarangay = barangays.firstWhere((Barangay barangay) => + event.personalReference.address?.barangay?.code == + barangay.code); + } else { + selectedBarangay = null; + } + emit(EditReferenceState( + selectedRegion: selectedRegion, + ref: event.personalReference, + countries: globalCountries, + regions: globalRegions, + barangays: barangays, + categories: globalCategories, + isOverseas: overseas, + provinces: provinces, + selectedProvince: selectedProvince, + cities: cities, + selectedCity: selectedCity, + selectedCategory: selectedCategory, + selectedBarangay: selectedBarangay)); + } else { + //// if address is overseas set initial value for country + selectedCountry = globalCountries.firstWhere((Country element) => + event.personalReference.address!.country!.id == element.id); + emit(EditReferenceState( + selectedCountry: selectedCountry, + selectedCategory: selectedCategory, + selectedRegion: null, + ref: event.personalReference, + countries: globalCountries, + regions: globalRegions, + categories: globalCategories, + isOverseas: overseas)); + } + } catch (e) { + emit(ReferencesErrorState(message: e.toString())); + } + }); + + //// CALL THE ERROR STATE EVEN T + on((event, emit) async { + emit(const ReferencesErrorState( + message: "Something went wrong. Please try again")); + //// EDIT REFERENCES EVENT + }); + on((event, emit) async { + Map status = await ReferencesServices.instace.update( + ref: event.reference, token: event.token, profileId: event.profileId); + if (status['success']) { + PersonalReference ref = PersonalReference.fromJson(status['data']); + references.removeWhere( + (PersonalReference element) => element.id == event.reference.id); + references.add(ref); + emit(ReferenceEditedState(response: status)); + } else { + emit(ReferenceEditedState(response: status)); + } + }); + +//// add reference event + on((event, emit) async { + try { + Map status = await ReferencesServices.instace + .addReference( + ref: event.reference, + token: event.token, + profileId: event.profileId); + if (status['success']) { + PersonalReference ref = PersonalReference.fromJson(status['data']); + references.add(ref); + emit(ReferencesAddedState(response: status)); + } else { + emit(ReferencesAddedState(response: status)); + } + } catch (e) { + emit(ReferencesErrorState(message: e.toString())); + } + }); + ////LOAD REFERENCE + on((event, emit) { + emit(ReferencesLoadingState()); + emit(ReferencesLoadedState(references: references)); + }); + ////DELETE REFERENCE + on((event, emit) async { + try { + final bool success = await ReferencesServices.instace.delete( + profileId: event.profileId, token: event.token, id: event.refId); + if (success) { + event.references.removeWhere( + (PersonalReference element) => element.id == event.refId); + references = event.references; + emit(DeleteReferenceState(success: success)); + } else { + emit(DeleteReferenceState(success: success)); + } + } catch (e) { + emit(ReferencesErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/references/references_event.dart b/lib/bloc/profile/references/references_event.dart new file mode 100644 index 0000000..5eedf7d --- /dev/null +++ b/lib/bloc/profile/references/references_event.dart @@ -0,0 +1,66 @@ +part of 'references_bloc.dart'; + +abstract class ReferencesEvent extends Equatable { + const ReferencesEvent(); + + @override + List get props => []; +} + +class GetReferences extends ReferencesEvent { + final int profileId; + final String token; + const GetReferences({required this.profileId, required this.token}); + @override + List get props => [profileId, token]; +} + +class ShowAddReferenceForm extends ReferencesEvent {} + +class ShowEditReferenceForm extends ReferencesEvent { + final PersonalReference personalReference; + const ShowEditReferenceForm({required this.personalReference}); + @override + List get props => [personalReference]; +} + +class CallErrorState extends ReferencesEvent {} + +class AddReference extends ReferencesEvent { + final PersonalReference reference; + final String token; + final int profileId; + const AddReference( + {required this.profileId, required this.reference, required this.token}); + @override + List get props => [profileId, token, reference]; +} + +class EditReference extends ReferencesEvent { + final PersonalReference reference; + final String token; + final int profileId; + const EditReference( + {required this.profileId, required this.reference, required this.token}); + @override + List get props => [profileId, token, reference]; +} + +class DeleteReference extends ReferencesEvent { + final List references; + final int profileId; + final String token; + final int refId; + const DeleteReference( + {required this.profileId, + required this.refId, + required this.references, + required this.token}); + @override + List get props => [profileId, token, refId, references]; +} + +class LoadReferences extends ReferencesEvent { + @override + List get props => []; +} diff --git a/lib/bloc/profile/references/references_state.dart b/lib/bloc/profile/references/references_state.dart new file mode 100644 index 0000000..b3a07d3 --- /dev/null +++ b/lib/bloc/profile/references/references_state.dart @@ -0,0 +1,93 @@ +part of 'references_bloc.dart'; + +abstract class ReferencesState extends Equatable { + const ReferencesState(); + + @override + List get props => []; +} + +class ReferencesInitial extends ReferencesState {} + +class ReferencesLoadedState extends ReferencesState { + final List references; + const ReferencesLoadedState({required this.references}); + + @override + List get props => [references]; +} + +class ReferencesErrorState extends ReferencesState { + final String message; + const ReferencesErrorState({required this.message}); + + @override + List get props => [message]; +} + +class ReferencesLoadingState extends ReferencesState {} + +class ReferencesAddedState extends ReferencesState { + final Map response; + const ReferencesAddedState( + { required this.response}); + @override + List get props => [ response]; +} +class ReferenceEditedState extends ReferencesState { + + final Map response; + const ReferenceEditedState( + { required this.response}); + @override + List get props => [ response]; +} + +class EditReferenceState extends ReferencesState { + final List regions; + final List countries; + final List categories; + final List? provinces; + final List? cities; + final List? barangays; + final PersonalReference ref; + final bool isOverseas; + final Region? selectedRegion; + final Province? selectedProvince; + final CityMunicipality? selectedCity; + final AddressCategory selectedCategory; + final Barangay? selectedBarangay; + final Country? selectedCountry; + const EditReferenceState( + { this.barangays, + this.selectedBarangay, + required this.selectedCategory, + this.cities, + this.selectedCity, + this.provinces, + this.selectedProvince, + this.selectedRegion, + this.selectedCountry, + required this.isOverseas, + required this.ref, + required this.categories, + required this.countries, + required this.regions}); + @override + List get props => [regions, countries, categories, isOverseas]; +} + +class AddReferenceState extends ReferencesState { + final List regions; + final List countries; + final List categories; + const AddReferenceState( + {required this.categories, + required this.countries, + required this.regions}); +} + +class DeleteReferenceState extends ReferencesState { + final bool success; + const DeleteReferenceState({ required this.success}); +} diff --git a/lib/bloc/profile/voluntary_works/voluntary_work_bloc.dart b/lib/bloc/profile/voluntary_works/voluntary_work_bloc.dart new file mode 100644 index 0000000..d6db36f --- /dev/null +++ b/lib/bloc/profile/voluntary_works/voluntary_work_bloc.dart @@ -0,0 +1,250 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/sevices/profile/volunatary_services.dart'; +import 'package:unit2/utils/profile_utilities.dart'; +import '../../../model/location/city.dart'; +import '../../../model/location/country.dart'; +import '../../../model/location/provinces.dart'; +import '../../../model/location/region.dart'; +import '../../../model/profile/voluntary_works.dart'; +import '../../../model/utils/agency.dart'; +import '../../../model/utils/category.dart'; +import '../../../model/utils/position.dart'; +import '../../../utils/location_utilities.dart'; +part 'voluntary_work_event.dart'; +part 'voluntary_work_state.dart'; + +class VoluntaryWorkBloc extends Bloc { + VoluntaryWorkBloc() : super(VoluntaryWorkInitial()) { + List voluntaryWorks = []; + List globalCountries = []; + List agencyCategory = []; + List globalRegions = []; + List agencyPositions = []; + List agencies = []; + List provinces = []; + List cities = []; + ///// current + PositionTitle currentPosition; + Agency currentAgency; + Region? currentRegion; + Country currentCountry; + Province? currentProvince; + CityMunicipality? currentCity; + ////Get Voluntary Works + on((event, emit) async { + emit(VoluntaryWorkLoadingState()); + try { + if(voluntaryWorks.isEmpty){ + List works = await VoluntaryService.instance + .getVoluntaryWorks(event.profileId, event.token); + voluntaryWorks = works; + } + emit(VoluntaryWorkLoadedState(voluntaryWorks: voluntaryWorks)); + } catch (e) { + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); + //// Load + on((event, emit) { + emit(VoluntaryWorkLoadedState(voluntaryWorks: voluntaryWorks)); + }); + //// Show Add form Event + on((event, emit) async { + try { + emit(VoluntaryWorkLoadingState()); + //// POSITIONS + if (agencyPositions.isEmpty) { + List positions = + await ProfileUtilities.instance.getAgencyPosition(); + agencyPositions = positions; + } + + /////AGENCIES------------------------------------------ + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + + /////Category Agency------------------------------------------ + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + + ////regions + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + + //// country + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + + emit(AddVoluntaryWorkState( + agencies: agencies, + positions: agencyPositions, + agencyCategory: agencyCategory, + regions: globalRegions, + countries: globalCountries)); + } catch (e) { + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(VoluntaryWorkErrorState(message: event.message)); + }); + //// Add Voluntary Work + on((event, emit) async { + try { + Map status = await VoluntaryService.instance.add( + voluntaryWork: event.work, + profileId: event.profileId, + token: event.token); + if (status['success']) { + VoluntaryWork work = VoluntaryWork.fromJson(status['data']); + voluntaryWorks.add(work); + emit(VoluntaryWorkAddedState(response: status)); + } else { + emit(VoluntaryWorkAddedState(response: status)); + } + } catch (e) { + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); + ////Update + on((event, emit) async { + final DateFormat formatter = DateFormat('yyyy-MM-dd'); + try{ + Map status = await VoluntaryService.instance.update( + voluntaryWork: event.work, + profileId: event.profileId, + token: event.token, + oldPosId: event.oldPosId, + oldAgencyId: event.oldAgencyId, + oldFromDate: formatter.format(DateTime.parse(event.oldFromDate))); + if (status['success']) { + VoluntaryWork work = VoluntaryWork.fromJson(status['data']); + voluntaryWorks.removeWhere((VoluntaryWork element) => + element.position!.id == event.oldPosId && + element.agency!.id == event.oldAgencyId && + element.fromDate.toString() == event.oldFromDate.toString()); + voluntaryWorks.add(work); + emit(VoluntaryWorkEditedState(response: status)); + } else { + emit(VoluntaryWorkEditedState(response: status)); + } + }catch(e){ + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); +/////SHOW EDIT FORM + on((event, emit) async { + try { + //// POSITIONS + if (agencyPositions.isEmpty) { + List positions = + await ProfileUtilities.instance.getAgencyPosition(); + agencyPositions = positions; + } + currentPosition = event.work.position!; + + /////AGENCIES------------------------------------------ + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + currentAgency = event.work.agency!; + + /////Category Agency------------------------------------------ + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + + ////regions + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + + //// country + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + currentCountry = globalCountries.firstWhere((Country country) => + event.work.address!.country!.code == country.code); + ////If overseas + if (!event.isOverseas) { + //// if not overseas + currentRegion = globalRegions.firstWhere((Region region) => + event.work.address!.cityMunicipality!.province!.region!.code == + region.code); + provinces = await LocationUtils.instance + .getProvinces(regionCode: currentRegion!.code.toString()); + currentProvince = provinces.firstWhere((Province province) => + event.work.address!.cityMunicipality!.province!.code == + province.code); + + cities = await LocationUtils.instance + .getCities(code: currentProvince!.code.toString()); + + currentCity = cities.firstWhere((CityMunicipality cityMunicipality) => + event.work.address!.cityMunicipality!.code == + cityMunicipality.code); + } + emit(EditVoluntaryWorks( + overseas: event.isOverseas, + agencies: agencies, + agencyCategory: agencyCategory, + cities: cities, + countries: globalCountries, + positions: agencyPositions, + provinces: provinces, + regions: globalRegions, + work: event.work, + currentAgency: currentAgency, + currentCity: currentCity, + currentCountry: currentCountry, + currentPosition: currentPosition, + currentProvince: currentProvince, + currentRegion: currentRegion)); + } catch (e) { + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); + //// Delete + on((event, emit) async { + try { + final DateFormat formatter = DateFormat('yyyy-MM-dd'); + + final bool success = await VoluntaryService.instance.delete( + agencyId: event.work.agency!.id!, + positionId: event.work.position!.id!, + fromDate: formatter.format(event.work.fromDate!), + token: event.token, + profileId: event.profileId); + if (success) { + voluntaryWorks.removeWhere((VoluntaryWork element) => + element.position!.id == event.work.position!.id && + element.agency!.id == event.work.agency!.id && + element.fromDate == event.work.fromDate); + emit(VoluntaryWorkDeletedState(success: success)); + } else { + emit(VoluntaryWorkDeletedState(success: success)); + } + } catch (e) { + emit(VoluntaryWorkErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/profile/voluntary_works/voluntary_work_event.dart b/lib/bloc/profile/voluntary_works/voluntary_work_event.dart new file mode 100644 index 0000000..ba83ba5 --- /dev/null +++ b/lib/bloc/profile/voluntary_works/voluntary_work_event.dart @@ -0,0 +1,84 @@ +part of 'voluntary_work_bloc.dart'; + +abstract class VoluntaryWorkEvent extends Equatable { + const VoluntaryWorkEvent(); + + @override + List get props => []; +} + +class GetVoluntarWorks extends VoluntaryWorkEvent { + final int profileId; + final String token; + const GetVoluntarWorks({required this.profileId, required this.token}); + @override + List get props => [profileId, token]; +} + +class ShowAddVoluntaryWorks extends VoluntaryWorkEvent {} + +class ShowEditVoluntaryWorks extends VoluntaryWorkEvent { + final VoluntaryWork work; + final int profileId; + final String token; + final bool isOverseas; + // final int oldPosId; + // final int oldAgencyId; + // final String oldFromDate; + const ShowEditVoluntaryWorks( + {required this.profileId, + required this.token, + required this.work, + // required this.oldAgencyId, + // required this.oldFromDate, + // required this.oldPosId, + required this.isOverseas}); + @override + List get props => [profileId, token, work]; +} + +class LoadVoluntaryWorks extends VoluntaryWorkEvent {} + +class ShowErrorState extends VoluntaryWorkEvent { + final String message; + const ShowErrorState({required this.message}); +} + +class UpdateVolunataryWork extends VoluntaryWorkEvent{ + final int oldPosId; + final int oldAgencyId; + final String oldFromDate; + final VoluntaryWork work; + final int profileId; + final String token; + const UpdateVolunataryWork({required this.oldAgencyId, required this.oldFromDate, required this.oldPosId, required this.profileId, required this.token, required this.work}); +} +class AddVoluntaryWork extends VoluntaryWorkEvent { + final int profileId; + final String token; + final VoluntaryWork work; + const AddVoluntaryWork( + {required this.profileId, required this.token, required this.work}); + @override + List get props => [profileId, token, work]; +} + +class DeleteVoluntaryWork extends VoluntaryWorkEvent { + final String token; + final int profileId; + final VoluntaryWork work; + const DeleteVoluntaryWork( + {required this.profileId, required this.token, required this.work}); + @override + List get props => [profileId, token, work]; +} +class AddAttachment extends VoluntaryWorkEvent{ + final String categoryId; + final String attachmentModule; + final List filePaths; + final String token; + final String profileId; + const AddAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token}); + @override + List get props => [categoryId,attachmentModule,filePaths, token,profileId]; +} diff --git a/lib/bloc/profile/voluntary_works/voluntary_work_state.dart b/lib/bloc/profile/voluntary_works/voluntary_work_state.dart new file mode 100644 index 0000000..b489c79 --- /dev/null +++ b/lib/bloc/profile/voluntary_works/voluntary_work_state.dart @@ -0,0 +1,86 @@ +part of 'voluntary_work_bloc.dart'; + +abstract class VoluntaryWorkState extends Equatable { + const VoluntaryWorkState(); + + @override + List get props => []; +} + +class VoluntaryWorkInitial extends VoluntaryWorkState {} +////Loaded State +class VoluntaryWorkLoadedState extends VoluntaryWorkState{ + final List voluntaryWorks; + const VoluntaryWorkLoadedState({required this.voluntaryWorks}); + @override + List get props => [voluntaryWorks]; +} +////Error State +class VoluntaryWorkErrorState extends VoluntaryWorkState{ + final String message; + const VoluntaryWorkErrorState({required this.message}); + @override + List get props => [message]; +} +////Loading State +class VoluntaryWorkLoadingState extends VoluntaryWorkState{ + +} +////Added State +class VoluntaryWorkAddedState extends VoluntaryWorkState{ + final Map response; + const VoluntaryWorkAddedState({required this.response}); + @override + List get props => [response]; +} +////Edited State +class VoluntaryWorkEditedState extends VoluntaryWorkState{ + final Map response; + const VoluntaryWorkEditedState({required this.response}); + @override + List get props => [response]; +} +class EditVoluntaryWorks extends VoluntaryWorkState{ + final VoluntaryWork work; + final List positions; + final List agencies; + final List agencyCategory; + final List countries; + final List regions; + final List provinces; + final List cities; + final PositionTitle currentPosition; + final Agency currentAgency; + final Region? currentRegion; + final Country currentCountry; + final Province? currentProvince; + final CityMunicipality? currentCity; + final bool overseas; + const EditVoluntaryWorks({required this.agencies, required this.agencyCategory, required this.cities, required this.countries,required this.positions, required this.provinces, required this.regions, required this.work, required this.currentAgency, required this.currentCity,required this.currentCountry, required this.currentPosition, required this.currentProvince, required this.currentRegion,required this.overseas}); + +} + + +////Adding State +class AddVoluntaryWorkState extends VoluntaryWorkState{ + final List positions; + final List agencies; + final List agencyCategory; + final List countries; + final List regions; + const AddVoluntaryWorkState({required this.agencies,required this.countries, required this.positions, required this.regions,required this.agencyCategory}); + @override + List get props => [positions,agencies,countries,regions]; +} +////Add Attachment +class AttachmentAddedState extends VoluntaryWorkState { + final Map response; + const AttachmentAddedState({required this.response}); +} +//// Deleted State +class VoluntaryWorkDeletedState extends VoluntaryWorkState{ + final bool success; + const VoluntaryWorkDeletedState({required this.success}); + @override + List get props => [success]; +} diff --git a/lib/bloc/profile/workHistory/workHistory_bloc.dart b/lib/bloc/profile/workHistory/workHistory_bloc.dart new file mode 100644 index 0000000..c3f34f6 --- /dev/null +++ b/lib/bloc/profile/workHistory/workHistory_bloc.dart @@ -0,0 +1,256 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/profile/work_history.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/agency_position.dart'; +import 'package:unit2/model/utils/position.dart'; +import 'package:unit2/sevices/profile/work_history_services.dart'; +import 'package:unit2/utils/profile_utilities.dart'; +import '../../../model/profile/attachment.dart'; + +import '../../../model/utils/category.dart'; +import '../../../utils/attachment_services.dart'; +part 'workHistory_event.dart'; +part 'workHistory_state.dart'; + +class WorkHistoryBloc extends Bloc { + List workExperiences = []; + List agencyPositions = []; + List agencies = []; + List appointmentStatus = []; + List agencyCategory = []; + List attachmentCategories = []; + WorkHistoryBloc() : super(EducationInitial()) { + ////GET WORK HISTORIES + on((event, emit) async { + emit(WorkHistoryLoadingState()); + try { + if (attachmentCategories.isEmpty) { + attachmentCategories = + await AttachmentServices.instance.getCategories(); + } + if (workExperiences.isEmpty) { + List works = await WorkHistoryService.instance + .getWorkExperiences(event.profileId, event.token); + workExperiences = works; + } + emit(WorkHistoryLoaded( + workExperiences: workExperiences, + attachmentCategory: attachmentCategories)); + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); +///// LOAD WORK HISTORIES + on((event, emit) { + emit(WorkHistoryLoadingState()); + emit(WorkHistoryLoaded( + workExperiences: workExperiences, + attachmentCategory: attachmentCategories)); + }); + ////DELETE + on((event, emit) async { + try { + final bool success = await WorkHistoryService.instance.delete( + profileId: event.profileId, + token: event.token, + work: event.workHistory); + if (success) { + workExperiences.removeWhere( + (WorkHistory element) => element.id == event.workHistory.id); + emit(DeletedState(success: success)); + } else { + emit(DeletedState(success: success)); + } + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); + //// ADD WORK HISTORIES + on((event, emit) async { + try { + Map status = await WorkHistoryService.instance.add( + accomplishment: event.accomplishment, + actualDuties: event.actualDuties, + isPrivate: event.isPrivate, + workHistory: event.workHistory, + token: event.token, + profileId: event.profileId); + if (status['success']) { + WorkHistory workHistory = WorkHistory.fromJson(status['data']); + workExperiences.add(workHistory); + emit(WorkHistoryAddedState(response: status)); + } else { + emit(WorkHistoryAddedState(response: status)); + } + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); + +////UPDATE WORK HISTORY + on((event, emit) async { + // try { + Map status = await WorkHistoryService.instance.update( + isPrivate: event.isPrivate, + workHistory: event.workHistory, + token: event.token, + profileId: event.profileId); + if (status['success']) { + WorkHistory workHistory = WorkHistory.fromJson(status['data']); + // workExperiences.removeWhere((WorkHistory work) { + // return work.id == event.workHistory.id; + // }); + workExperiences.add(workHistory); + emit(WorkHistoryEditedState(response: status)); + } else { + emit(WorkHistoryEditedState( + response: status, + )); + } + // } catch (e) { + // emit(WorkHistoryErrorState(message: e.toString())); + // } + }); + +////SHOW EDIT WORK HISTORIES + on((event, emit) async { + try { + /////POSITIONS------------------------------------------ + if (agencyPositions.isEmpty) { + List positions = + await WorkHistoryService.instance.getAgencyPosition(); + agencyPositions = positions; + } + + /////AGENCIES------------------------------------------ + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + + /////Category Agency------------------------------------------ + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + /////////------------------------------------- + if (appointmentStatus.isEmpty) { + List status = + WorkHistoryService.instance.getAppointmentStatusList(); + appointmentStatus = status; + } + + emit(EditWorkHistoryState( + workHistory: event.workHistory, + agencyPositions: agencyPositions, + appointmentStatus: appointmentStatus, + agencyCategory: agencyCategory, + agencies: agencies)); + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); + ////SHOW ADD FORM WORK HISTORIES + on((event, emit) async { + emit(WorkHistoryLoadingState()); + try { + /////POSITIONS------------------------------------------ + if (agencyPositions.isEmpty) { + List positions = + await WorkHistoryService.instance.getAgencyPosition(); + agencyPositions = positions; + } + + /////AGENCIES------------------------------------------ + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + + /////Category Agency------------------------------------------ + if (agencyCategory.isEmpty) { + List categoryAgencies = + await ProfileUtilities.instance.agencyCategory(); + agencyCategory = categoryAgencies; + } + /////////------------------------------------- + if (appointmentStatus.isEmpty) { + List status = + WorkHistoryService.instance.getAppointmentStatusList(); + appointmentStatus = status; + } + + emit(AddWorkHistoryState( + agencyPositions: agencyPositions, + appointmentStatus: appointmentStatus, + agencyCategory: agencyCategory, + agencies: agencies)); + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); + ////Add Attachment + on((event, emit) async { + emit(WorkHistoryLoadingState()); + List attachments = []; + WorkHistory workHistory = workExperiences.firstWhere( + (element) => element.id.toString() == event.attachmentModule); + try { + Map status = await AttachmentServices.instance + .attachment( + categoryId: event.categoryId, + module: event.attachmentModule, + paths: event.filePaths, + token: event.token, + profileId: event.profileId); + if (status['success']) { + status['data'].forEach((element) { + Attachment newAttachment = Attachment.fromJson(element); + attachments.add(newAttachment); + }); + // workHistory.attachments == null + // ? workHistory.attachments = attachments + // : workHistory.attachments = [ + // ...workHistory.attachments!, + // ...attachments + // ]; + emit(WorkHistoryDevAttachmentAddedState(response: status)); + } else { + emit(WorkHistoryDevAttachmentAddedState(response: status)); + } + } catch (e) { + emit(WorkHistoryErrorState(message: e.toString())); + } + }); + // ////Delete Attachment + // on((event, emit) async { + // emit(WorkHistoryLoadingState()); + // try { + // final bool success = await AttachmentServices.instance.deleteAttachment( + // attachment: event.attachment, + // moduleId: event.moduleId, + // profileId: event.profileId.toString(), + // token: event.token); + // if (success) { + // final WorkHistory workHistory = + // workExperiences + // .firstWhere((element) => element.id == event.moduleId); + // workHistory.attachments + // ?.removeWhere((element) => element.id == event.attachment.id); + // workExperiences + // .removeWhere((element) => element.id == event.moduleId); + // workExperiences.add(workHistory); + // emit(WorkHistoryDevAttachmentDeletedState(success: success)); + // } else { + // emit(WorkHistoryDevAttachmentDeletedState(success: success)); + // } + // } catch (e) { + // emit(WorkHistoryErrorState(message: e.toString())); + // } + // }); + } +} diff --git a/lib/bloc/profile/workHistory/workHistory_event.dart b/lib/bloc/profile/workHistory/workHistory_event.dart new file mode 100644 index 0000000..a1a8ffc --- /dev/null +++ b/lib/bloc/profile/workHistory/workHistory_event.dart @@ -0,0 +1,89 @@ +part of 'workHistory_bloc.dart'; + +abstract class WorkHistorytEvent extends Equatable { + const WorkHistorytEvent(); + + @override + List get props => []; +} + +class GetWorkHistories extends WorkHistorytEvent{ + final int profileId; + final String token; + const GetWorkHistories({required this.profileId, required this.token}); + + + @override + List get props => [profileId, token]; +} + +class LoadWorkHistories extends WorkHistorytEvent{ + @override + List get props => []; +} + +class ShowAddWorkHistoryForm extends WorkHistorytEvent{ + +} +class ShowEditWorkHistoryForm extends WorkHistorytEvent{ + final WorkHistory workHistory; + const ShowEditWorkHistoryForm({required this.workHistory}); + @override + List get props => [workHistory]; + +} +class DeleteWorkHistory extends WorkHistorytEvent{ + final String token; + final int profileId; + final WorkHistory workHistory; + const DeleteWorkHistory({required this.profileId, required this.token, required this.workHistory}); + @override + List get props => [token, profileId,workHistory]; +} + +class UpdateWorkHistory extends WorkHistorytEvent{ + final WorkHistory workHistory; + final bool isPrivate; + final int profileId; + final String token; + + const UpdateWorkHistory({required this.profileId, required this.token, required this.workHistory, required this.isPrivate}); + @override + List get props => [profileId,token,workHistory,]; +} + +class AddWorkHostory extends WorkHistorytEvent{ + final WorkHistory workHistory; + final bool isPrivate; + final int profileId; + final String token; + final String? actualDuties; + final String? accomplishment; + const AddWorkHostory({required this.workHistory, required this.isPrivate, required this.profileId, required this.token, required this.accomplishment, required this.actualDuties}); + @override + List get props => [workHistory,profileId,token,isPrivate]; +} + +////Add Attachment +class AddWorkHistoryAttachment extends WorkHistorytEvent{ + final String categoryId; + final String attachmentModule; + final List filePaths; + final String token; + final String profileId; + const AddWorkHistoryAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token}); + @override + List get props => [categoryId,attachmentModule,filePaths, token,profileId]; +} + +////Delete Attachment +class DeleteWorkHistoryAttachment extends WorkHistorytEvent{ + final int moduleId; + final Attachment attachment; + final String token; + final int profileId; + const DeleteWorkHistoryAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token}); +} + + + diff --git a/lib/bloc/profile/workHistory/workHistory_state.dart b/lib/bloc/profile/workHistory/workHistory_state.dart new file mode 100644 index 0000000..478dc2f --- /dev/null +++ b/lib/bloc/profile/workHistory/workHistory_state.dart @@ -0,0 +1,94 @@ +part of 'workHistory_bloc.dart'; + +abstract class WorkHistoryState extends Equatable { + const WorkHistoryState(); + + @override + List get props => []; +} + +class EducationInitial extends WorkHistoryState {} + +class WorkHistoryLoaded extends WorkHistoryState{ + final List workExperiences; + final List< AttachmentCategory> attachmentCategory; + const WorkHistoryLoaded({required this.workExperiences,required this.attachmentCategory}); + @override + List get props => [workExperiences]; +} + +class WorkHistoryLoadingState extends WorkHistoryState{ + +} +class WorkHistoryErrorState extends WorkHistoryState{ + final String message; + const WorkHistoryErrorState({required this.message}); + + @override + List get props => [message]; +} + + + +class AddWorkHistoryState extends WorkHistoryState{ + final List agencyPositions; + final List agencies; + final List agencyCategory; + final List appointmentStatus; + + const AddWorkHistoryState({required this.agencyPositions, required this.appointmentStatus,required this.agencies,required this.agencyCategory}); + @override + List get props => [agencyPositions,appointmentStatus,agencies,agencyCategory]; + +} + +class EditWorkHistoryState extends WorkHistoryState{ + final WorkHistory workHistory; + final List agencyPositions; + final List agencies; + final List agencyCategory; + final List appointmentStatus; + const EditWorkHistoryState({required this.workHistory, required this.agencies,required this.agencyCategory, required this.agencyPositions, required this.appointmentStatus}); + @override + List get props => [workHistory, agencyPositions,appointmentStatus,agencies,agencyCategory]; +} + +class DeletedState extends WorkHistoryState{ + final bool success; + const DeletedState({required this.success}); + @override + List get props => [success]; +} + +class WorkHistoryEditedState extends WorkHistoryState{ + final Map response; + const WorkHistoryEditedState({required this.response}); + @override + List get props => [response]; +} + +class WorkHistoryAddedState extends WorkHistoryState{ + final Map response; + const WorkHistoryAddedState({required this.response}); + @override + List get props => [response]; +} + + +////Attachment AddedState +class WorkHistoryDevAttachmentAddedState extends WorkHistoryState { + final Map response; + const WorkHistoryDevAttachmentAddedState({required this.response}); + @override + List get props => [response]; +} + + + +////Attachment Deleted State State +class WorkHistoryDevAttachmentDeletedState extends WorkHistoryState { + final bool success; + const WorkHistoryDevAttachmentDeletedState({required this.success}); + @override + List get props => [success]; +} \ No newline at end of file diff --git a/lib/bloc/rbac/rbac_bloc.dart b/lib/bloc/rbac/rbac_bloc.dart new file mode 100644 index 0000000..8d8287a --- /dev/null +++ b/lib/bloc/rbac/rbac_bloc.dart @@ -0,0 +1,45 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/permission.dart'; +import 'package:unit2/sevices/roles/rbac_services.dart'; + +import '../../model/rbac/new_permission.dart'; +import '../../model/rbac/rbac.dart'; + +part 'rbac_event.dart'; +part 'rbac_state.dart'; + +class RbacBloc extends Bloc { + + RbacBloc() : super(RbacInitial()) { + List? modules; + List? objects; + List? roles; + List? permissions; + List? operations; + on((event, emit) async { + emit(RbacLoadingState()); + try { + modules = await RbacServices.instance.getModules(); + objects = await RbacServices.instance.getObjects(); + roles = await RbacServices.instance.getRole(); + permissions = await RbacServices.instance.getPermission(); + operations = await RbacServices.instance.getOperations(); + emit(RbacScreenSetted(modules: modules!, objects: objects!, operations: operations!, permission: permissions!, role: roles!)); + } catch (e) { + emit(RbacErrorState(message: e.toString())); + } + });on((event, emit)async{ + try{ + emit(RbacLoadingState()); + Map responseStatus = await RbacServices.instance.assignRBAC(assigneeId: event.assigneeId, assignerId: event.assignerId, selectedRole: event.selectedRole, selectedModule: event.selectedModule, permissionId: event.permissionId, newPermissions: event.newPermissions); + emit(RbacAssignedState(responseStatus: responseStatus)); + }catch(e){ + emit(RbacErrorState(message: e.toString())); + } + }); + on((event,emit){ + emit(RbacScreenSetted(modules: modules!, objects: objects!, operations: operations!, permission: permissions!, role: roles!)); + }); + } +} diff --git a/lib/bloc/rbac/rbac_event.dart b/lib/bloc/rbac/rbac_event.dart new file mode 100644 index 0000000..4daa43e --- /dev/null +++ b/lib/bloc/rbac/rbac_event.dart @@ -0,0 +1,29 @@ +part of 'rbac_bloc.dart'; + +abstract class RbacEvent extends Equatable { + const RbacEvent(); + + @override + List get props => []; +} + +class SetRbacScreen extends RbacEvent {} + +class AssignedRbac extends RbacEvent { + final int assigneeId; + final int assignerId; + final RBAC? selectedRole; + final RBAC? selectedModule; + final List permissionId; + final List newPermissions; + const AssignedRbac( + {required this.assigneeId, + required this.assignerId, + required this.newPermissions, + required this.permissionId, + required this.selectedModule, + required this.selectedRole}); +} +class LoadRbac extends RbacEvent{ + +} diff --git a/lib/bloc/rbac/rbac_operations/agency/agency_bloc.dart b/lib/bloc/rbac/rbac_operations/agency/agency_bloc.dart new file mode 100644 index 0000000..07ff0ce --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/agency/agency_bloc.dart @@ -0,0 +1,53 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/login_data/user_info/assigned_area.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/utils/profile_utilities.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../sevices/roles/rbac_operations/agency_services.dart'; + +part 'agency_event.dart'; +part 'agency_state.dart'; + +class AgencyBloc extends Bloc { + AgencyBloc() : super(AgencyInitial()) { + List agencies = []; + List agencyCategory = []; + on((event, emit) async { + emit(AgencyLoadingState()); + try { + if (agencies.isEmpty) { + agencies = await AgencyServices.instance.getAgencies(); + } + if (agencyCategory.isEmpty) { + agencyCategory = await ProfileUtilities.instance.agencyCategory(); + } + emit( + AgenciesLoaded(agencies: agencies, agencyCategory: agencyCategory)); + } catch (e) { + emit(AgencyErrorState(message: e.toString())); + } + }); + on((event,emit)async{ + if (agencyCategory.isEmpty) { + agencyCategory = await ProfileUtilities.instance.agencyCategory(); + } + }); + on((event, emit) async { + emit(AgencyLoadingState()); + try { + Map statusResponse = + await AgencyServices.instance.add(agency: event.agency); + if (statusResponse['success']) { + Agency newAgency = Agency.fromJson(statusResponse['data']); + agencies.insert(0,newAgency); + emit(AgencyAddesState(response: statusResponse)); + } else { + emit(AgencyAddesState(response: statusResponse)); + } + } catch (e) { + emit(AgencyErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/agency/agency_event.dart b/lib/bloc/rbac/rbac_operations/agency/agency_event.dart new file mode 100644 index 0000000..fece6bc --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/agency/agency_event.dart @@ -0,0 +1,21 @@ +part of 'agency_bloc.dart'; + +abstract class AgencyEvent extends Equatable { + const AgencyEvent(); + + @override + List get props => []; +} + +class GetAgencies extends AgencyEvent{ + +} +class AddAgency extends AgencyEvent{ + final Agency agency; + const AddAgency({required this.agency}); +} + +class GetEstPointPersonAgencies extends AgencyEvent{ + final List? assignedAreas; + const GetEstPointPersonAgencies({required this.assignedAreas}); +} diff --git a/lib/bloc/rbac/rbac_operations/agency/agency_state.dart b/lib/bloc/rbac/rbac_operations/agency/agency_state.dart new file mode 100644 index 0000000..22aadcb --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/agency/agency_state.dart @@ -0,0 +1,33 @@ +part of 'agency_bloc.dart'; + +abstract class AgencyState extends Equatable { + const AgencyState(); + + @override + List get props => []; +} + +class AgenciesLoaded extends AgencyState { + final List agencies; + final List agencyCategory; + const AgenciesLoaded({required this.agencies, required this.agencyCategory}); +} + +class AgencyErrorState extends AgencyState { + final String message; + const AgencyErrorState({required this.message}); +} + +class AgencyLoadingState extends AgencyState {} + +class AgencyAddesState extends AgencyState { + final Map response; + const AgencyAddesState({required this.response}); +} + +class AgencyDeletedState extends AgencyState { + final bool success; + const AgencyDeletedState({required this.success}); +} + +class AgencyInitial extends AgencyState {} diff --git a/lib/bloc/rbac/rbac_operations/module/module_bloc.dart b/lib/bloc/rbac/rbac_operations/module/module_bloc.dart new file mode 100644 index 0000000..6586411 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module/module_bloc.dart @@ -0,0 +1,84 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/roles/rbac_operations/module_services.dart'; +import '../../../../model/rbac/rbac.dart'; +part 'module_event.dart'; +part 'module_state.dart'; + +class ModuleBloc extends Bloc { + ModuleBloc() : super(ModuleInitial()) { + List modules = []; + on((event, emit) async { + emit(ModuleLoadingState()); + try { + if (modules.isEmpty) { + modules = await RbacModuleServices.instance.getRbacModule(); + } + + emit(ModuleLoaded(module: modules)); + } catch (e) { + emit(ModuleErrorState(message: e.toString())); + } + }); ////Add + on((event, emit) async { + try { + emit(ModuleLoadingState()); + Map statusResponse = await RbacModuleServices.instance + .add( + name: event.name!, + slug: event.slug, + short: event.shorthand, + id: event.id); + if (statusResponse['success']) { + RBAC newRole = RBAC.fromJson(statusResponse['data']); + modules.add(newRole); + emit(ModuleAddedState(response: statusResponse)); + } else { + emit(ModuleAddedState(response: statusResponse)); + } + } catch (e) { + emit(ModuleErrorState(message: e.toString())); + } + }); + ////update + on((event, emit) async { + emit(ModuleLoadingState()); + try { + Map statusResponse = await RbacModuleServices.instance + .update( + name: event.name, + slug: event.slug, + short: event.short, + moduleId: event.moduleId, + createdBy: event.createdBy, + updatedBy: event.updatedBy); + + if (statusResponse['success']) { + modules.removeWhere((element) => element.id == event.moduleId); + RBAC newRole = RBAC.fromJson(statusResponse['data']); + modules.add(newRole); + emit(ModuleUpdatedState(response: statusResponse)); + } else { + emit(ModuleUpdatedState(response: statusResponse)); + } + } catch (e) { + emit(ModuleErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(ModuleLoadingState()); + try { + bool success = await RbacModuleServices.instance + .deleteRbacModule(moduleId: event.moduleId); + if (success) { + modules.removeWhere((element) => element.id == event.moduleId); + emit(ModuleDeletedState(success: success)); + } else { + emit(ModuleDeletedState(success: success)); + } + } catch (e) { + emit(ModuleErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/module/module_event.dart b/lib/bloc/rbac/rbac_operations/module/module_event.dart new file mode 100644 index 0000000..53b9ed9 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module/module_event.dart @@ -0,0 +1,48 @@ +part of 'module_bloc.dart'; + +abstract class ModuleEvent extends Equatable { + const ModuleEvent(); + + @override + List get props => []; +} + + +class GetModule extends ModuleEvent{ + +} + +class AddRbacModule extends ModuleEvent { + final String? name; + final String? slug; + final String? shorthand; + final int id; + const AddRbacModule( + {required this.id, + required this.name, + required this.shorthand, + required this.slug}); +} + + +class UpdateRbacModule extends ModuleEvent { + final int moduleId; + final String name; + final String? slug; + final String? short; + final int? createdBy; + final int updatedBy; + const UpdateRbacModule({ + required this.moduleId, + required this.createdBy, + required this.name, + required this.short, + required this.slug, + required this.updatedBy, + }); +} + +class DeleteRbacModule extends ModuleEvent { + final int moduleId; + const DeleteRbacModule({required this.moduleId}); +} \ No newline at end of file diff --git a/lib/bloc/rbac/rbac_operations/module/module_state.dart b/lib/bloc/rbac/rbac_operations/module/module_state.dart new file mode 100644 index 0000000..7dcde63 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module/module_state.dart @@ -0,0 +1,36 @@ +part of 'module_bloc.dart'; + +abstract class ModuleState extends Equatable { + const ModuleState(); + + @override + List get props => []; +} + +class ModuleInitial extends ModuleState {} + +class ModuleLoaded extends ModuleState{ + final List module; + const ModuleLoaded({required this.module}); +} + +class ModuleLoadingState extends ModuleState{ + +} +class ModuleErrorState extends ModuleState{ + final String message; + const ModuleErrorState({required this.message}); +} + +class ModuleAddedState extends ModuleState { + final Map response; + const ModuleAddedState({required this.response}); +} +class ModuleUpdatedState extends ModuleState { + final Map response; + const ModuleUpdatedState({required this.response}); +} +class ModuleDeletedState extends ModuleState{ + final bool success; + const ModuleDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/module_objects/module_objects_bloc.dart b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_bloc.dart new file mode 100644 index 0000000..f401b3b --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_bloc.dart @@ -0,0 +1,82 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac_rbac.dart'; +import 'package:unit2/sevices/roles/rbac_operations/module_objects_services.dart'; +import 'package:unit2/sevices/roles/rbac_operations/object_services.dart'; + +import '../../../../model/rbac/rbac.dart'; +import '../../../../sevices/roles/rbac_operations/module_services.dart'; +part 'module_objects_event.dart'; +part 'module_objects_state.dart'; + +class ModuleObjectsBloc extends Bloc { + ModuleObjectsBloc() : super(ModuleObjectsInitial()) { + List moduleObjects = []; + List objects = []; + List modules = []; + List ids = []; + on((event, emit) async { + emit(ModuleObjectLoadingState()); + try { + if (moduleObjects.isEmpty) { + moduleObjects = + await RbacModuleObjectsServices.instance.getModuleObjects(); + } + if (objects.isEmpty) { + objects = await RbacObjectServices.instance.getRbacObjects(); + } + if (modules.isEmpty) { + modules = await RbacModuleServices.instance.getRbacModule(); + } + ids =[]; + for(var mo in moduleObjects){ + ids.add(mo.id); + } + emit(ModuleObjectLoadedState( + moduleObjects: moduleObjects, objecs: objects, modules: modules,ids: ids)); + } catch (e) { + emit(ModuleObjectsErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(ModuleObjectLoadingState()); + Map statusResponse = + await RbacModuleObjectsServices.instance.add( + assignerId: event.assignerId, + moduleId: event.moduleId, + objectsId: event.objectsId); + + if (statusResponse['success']) { + statusResponse['data'].forEach((var permission) { + ModuleObjects newModuleObject = ModuleObjects.fromJson(permission); + if(!ids.contains(newModuleObject.id)){ + moduleObjects.add(newModuleObject); + } + emit(ModuleObjectAddedState(response: statusResponse)); + }); + } else { + emit(ModuleObjectAddedState(response: statusResponse)); + } + } catch (e) { + emit(ModuleObjectsErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(ModuleObjectLoadingState()); + try { + bool success = await RbacModuleObjectsServices.instance + .deleteRbacModuleObject(moduleObjectId: event.moduleObjectId); + if (success) { + moduleObjects + .removeWhere((element) => element.id == event.moduleObjectId); + emit(ModuleObjectDeletedState(success: success)); + } else { + emit(ModuleObjectDeletedState(success: success)); + } + } catch (e) { + emit(ModuleObjectsErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/module_objects/module_objects_event.dart b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_event.dart new file mode 100644 index 0000000..65d9e89 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_event.dart @@ -0,0 +1,26 @@ +part of 'module_objects_bloc.dart'; + +abstract class ModuleObjectsEvent extends Equatable { + const ModuleObjectsEvent(); + + @override + List get props => []; +} + +class GetModuleObjects extends ModuleObjectsEvent {} + +class DeleteRbacModuleObject extends ModuleObjectsEvent { + final int moduleObjectId; + const DeleteRbacModuleObject({required this.moduleObjectId}); +} + +class AddRbacModuleObjects extends ModuleObjectsEvent { + final int moduleId; + final List objectsId; + final int assignerId; + const AddRbacModuleObjects( + {required this.assignerId, + required this.moduleId, + required this.objectsId}); +} + diff --git a/lib/bloc/rbac/rbac_operations/module_objects/module_objects_state.dart b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_state.dart new file mode 100644 index 0000000..3ae8984 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/module_objects/module_objects_state.dart @@ -0,0 +1,38 @@ +part of 'module_objects_bloc.dart'; + +abstract class ModuleObjectsState extends Equatable { + const ModuleObjectsState(); + + @override + List get props => []; +} + +class ModuleObjectsInitial extends ModuleObjectsState {} + +class ModuleObjectLoadedState extends ModuleObjectsState { + final List moduleObjects; + final List objecs; + final List modules; + final List ids; + const ModuleObjectLoadedState( + {required this.moduleObjects, + required this.modules, + required this.objecs,required this.ids}); +} + +class ModuleObjectsErrorState extends ModuleObjectsState { + final String message; + const ModuleObjectsErrorState({required this.message}); +} + +class ModuleObjectLoadingState extends ModuleObjectsState {} + +class ModuleObjectAddedState extends ModuleObjectsState { + final Map response; + const ModuleObjectAddedState({required this.response}); +} + +class ModuleObjectDeletedState extends ModuleObjectsState { + final bool success; + const ModuleObjectDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/object/object_bloc.dart b/lib/bloc/rbac/rbac_operations/object/object_bloc.dart new file mode 100644 index 0000000..024aa4d --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/object/object_bloc.dart @@ -0,0 +1,87 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/sevices/roles/rbac_operations/object_services.dart'; + +import '../../../../model/rbac/rbac.dart'; + +part 'object_event.dart'; +part 'object_state.dart'; + +class ObjectBloc extends Bloc { + ObjectBloc() : super(ObjectInitial()) { + List objects = []; + on((event, emit) async { + emit(ObjectLoadingState()); + try { + if (objects.isEmpty) { + objects = await RbacObjectServices.instance.getRbacObjects(); + } + emit(ObjectLoaded(objects: objects)); + } catch (e) { + emit(ObjectErrorState(message: e.toString())); + } + }); + ////Add + on((event, emit) async { + try { + emit(ObjectLoadingState()); + Map statusResponse = await RbacObjectServices.instance + .add( + name: event.name!, + slug: event.slug, + short: event.shorthand, + id: event.id); + if (statusResponse['success']) { + RBAC newObject = RBAC.fromJson(statusResponse['data']); + objects.add(newObject); + emit(ObjectAddedState(response: statusResponse)); + } else { + emit(ObjectAddedState(response: statusResponse)); + } + } catch (e) { + emit(ObjectErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(ObjectLoadingState()); + try { + Map statusResponse = await RbacObjectServices.instance + .update( + name: event.name, + slug: event.slug, + short: event.short, + objectId: event.objectId, + createdBy: event.createdBy, + updatedBy: event.updatedBy); + + if (statusResponse['success']) { + objects.removeWhere((element) => element.id == event.objectId); + RBAC newObject = RBAC.fromJson(statusResponse['data']); + objects.add(newObject); + emit(ObjectUpdatedState(response: statusResponse)); + } else { + emit(ObjectUpdatedState(response: statusResponse)); + } + } catch (e) { + emit(ObjectErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(ObjectLoadingState()); + try { + bool success = await RbacObjectServices.instance + .deleteRbacRole(objectId: event.objectId); + if (success) { + objects.removeWhere((element) => element.id == event.objectId); + emit(ObjectDeletedState(success: success)); + } else { + emit(ObjectDeletedState(success: success)); + } + } catch (e) { + emit(ObjectErrorState(message: e.toString())); + } + }); + } + } + + diff --git a/lib/bloc/rbac/rbac_operations/object/object_event.dart b/lib/bloc/rbac/rbac_operations/object/object_event.dart new file mode 100644 index 0000000..a654e0d --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/object/object_event.dart @@ -0,0 +1,46 @@ +part of 'object_bloc.dart'; + +abstract class ObjectEvent extends Equatable { + const ObjectEvent(); + + @override + List get props => []; +} + +class GetObjects extends ObjectEvent{ + +} +class AddRbacObject extends ObjectEvent { + final String? name; + final String? slug; + final String? shorthand; + final int id; + const AddRbacObject( + {required this.id, + required this.name, + required this.shorthand, + required this.slug}); +} + + +class UpdateRbacObject extends ObjectEvent { + final int objectId; + final String name; + final String? slug; + final String? short; + final int? createdBy; + final int updatedBy; + const UpdateRbacObject({ + required this.objectId, + required this.createdBy, + required this.name, + required this.short, + required this.slug, + required this.updatedBy, + }); +} + +class DeleteRbacObject extends ObjectEvent { + final int objectId; + const DeleteRbacObject({required this.objectId}); +} diff --git a/lib/bloc/rbac/rbac_operations/object/object_state.dart b/lib/bloc/rbac/rbac_operations/object/object_state.dart new file mode 100644 index 0000000..1c45114 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/object/object_state.dart @@ -0,0 +1,36 @@ +part of 'object_bloc.dart'; + +abstract class ObjectState extends Equatable { + const ObjectState(); + + @override + List get props => []; +} + +class ObjectInitial extends ObjectState {} + +class ObjectLoaded extends ObjectState{ + final List objects; + const ObjectLoaded({required this.objects}); +} + +class ObjectLoadingState extends ObjectState{ + +} + +class ObjectErrorState extends ObjectState{ + final String message; + const ObjectErrorState({required this.message}); +} +class ObjectAddedState extends ObjectState { + final Map response; + const ObjectAddedState({required this.response}); +} +class ObjectUpdatedState extends ObjectState { + final Map response; + const ObjectUpdatedState({required this.response}); +} +class ObjectDeletedState extends ObjectState{ + final bool success; + const ObjectDeletedState({required this.success}); +} \ No newline at end of file diff --git a/lib/bloc/rbac/rbac_operations/operation/operation_bloc.dart b/lib/bloc/rbac/rbac_operations/operation/operation_bloc.dart new file mode 100644 index 0000000..5dcf5e8 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/operation/operation_bloc.dart @@ -0,0 +1,84 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/sevices/roles/rbac_operations/operation_services.dart'; + +part 'operation_event.dart'; +part 'operation_state.dart'; + +class OperationBloc extends Bloc { + OperationBloc() : super(OperationInitial()) { + List operations = []; + on((event, emit) async { + emit(OperationLoadingState()); + try { + if (operations.isEmpty) { + operations = await RbacOperationServices.instance.getRbacOperations(); + } + + emit(OperationsLoaded(operations: operations)); + } catch (e) { + emit(OperationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(OperationLoadingState()); + Map statusResponse = + await RbacOperationServices.instance.add( + name: event.name!, + slug: event.slug, + short: event.shorthand, + id: event.id); + if (statusResponse['success']) { + RBAC newOperation = RBAC.fromJson(statusResponse['data']); + operations.add(newOperation); + emit(OperationAddedState(response: statusResponse)); + } else { + emit(OperationAddedState(response: statusResponse)); + } + } catch (e) { + emit(OperationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(OperationLoadingState()); + try { + Map statusResponse = + await RbacOperationServices.instance.update( + name: event.name, + slug: event.slug, + short: event.short, + operationId: event.operationId, + createdBy: event.createdBy, + updatedBy: event.updatedBy); + + if (statusResponse['success']) { + operations.removeWhere((element) => element.id == event.operationId); + RBAC newRole = RBAC.fromJson(statusResponse['data']); + operations.add(newRole); + emit(OperationUpdatedState(response: statusResponse)); + } else { + emit(OperationUpdatedState(response: statusResponse)); + } + } catch (e) { + emit(OperationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(OperationLoadingState()); + try { + bool success = await RbacOperationServices.instance + .delete(operation: event.operationId); + if (success) { + operations.removeWhere((element) => element.id == event.operationId); + emit(OperationDeletedState(success: success)); + } else { + emit(OperationDeletedState(success: success)); + } + } catch (e) { + emit(OperationErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/operation/operation_event.dart b/lib/bloc/rbac/rbac_operations/operation/operation_event.dart new file mode 100644 index 0000000..35bd990 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/operation/operation_event.dart @@ -0,0 +1,45 @@ +part of 'operation_bloc.dart'; + +abstract class OperationEvent extends Equatable { + const OperationEvent(); + + @override + List get props => []; +} +class GetOperations extends OperationEvent{ + +} +class AddRbacOperation extends OperationEvent { + final String? name; + final String? slug; + final String? shorthand; + final int id; + const AddRbacOperation( + {required this.id, + required this.name, + required this.shorthand, + required this.slug}); +} + + +class UpdateRbacOperation extends OperationEvent { + final int operationId; + final String name; + final String? slug; + final String? short; + final int? createdBy; + final int updatedBy; + const UpdateRbacOperation({ + required this.operationId, + required this.createdBy, + required this.name, + required this.short, + required this.slug, + required this.updatedBy, + }); +} + +class DeleteRbacOperation extends OperationEvent { + final int operationId; + const DeleteRbacOperation({required this.operationId}); +} diff --git a/lib/bloc/rbac/rbac_operations/operation/operation_state.dart b/lib/bloc/rbac/rbac_operations/operation/operation_state.dart new file mode 100644 index 0000000..4490f67 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/operation/operation_state.dart @@ -0,0 +1,34 @@ +part of 'operation_bloc.dart'; + +abstract class OperationState extends Equatable { + const OperationState(); + + @override + List get props => []; +} + +class OperationInitial extends OperationState {} + +class OperationsLoaded extends OperationState { + final List operations; + const OperationsLoaded({required this.operations}); +} + +class OperationLoadingState extends OperationState {} + +class OperationErrorState extends OperationState { + final String message; + const OperationErrorState({required this.message}); +} +class OperationAddedState extends OperationState { + final Map response; + const OperationAddedState({required this.response}); +} +class OperationUpdatedState extends OperationState { + final Map response; + const OperationUpdatedState({required this.response}); +} +class OperationDeletedState extends OperationState{ + final bool success; + const OperationDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/permission/permission_bloc.dart b/lib/bloc/rbac/rbac_operations/permission/permission_bloc.dart new file mode 100644 index 0000000..fe14035 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/permission/permission_bloc.dart @@ -0,0 +1,81 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/permission.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/screens/unit2/roles/rbac/add_rbac.dart'; +import 'package:unit2/sevices/roles/rbac_operations/permission_service.dart'; + +import '../../../../sevices/roles/rbac_operations/object_services.dart'; +import '../../../../sevices/roles/rbac_operations/operation_services.dart'; + +part 'permission_event.dart'; +part 'permission_state.dart'; + +class PermissionBloc extends Bloc { + PermissionBloc() : super(PermissionInitial()) { + List permissions = []; + List objects = []; + List operations = []; + on((event, emit) async { + try { + emit(PermissonLoadingState()); + if (permissions.isEmpty) { + permissions = + await RbacPermissionServices.instance.getRbacPermission(); + } + if (objects.isEmpty) { + objects = await RbacObjectServices.instance.getRbacObjects(); + } + if (operations.isEmpty) { + operations = await RbacOperationServices.instance.getRbacOperations(); + } + emit(PermissionLoaded( + permissions: permissions, + objects: objects, + operations: operations)); + } catch (e) { + emit(PermissionErrorState(message: e.toString())); + } + }); + ////Add + on((event, emit) async { + try { + emit(PermissonLoadingState()); + Map statusResponse = + await RbacPermissionServices.instance.add( + assignerId: event.assignerId, + objectId: event.objectId, + operationsId: event.operationIds); + if (statusResponse['success']) { + statusResponse['data'].forEach((var permission) { + RBACPermission newPermission = RBACPermission.fromJson(permission); + permissions.add(newPermission); + }); + + emit(PermissionAddedState(response: statusResponse)); + } else { + emit(PermissionAddedState(response: statusResponse)); + } + } catch (e) { + emit(PermissionErrorState(message: e.toString())); + } + }); + ////Delete + on((event, emit) async { + emit(PermissonLoadingState()); + try { + bool success = await RbacPermissionServices.instance + .deletePermission(permissionId: event.permissionId); + if (success) { + permissions + .removeWhere((element) => element.id == event.permissionId); + emit(PermissionDeletedState(success: success)); + } else { + emit(PermissionDeletedState(success: success)); + } + } catch (e) { + emit(PermissionErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/permission/permission_event.dart b/lib/bloc/rbac/rbac_operations/permission/permission_event.dart new file mode 100644 index 0000000..c1c2cc3 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/permission/permission_event.dart @@ -0,0 +1,25 @@ +part of 'permission_bloc.dart'; + +abstract class PermissionEvent extends Equatable { + const PermissionEvent(); + + @override + List get props => []; +} + +class GetPermissions extends PermissionEvent {} + +class AddRbacPermission extends PermissionEvent { + final int objectId; + final List operationIds; + final int assignerId; + const AddRbacPermission( + {required this.assignerId, + required this.objectId, + required this.operationIds}); +} + +class DeleteRbacPermission extends PermissionEvent { + final int permissionId; + const DeleteRbacPermission({required this.permissionId}); +} diff --git a/lib/bloc/rbac/rbac_operations/permission/permission_state.dart b/lib/bloc/rbac/rbac_operations/permission/permission_state.dart new file mode 100644 index 0000000..c8d2487 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/permission/permission_state.dart @@ -0,0 +1,37 @@ +part of 'permission_bloc.dart'; + +abstract class PermissionState extends Equatable { + const PermissionState(); + + @override + List get props => []; +} + +class PermissionInitial extends PermissionState {} + +class PermissionLoaded extends PermissionState { + final List permissions; + final List objects; + final List operations; + const PermissionLoaded( + {required this.permissions, + required this.objects, + required this.operations}); +} + +class PermissionAddedState extends PermissionState { + final Map response; + const PermissionAddedState({required this.response}); +} + +class PermissonLoadingState extends PermissionState {} + +class PermissionErrorState extends PermissionState { + final String message; + const PermissionErrorState({required this.message}); +} + +class PermissionDeletedState extends PermissionState { + final bool success; + const PermissionDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/role/role_bloc.dart b/lib/bloc/rbac/rbac_operations/role/role_bloc.dart new file mode 100644 index 0000000..5f9980b --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role/role_bloc.dart @@ -0,0 +1,83 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/sevices/roles/rbac_operations/role_services.dart'; +part 'role_event.dart'; +part 'role_state.dart'; + +class RoleBloc extends Bloc { + RoleBloc() : super(RoleInitial()) { + List roles = []; + on((event, emit) async { + try { + emit(RoleLoadingState()); + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + emit(RoleLoadedState(roles: roles)); + } catch (e) { + emit(RoleErrorState(message: e.toString())); + } + ////Add + }); + on((event, emit) async { + try { + emit(RoleLoadingState()); + Map statusResponse = await RbacRoleServices.instance + .add( + name: event.name!, + slug: event.slug, + short: event.shorthand, + id: event.id); + if (statusResponse['success']) { + RBAC newRole = RBAC.fromJson(statusResponse['data']); + roles.add(newRole); + emit(RoleAddedState(response: statusResponse)); + } else { + emit(RoleAddedState(response: statusResponse)); + } + } catch (e) { + emit(RoleErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleLoadingState()); + try { + Map statusResponse = await RbacRoleServices.instance + .update( + name: event.name, + slug: event.slug, + short: event.short, + roleId: event.roleId, + createdBy: event.createdBy, + updatedBy: event.updatedBy); + + if (statusResponse['success']) { + roles.removeWhere((element) => element.id == event.roleId); + RBAC newRole = RBAC.fromJson(statusResponse['data']); + roles.add(newRole); + emit(RoleUpdatedState(response: statusResponse)); + } else { + emit(RoleUpdatedState(response: statusResponse)); + } + } catch (e) { + emit(RoleErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleLoadingState()); + try { + bool success = await RbacRoleServices.instance + .deleteRbacRole(roleId: event.roleId); + if (success) { + roles.removeWhere((element) => element.id == event.roleId); + emit(RoleDeletedState(success: success)); + } else { + emit(RoleDeletedState(success: success)); + } + } catch (e) { + emit(RoleErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/role/role_event.dart b/lib/bloc/rbac/rbac_operations/role/role_event.dart new file mode 100644 index 0000000..60987d9 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role/role_event.dart @@ -0,0 +1,45 @@ +part of 'role_bloc.dart'; + +abstract class RoleEvent extends Equatable { + const RoleEvent(); + + @override + List get props => []; +} + +class GetRoles extends RoleEvent {} + +class AddRbacRole extends RoleEvent { + final String? name; + final String? slug; + final String? shorthand; + final int id; + const AddRbacRole( + {required this.id, + required this.name, + required this.shorthand, + required this.slug}); +} + + +class UpdateRbacRole extends RoleEvent { + final int roleId; + final String name; + final String? slug; + final String? short; + final int? createdBy; + final int updatedBy; + const UpdateRbacRole({ + required this.roleId, + required this.createdBy, + required this.name, + required this.short, + required this.slug, + required this.updatedBy, + }); +} + +class DeleteRbacRole extends RoleEvent { + final int roleId; + const DeleteRbacRole({required this.roleId}); +} diff --git a/lib/bloc/rbac/rbac_operations/role/role_state.dart b/lib/bloc/rbac/rbac_operations/role/role_state.dart new file mode 100644 index 0000000..255ce6e --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role/role_state.dart @@ -0,0 +1,37 @@ +part of 'role_bloc.dart'; + +abstract class RoleState extends Equatable { + const RoleState(); + + @override + List get props => []; +} + +class RoleInitial extends RoleState {} + +class RoleLoadedState extends RoleState { + final List roles; + const RoleLoadedState({required this.roles}); +} + +class RoleLoadingState extends RoleState {} + +class RoleErrorState extends RoleState { + final String message; + const RoleErrorState({required this.message}); +} + +class RoleAddedState extends RoleState { + final Map response; + const RoleAddedState({required this.response}); +} +class RoleUpdatedState extends RoleState { + final Map response; + const RoleUpdatedState({required this.response}); +} +class RoleDeletedState extends RoleState{ + final bool success; + const RoleDeletedState({required this.success}); +} + + diff --git a/lib/bloc/rbac/rbac_operations/role_extend/role_extend_bloc.dart b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_bloc.dart new file mode 100644 index 0000000..85e6837 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_bloc.dart @@ -0,0 +1,73 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/role_extend.dart'; +import 'package:unit2/sevices/roles/rbac_operations/role_extend_services.dart'; +import '../../../../model/rbac/rbac.dart'; +import '../../../../sevices/roles/rbac_operations/role_services.dart'; + +part 'role_extend_event.dart'; +part 'role_extend_state.dart'; + +class RoleExtendBloc extends Bloc { + RoleExtendBloc() : super(RoleExtendInitial()) { + List rolesExtend = []; + List roleExtendIds = []; + List roles = []; + on((event, emit) async { + emit(RoleExtendLoadingState()); + try { + if (rolesExtend.isEmpty) { + rolesExtend = await RbacRoleExtendServices.instance.getRolesExtend(); + } + + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + for (var roleExt in rolesExtend) { + roleExtendIds.add(roleExt.id); + } + emit(RoleExtendLoadedState(rolesExtend: rolesExtend, roles: roles)); + } catch (e) { + emit(RoleExtendErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(RoleExtendLoadingState()); + Map statusResponse = await RbacRoleExtendServices + .instance + .add(roleId: event.roleId, rolesExtendsId: event.roleExtendsId); + + if (statusResponse['success']) { + statusResponse['data'].forEach((var roleExt) { + RolesExtend newRoleExtend = RolesExtend.fromJson(roleExt); + if(!roleExtendIds.contains(newRoleExtend.id)){ + rolesExtend.add(newRoleExtend); + } + }); + emit(RoleExtendAddedState(response: statusResponse)); + } else { + emit(RoleExtendAddedState(response: statusResponse)); + } + } catch (e) { + emit(RoleExtendErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleExtendLoadingState()); + try { + bool success = await RbacRoleExtendServices.instance + .delete(roleExtendId: event.roleExtendId); + if (success) { + rolesExtend + .removeWhere((element) => element.id == event.roleExtendId); + emit(RoleExtendDeletedState(success: success)); + } else { + emit(RoleExtendDeletedState(success: success)); + } + } catch (e) { + emit(RoleExtendErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/role_extend/role_extend_event.dart b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_event.dart new file mode 100644 index 0000000..c0b4637 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_event.dart @@ -0,0 +1,21 @@ +part of 'role_extend_bloc.dart'; + +abstract class RoleExtendEvent extends Equatable { + const RoleExtendEvent(); + + @override + List get props => []; +} + +class GetRoleExtend extends RoleExtendEvent {} + +class DeleteRoleExtend extends RoleExtendEvent { + final int roleExtendId; + const DeleteRoleExtend({required this.roleExtendId}); +} + +class AddRoleExtend extends RoleExtendEvent { + final int roleId; + final List roleExtendsId; + const AddRoleExtend({required this.roleId, required this.roleExtendsId}); +} diff --git a/lib/bloc/rbac/rbac_operations/role_extend/role_extend_state.dart b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_state.dart new file mode 100644 index 0000000..8e788cb --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_extend/role_extend_state.dart @@ -0,0 +1,34 @@ +part of 'role_extend_bloc.dart'; + +abstract class RoleExtendState extends Equatable { + const RoleExtendState(); + + @override + List get props => []; +} + +class RoleExtendInitial extends RoleExtendState {} + +class RoleExtendLoadedState extends RoleExtendState { + final List rolesExtend; + final List roles; + + const RoleExtendLoadedState({required this.rolesExtend, required this.roles}); +} + +class RoleExtendLoadingState extends RoleExtendState {} + +class RoleExtendErrorState extends RoleExtendState { + final String message; + const RoleExtendErrorState({required this.message}); +} + +class RoleExtendAddedState extends RoleExtendState { + final Map response; + const RoleExtendAddedState({required this.response}); +} + +class RoleExtendDeletedState extends RoleExtendState { + final bool success; + const RoleExtendDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/role_module/role_module_bloc.dart b/lib/bloc/rbac/rbac_operations/role_module/role_module_bloc.dart new file mode 100644 index 0000000..3f52bd4 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_module/role_module_bloc.dart @@ -0,0 +1,72 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/sevices/roles/rbac_operations/role_module_services.dart'; +import 'package:unit2/sevices/roles/rbac_operations/role_services.dart'; +import '../../../../model/rbac/role_module.dart'; +import '../../../../sevices/roles/rbac_operations/module_services.dart'; +part 'role_module_event.dart'; +part 'role_module_state.dart'; + +class RoleModuleBloc extends Bloc { + RoleModuleBloc() : super(RoleModuleInitial()) { + List roleModules = []; + List roles = []; + List modules = []; + on((event, emit) async { + emit(RoleModuleLoadingState()); + try { + if (roleModules.isEmpty) { + roleModules = await RbacRoleModuleServices.instance.getRoleModules(); + } + if (modules.isEmpty) { + modules = await RbacModuleServices.instance.getRbacModule(); + } + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + emit(RoleModuleLoadedState(roleModules: roleModules,modules: modules,roles: roles)); + } catch (e) { + emit(RoleModuleErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(RoleModuleLoadingState()); + Map statusResponse = + await RbacRoleModuleServices.instance.add( + assignerId: event.assignerId, + roleId: event.roleId, + moduleIds: event.moduleIds); + + if (statusResponse['success']) { + statusResponse['data'].forEach((var roleMod) { + RoleModules newRoleModule = RoleModules.fromJson(roleMod); + roleModules.add(newRoleModule); + emit(RoleModuleAddedState(response: statusResponse)); + }); + } else { + emit(RoleModuleAddedState(response: statusResponse)); + } + } catch (e) { + emit(RoleModuleErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleModuleLoadingState()); + try { + bool success = await RbacRoleModuleServices.instance + .deleteRbacRoleModule(moduleObjectId: event.roleModuleId); + if (success) { + roleModules + .removeWhere((element) => element.id == event.roleModuleId); + emit(RoleModuleDeletedState(success: success)); + } else { + RoleModuleDeletedState(success: success); + } + } catch (e) { + emit(RoleModuleErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/role_module/role_module_event.dart b/lib/bloc/rbac/rbac_operations/role_module/role_module_event.dart new file mode 100644 index 0000000..b0cfa8a --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_module/role_module_event.dart @@ -0,0 +1,25 @@ +part of 'role_module_bloc.dart'; + +abstract class RoleModuleEvent extends Equatable { + const RoleModuleEvent(); + + @override + List get props => []; +} + +class GetRoleModules extends RoleModuleEvent {} + +class DeleteRoleModule extends RoleModuleEvent { + final int roleModuleId; + const DeleteRoleModule({required this.roleModuleId}); +} + +class AddRoleModule extends RoleModuleEvent { + final int roleId; + final List moduleIds; + final int assignerId; + const AddRoleModule( + {required this.assignerId, + required this.roleId, + required this.moduleIds}); +} diff --git a/lib/bloc/rbac/rbac_operations/role_module/role_module_state.dart b/lib/bloc/rbac/rbac_operations/role_module/role_module_state.dart new file mode 100644 index 0000000..733d56c --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/role_module/role_module_state.dart @@ -0,0 +1,36 @@ +part of 'role_module_bloc.dart'; + +abstract class RoleModuleState extends Equatable { + const RoleModuleState(); + + @override + List get props => []; +} + +class RoleModuleInitial extends RoleModuleState {} + +class RoleModuleLoadedState extends RoleModuleState { + final List roleModules; + final List roles; + final List modules; + + const RoleModuleLoadedState( + {required this.roleModules, required this.modules, required this.roles}); +} + +class RoleModuleLoadingState extends RoleModuleState {} + +class RoleModuleErrorState extends RoleModuleState { + final String message; + const RoleModuleErrorState({required this.message}); +} + +class RoleModuleAddedState extends RoleModuleState { + final Map response; + const RoleModuleAddedState({required this.response}); +} + +class RoleModuleDeletedState extends RoleModuleState { + final bool success; + const RoleModuleDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart new file mode 100644 index 0000000..f8fc508 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart @@ -0,0 +1,67 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/role_under.dart'; +import 'package:unit2/sevices/roles/rbac_operations/roles_under_services.dart'; + +import '../../../../model/rbac/rbac.dart'; +import '../../../../sevices/roles/rbac_operations/role_services.dart'; + +part 'roles_under_event.dart'; +part 'roles_under_state.dart'; + +class RolesUnderBloc extends Bloc { + RolesUnderBloc() : super(RolesUnderInitial()) { + List rolesUnder = []; + List roles = []; + on((event, emit) async { + emit(RoleUnderLoadingState()); + try { + if (rolesUnder.isEmpty) { + rolesUnder = await RbacRoleUnderServices.instance.getRolesUnder(); + } + + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + emit(RoleUnderLoadedState(rolesUnder: rolesUnder, roles: roles)); + } catch (e) { + emit(RoleUnderErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(RoleUnderLoadingState()); + Map statusResponse = await RbacRoleUnderServices + .instance + .add(roleId: event.roleId, rolesId: event.roleUnderIds); + + if (statusResponse['success']) { + statusResponse['data'].forEach((var roleMod) { + RolesUnder newRoleUnder = RolesUnder.fromJson(roleMod); + rolesUnder.add(newRoleUnder); + emit(RoleUnderAddedState(response: statusResponse)); + }); + } else { + emit(RoleUnderAddedState(response: statusResponse)); + } + } catch (e) { + emit(RoleUnderErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleUnderLoadingState()); + try { + bool success = await RbacRoleUnderServices.instance + .deleteRbacRoleUnder(roleUnderId: event.roleUnderId); + if (success) { + rolesUnder.removeWhere((element) => element.id == event.roleUnderId); + emit(RoleUnderDeletedState(success: success)); + } else { + emit(RoleUnderDeletedState(success: success)); + } + } catch (e) { + emit(RoleUnderErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/rbac/rbac_operations/roles_under/roles_under_event.dart b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_event.dart new file mode 100644 index 0000000..3c17f46 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_event.dart @@ -0,0 +1,21 @@ +part of 'roles_under_bloc.dart'; + +abstract class RolesUnderEvent extends Equatable { + const RolesUnderEvent(); + + @override + List get props => []; +} + +class GetRolesUnder extends RolesUnderEvent {} + +class DeleteRoleUnder extends RolesUnderEvent { + final int roleUnderId; + const DeleteRoleUnder({required this.roleUnderId}); +} + +class AddRoleUnder extends RolesUnderEvent{ + final int roleId; + final List roleUnderIds; + const AddRoleUnder({required this.roleId, required this.roleUnderIds}); +} diff --git a/lib/bloc/rbac/rbac_operations/roles_under/roles_under_state.dart b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_state.dart new file mode 100644 index 0000000..0263414 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/roles_under/roles_under_state.dart @@ -0,0 +1,34 @@ +part of 'roles_under_bloc.dart'; + +abstract class RolesUnderState extends Equatable { + const RolesUnderState(); + + @override + List get props => []; +} + +class RolesUnderInitial extends RolesUnderState {} + +class RoleUnderLoadedState extends RolesUnderState { + final List rolesUnder; + final List roles; + + const RoleUnderLoadedState({required this.rolesUnder, required this.roles}); +} + +class RoleUnderLoadingState extends RolesUnderState {} + +class RoleUnderErrorState extends RolesUnderState { + final String message; + const RoleUnderErrorState({required this.message}); +} + +class RoleUnderAddedState extends RolesUnderState { + final Map response; + const RoleUnderAddedState({required this.response}); +} + +class RoleUnderDeletedState extends RolesUnderState { + final bool success; + const RoleUnderDeletedState({required this.success}); +} diff --git a/lib/bloc/rbac/rbac_operations/station/station_bloc.dart b/lib/bloc/rbac/rbac_operations/station/station_bloc.dart new file mode 100644 index 0000000..79a9597 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/station/station_bloc.dart @@ -0,0 +1,85 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac_station.dart'; +import 'package:unit2/sevices/roles/rbac_operations/station_services.dart'; +import '../../../../model/rbac/station_type.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/position.dart'; +import '../../../../utils/profile_utilities.dart'; +part 'station_event.dart'; +part 'station_state.dart'; + +class StationBloc extends Bloc { + StationBloc() : super(StationInitial()) { + List stations = []; + List agencies = []; + List stationTypes = []; + List positions = []; + on((event, emit) async { + emit(StationLoadingState()); + try { + stations = await RbacStationServices.instance + .getStations(agencyId: event.agencyId.toString()); + + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + if (stationTypes.isEmpty) { + stationTypes = await RbacStationServices.instance.getStationTypes(); + } + if (positions.isEmpty) { + positions = await RbacStationServices.instance.getPositionTitle(); + } + emit(StationLoadedState( + stations: stations, + agencies: agencies, + stationTypes: stationTypes, + positions: positions)); + } catch (e) { + emit(StationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(StationLoadingState()); + try { + Map statusResponse = await RbacStationServices + .instance + .addStation(station: event.station); + if (statusResponse['success']) { + RbacStation newStation = RbacStation.fromJson(statusResponse['data']); + stations.add(newStation); + emit(RbacStationAddedState(response: statusResponse)); + } else { + emit(RbacStationAddedState(response: statusResponse)); + } + } catch (e) { + emit(StationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(StationLoadingState()); + + try { + stations = await RbacStationServices.instance + .getStations(agencyId: event.agencyId.toString()); + + if (agencies.isEmpty) { + List newAgencies = + await ProfileUtilities.instance.getAgecies(); + agencies = newAgencies; + } + emit(StationLoadedState( + stations: stations, + agencies: agencies, + positions: positions, + stationTypes: stationTypes)); + } catch (e) { + emit(StationErrorState(message: e.toString())); + } + }); + + + } +} diff --git a/lib/bloc/rbac/rbac_operations/station/station_event.dart b/lib/bloc/rbac/rbac_operations/station/station_event.dart new file mode 100644 index 0000000..bf26ec8 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/station/station_event.dart @@ -0,0 +1,26 @@ +part of 'station_bloc.dart'; + +abstract class StationEvent extends Equatable { + const StationEvent(); + + @override + List get props => []; +} + +class GetStations extends StationEvent { + final int agencyId; + const GetStations({required this.agencyId}); + @override + List get props => [agencyId]; +} + +class FilterStation extends StationEvent { + final int agencyId; + const FilterStation({required this.agencyId}); + @override + List get props => [agencyId]; +} +class AddRbacStation extends StationEvent { + final RbacStation station; + const AddRbacStation({required this.station}); +} diff --git a/lib/bloc/rbac/rbac_operations/station/station_state.dart b/lib/bloc/rbac/rbac_operations/station/station_state.dart new file mode 100644 index 0000000..0494c90 --- /dev/null +++ b/lib/bloc/rbac/rbac_operations/station/station_state.dart @@ -0,0 +1,45 @@ +part of 'station_bloc.dart'; + +abstract class StationState extends Equatable { + const StationState(); + + @override + List get props => []; +} + +class StationInitial extends StationState {} + +class StationLoadedState extends StationState { + final List agencies; + final List stations; + final List stationTypes; + final List positions; + const StationLoadedState({required this.stations, required this.agencies,required this.positions, required this.stationTypes}); + @override + List get props => [agencies,stations,stationTypes,positions]; +} + +class StationLoadingState extends StationState {} + +class StationErrorState extends StationState { + final String message; + const StationErrorState({required this.message}); + @override + List get props => [message]; +} + +class FilterStationState extends StationState { + final List agencies; + final List stations; + final List stationTypes; + final List positions; + const FilterStationState({required this.stations, required this.agencies,required this.positions, required this.stationTypes}); + @override + List get props => [agencies,stations,stationTypes,positions]; +} + +class RbacStationAddedState extends StationState{ + final Map response; + const RbacStationAddedState({required this.response}); +} + diff --git a/lib/bloc/rbac/rbac_state.dart b/lib/bloc/rbac/rbac_state.dart new file mode 100644 index 0000000..6c793a5 --- /dev/null +++ b/lib/bloc/rbac/rbac_state.dart @@ -0,0 +1,36 @@ +part of 'rbac_bloc.dart'; + +abstract class RbacState extends Equatable { + const RbacState(); + + @override + List get props => []; +} + +class RbacInitial extends RbacState {} + +class RbacScreenSetted extends RbacState { + final List modules; + final List objects; + final List role; + final List permission; + final List operations; + const RbacScreenSetted( + {required this.modules, + required this.objects, + required this.operations, + required this.permission, + required this.role}); +} + +class RbacLoadingState extends RbacState {} + +class RbacErrorState extends RbacState { + final String message; + const RbacErrorState({required this.message}); +} + +class RbacAssignedState extends RbacState{ +final Map responseStatus; + const RbacAssignedState({required this.responseStatus}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart new file mode 100644 index 0000000..0c1db96 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart @@ -0,0 +1,31 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/login_data/user_info/assigned_area.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/category.dart'; + +import '../../../../../utils/profile_utilities.dart'; + +part 'assign_area_agency_event.dart'; +part 'assign_area_agency_state.dart'; + +class AssignAreaAgencyBloc + extends Bloc { + AssignAreaAgencyBloc() : super(AssignAreaAgencyInitial()) { + List? agencies = []; + List agencyCategory = []; + on((event, emit) async { + emit(EstPointPersonAgencyLoadingState()); + try { + if (agencyCategory.isEmpty) { + agencyCategory = await ProfileUtilities.instance.agencyCategory(); + } + agencies = event.assignedAreas; + emit(EstPointPersonAgenciesLoaded( + agencies: agencies, agencyCategory: agencyCategory)); + } catch (e) { + emit(EstPointAgencyErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_event.dart b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_event.dart new file mode 100644 index 0000000..a1dcf49 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_event.dart @@ -0,0 +1,18 @@ +part of 'assign_area_agency_bloc.dart'; + +abstract class AssignAreaAgencyEvent extends Equatable { + const AssignAreaAgencyEvent(); + + @override + List get props => []; +} + +class EstPointPersonGetAgencies extends AssignAreaAgencyEvent { + final List? assignedAreas; + const EstPointPersonGetAgencies({required this.assignedAreas}); +} + +class EstPointPersonAddAgency extends AssignAreaAgencyEvent { + final Agency agency; + const EstPointPersonAddAgency({required this.agency}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_state.dart b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_state.dart new file mode 100644 index 0000000..40d9ff3 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_state.dart @@ -0,0 +1,34 @@ +part of 'assign_area_agency_bloc.dart'; + +abstract class AssignAreaAgencyState extends Equatable { + const AssignAreaAgencyState(); + + @override + List get props => []; + + get message => null; +} + +class AssignAreaAgencyInitial extends AssignAreaAgencyState {} +class EstPointPersonAgenciesLoaded extends AssignAreaAgencyState { + final List? agencies; + final List agencyCategory; + const EstPointPersonAgenciesLoaded({required this.agencies, required this.agencyCategory}); +} + +class EstPointAgencyErrorState extends AssignAreaAgencyState { + final String message; + const EstPointAgencyErrorState({required this.message}); +} + +class EstPointPersonAgencyLoadingState extends AssignAreaAgencyState {} + +class EstPointPersonAgencyAddesState extends AssignAreaAgencyState { + final Map response; + const EstPointPersonAgencyAddesState({required this.response}); +} + +class EstPointPersonAgencyDeletedState extends AssignAreaAgencyState { + final bool success; + const EstPointPersonAgencyDeletedState({required this.success}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart new file mode 100644 index 0000000..0ca0aef --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart @@ -0,0 +1,79 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/model/rbac/role_under.dart'; + +import '../../../../../sevices/roles/est_point_person/est_point_person_role_assignment_services.dart'; +import '../../../../../sevices/roles/rbac_operations/role_services.dart'; +import '../../../../../sevices/roles/rbac_operations/roles_under_services.dart'; + +part 'est_point_person_assinable_role_event.dart'; +part 'est_point_person_assinable_role_state.dart'; + +class EstPointPersonAssinableRoleBloc extends Bloc< + EstPointPersonAssinableRoleEvent, EstPointPersonAssinableRoleState> { + EstPointPersonAssinableRoleBloc() + : super(EstPointPersonAssinableRoleInitial()) { + List rolesUnder = []; + List roles = []; + RBAC? mainRole; + on((event, emit) async { + emit(EstPointPersonAssignableRoleLoadingState()); + try { + if (rolesUnder.isEmpty) { + List rolesUnders = await EstPointPersonRoleAssignment + .instance + .getRolesUnder(roleId: event.roleId); + for (var roleUnder in rolesUnders) { + RBAC roleChild = roleUnder.roleUnderChild; + roleChild.id = roleUnder.id; + rolesUnder.add(roleUnder.roleUnderChild); + } + } + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + RBAC role = roles.firstWhere((e) => e.id == event.roleId); + mainRole = role; + emit(EstPointPersonAssignableRoleLoaded( + roles: roles, rolesUnder: rolesUnder, mainRole: role)); + } catch (e) { + emit(EstPointPersonAssignableErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + emit(EstPointPersonAssignableRoleLoadingState()); + Map statusResponse = await RbacRoleUnderServices + .instance + .add(roleId: event.mainRoleId, rolesId: event.rolesUnder); + + if (statusResponse['success']) { + emit(EstPointPersonAssignableRoleLoaded( + mainRole: mainRole!, roles: roles, rolesUnder: rolesUnder)); + } else { + emit(EstPointPersonAssignableRoleLoaded( + mainRole: mainRole!, roles: roles, rolesUnder: rolesUnder)); + } + } catch (e) { + emit(EstPointPersonAssignableErrorState(message: e.toString())); + } + }); + + on((event, emit) async { + emit(EstPointPersonAssignableRoleLoadingState()); + try { + bool success = await RbacRoleUnderServices.instance + .deleteRbacRoleUnder(roleUnderId: event.roleId); + if (success) { + rolesUnder.removeWhere((element) => element.id == event.roleId); + emit(EstPointPersonAssignableDeletedState(success: success)); + } else { + emit(EstPointPersonAssignableDeletedState(success: success)); + } + } catch (e) { + emit(EstPointPersonAssignableErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_event.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_event.dart new file mode 100644 index 0000000..8d4fb53 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_event.dart @@ -0,0 +1,28 @@ +part of 'est_point_person_assinable_role_bloc.dart'; + +abstract class EstPointPersonAssinableRoleEvent extends Equatable { + const EstPointPersonAssinableRoleEvent(); + + @override + List get props => []; +} + +class GetEstPointPersonAssignableRoles + extends EstPointPersonAssinableRoleEvent { + final int roleId; + const GetEstPointPersonAssignableRoles({required this.roleId}); +} + +class AddEstPointPersonAssignableRoles + extends EstPointPersonAssinableRoleEvent { + final int mainRoleId; + final List rolesUnder; + const AddEstPointPersonAssignableRoles( + {required this.mainRoleId, required this.rolesUnder}); +} + +class DeleteEstPointPersonAssignableRoles + extends EstPointPersonAssinableRoleEvent { + final int roleId; + const DeleteEstPointPersonAssignableRoles({required this.roleId}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_state.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_state.dart new file mode 100644 index 0000000..3ce7cbe --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_state.dart @@ -0,0 +1,38 @@ +part of 'est_point_person_assinable_role_bloc.dart'; + +abstract class EstPointPersonAssinableRoleState extends Equatable { + const EstPointPersonAssinableRoleState(); + + @override + List get props => []; +} + +class EstPointPersonAssignableRoleLoadingState + extends EstPointPersonAssinableRoleState {} + +class EstPointPersonAssignableErrorState + extends EstPointPersonAssinableRoleState { + final String message; + const EstPointPersonAssignableErrorState({required this.message}); +} + +class EstPointPersonAssginableRoleAssignState + extends EstPointPersonAssinableRoleState { + final Map responseStatus; + const EstPointPersonAssginableRoleAssignState({required this.responseStatus}); +} + +class EstPointPersonAssinableRoleInitial + extends EstPointPersonAssinableRoleState {} + +class EstPointPersonAssignableRoleLoaded + extends EstPointPersonAssinableRoleState { + final List roles; + final List rolesUnder; + final RBAC mainRole; + const EstPointPersonAssignableRoleLoaded({required this.roles, required this.rolesUnder, required this.mainRole}); +} +class EstPointPersonAssignableDeletedState extends EstPointPersonAssinableRoleState { + final bool success; + const EstPointPersonAssignableDeletedState({required this.success}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart new file mode 100644 index 0000000..b85da22 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart @@ -0,0 +1,79 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/rbac/assigned_role.dart'; +import 'package:unit2/model/rbac/role_under.dart'; + +import '../../../../../model/rbac/rbac.dart'; +import '../../../../../sevices/roles/est_point_person/est_point_person_role_assignment_services.dart'; +import '../../../../../sevices/roles/rbac_operations/role_assignment_services.dart'; + +part 'est_role_assignment_event.dart'; +part 'est_role_assignment_state.dart'; + +class EstRoleAssignmentBloc + extends Bloc { + EstRoleAssignmentBloc() : super(EstRoleAssignmentInitial()) { + List rolesUnders = []; + List assignedRoles = []; + List assignableRoles = []; + on((event, emit) async { + emit(EstPointPersonRoleLoadingState()); + try { + if (assignedRoles.isEmpty) { + assignedRoles = await EstPointPersonRoleAssignment.instance + .getAssignedRoles(webuserId: event.userId); + } + if (rolesUnders.isEmpty) { + rolesUnders = await EstPointPersonRoleAssignment.instance + .getRolesUnder(roleId: 16); + } + for (var roleUnder in rolesUnders) { + assignableRoles.add(roleUnder.roleUnderChild); + } + emit(EstPointPersonRolesUnderLoadedState( + assignedRoles: assignedRoles, + rolesUnders: rolesUnders, + assignableRole: assignableRoles)); + } catch (e) { + emit(EstPointPersonRolesUnderErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(EstPointPersonRoleLoadingState()); + try { + Map statusResponse = + await RbacRoleAssignmentServices.instance.add( + userId: event.userId, + assignerId: event.assingerId, + roles: event.rolesId); + if (statusResponse['success']) { + assignedRoles = []; + statusResponse['data'].forEach((var roles) { + AssignedRole newAssignRole = AssignedRole.fromJson(roles); + + }); + emit(EstPointPersonRoleUnderAddedState(response: statusResponse)); + } else { + emit(EstPointPersonRoleUnderAddedState(response: statusResponse)); + } + } catch (e) { + emit(EstPointPersonRolesUnderErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(EstPointPersonRoleLoadingState()); + try { + bool success = await RbacRoleAssignmentServices.instance + .deleteAssignedRole(roleId: event.roleId); + if (success) { + assignedRoles.removeWhere((element) => element.id == event.roleId); + emit(EstPointPersonDeletedState(success: success)); + } else { + emit(EstPointPersonDeletedState(success: success)); + } + } catch (e) { + emit(EstPointPersonRolesUnderErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_event.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_event.dart new file mode 100644 index 0000000..a0ea7c3 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_event.dart @@ -0,0 +1,25 @@ +part of 'est_role_assignment_bloc.dart'; + +abstract class EstRoleAssignmentEvent extends Equatable { + const EstRoleAssignmentEvent(); + + @override + List get props => []; +} + +class GetEstPointPersonRolesUnder extends EstRoleAssignmentEvent{ + final int userId; + const GetEstPointPersonRolesUnder({required this.userId}); +} + +class EstPointPersonAssignRole extends EstRoleAssignmentEvent{ + final int userId; + final List rolesId; + final int assingerId; + const EstPointPersonAssignRole({required this.assingerId, required this.rolesId, required this.userId}); +} +class EstPointPersonDeleteAssignRole extends EstRoleAssignmentEvent { + final int roleId; + const EstPointPersonDeleteAssignRole({required this.roleId}); +} + diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_state.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_state.dart new file mode 100644 index 0000000..c047a3a --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_state.dart @@ -0,0 +1,36 @@ +part of 'est_role_assignment_bloc.dart'; + +abstract class EstRoleAssignmentState extends Equatable { + const EstRoleAssignmentState(); + + @override + List get props => []; +} + +class EstPointPersonRolesUnderLoadedState extends EstRoleAssignmentState{ + final List rolesUnders; + final List assignedRoles; + final List assignableRole; + const EstPointPersonRolesUnderLoadedState({required this.assignedRoles, required this.rolesUnders, required this.assignableRole}); +} + +class EstPointPersonRolesUnderErrorState extends EstRoleAssignmentState{ + final String message; + const EstPointPersonRolesUnderErrorState({required this.message}); +} + +class EstPointPersonRoleLoadingState extends EstRoleAssignmentState{ + +} +class EstPointPersonRoleUnderAddedState extends EstRoleAssignmentState{ + final Map response; + const EstPointPersonRoleUnderAddedState({required this.response}); +} + +class EstPointPersonDeletedState extends EstRoleAssignmentState { + final bool success; + const EstPointPersonDeletedState({required this.success}); +} + + +class EstRoleAssignmentInitial extends EstRoleAssignmentState {} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart new file mode 100644 index 0000000..ea55a22 --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart @@ -0,0 +1,58 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:unit2/model/login_data/user_info/assigned_area.dart'; +import 'package:unit2/model/utils/position.dart'; +import '../../../../../model/rbac/rbac_station.dart'; +import '../../../../../model/rbac/station_type.dart'; +import '../../../../../sevices/roles/rbac_operations/station_services.dart'; +part 'est_point_person_station_event.dart'; +part 'est_point_person_station_state.dart'; + +class EstPointPersonStationBloc + extends Bloc { + EstPointPersonStationBloc() : super(EstPointPersonStationInitial()) { + List stations = []; + List assignAreas = []; + List stationTypes = []; + List positions = []; + on((event, emit) async { + emit(EstPersonStationLoadingState()); + try { + if (stations.isEmpty) { + stations = await RbacStationServices.instance + .getStations(agencyId: event.agencyId); + } + if (stationTypes.isEmpty) { + stationTypes = await RbacStationServices.instance.getStationTypes(); + } + if (positions.isEmpty) { + positions = await RbacStationServices.instance.getPositionTitle(); + } + + emit(EstPersonStationLoadedState( + stations: stations, + stationTypes: stationTypes, + positions: positions)); + } catch (e) { + emit(EstPersonStationErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(EstPersonStationLoadingState()); + try { + Map statusResponse = await RbacStationServices + .instance + .addStation(station: event.station); + if (statusResponse['success']) { + RbacStation newStation = RbacStation.fromJson(statusResponse['data']); + stations.add(newStation); + emit(EstPointPersonAddedState(response: statusResponse)); + } else { + emit(EstPointPersonAddedState(response: statusResponse)); + } + } catch (e) { + emit(EstPersonStationErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_event.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_event.dart new file mode 100644 index 0000000..adc933e --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_event.dart @@ -0,0 +1,19 @@ +part of 'est_point_person_station_bloc.dart'; + +abstract class EstPointPersonStationEvent extends Equatable { + const EstPointPersonStationEvent(); + + @override + List get props => []; +} + +class EstPointPersonGetStations extends EstPointPersonStationEvent { + final String agencyId; + const EstPointPersonGetStations( + {required this.agencyId}); +} + +class AddEstPointPersonStation extends EstPointPersonStationEvent { + final RbacStation station; + const AddEstPointPersonStation({required this.station}); +} diff --git a/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_state.dart b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_state.dart new file mode 100644 index 0000000..7b092cd --- /dev/null +++ b/lib/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_state.dart @@ -0,0 +1,33 @@ +part of 'est_point_person_station_bloc.dart'; + +abstract class EstPointPersonStationState extends Equatable { + const EstPointPersonStationState(); + + @override + List get props => []; +} + +class EstPointPersonStationInitial extends EstPointPersonStationState {} + +class EstPersonStationLoadedState extends EstPointPersonStationState { + final List stations; + final List stationTypes; + final List positions; + const EstPersonStationLoadedState({required this.stations, required this.stationTypes, required this.positions}); + @override + List get props => [stations]; +} + +class EstPersonStationLoadingState extends EstPointPersonStationState {} + +class EstPersonStationErrorState extends EstPointPersonStationState { + final String message; + const EstPersonStationErrorState({required this.message}); + @override + List get props => [message]; +} + +class EstPointPersonAddedState extends EstPointPersonStationState{ + final Map response; + const EstPointPersonAddedState({required this.response}); +} \ No newline at end of file diff --git a/lib/bloc/role/pass_check/pass_check_bloc.dart b/lib/bloc/role/pass_check/pass_check_bloc.dart new file mode 100644 index 0000000..c1d157a --- /dev/null +++ b/lib/bloc/role/pass_check/pass_check_bloc.dart @@ -0,0 +1,180 @@ + +import 'package:barcode_scan2/model/scan_result.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:unit2/model/roles/pass_check/passer_info.dart'; +import 'package:unit2/sevices/roles/pass_check_services.dart'; +import '../../../utils/scanner.dart'; +part 'pass_check_event.dart'; +part 'pass_check_state.dart'; + +class PassCheckBloc extends Bloc { + PassCheckBloc() : super(PassCheckInitial()) { + int? roleId; + String? uuid; + bool? otherInputs; + String? io; + dynamic assignedArea; + int? checkerId; + String? token; + int? stationId; + String? cpId; + on((event, emit) async { + try { + emit(PassCheckLoadingState()); + List response = await PassCheckServices.instance + .getPassCheckArea(roleId: event.roleId, userId: event.userId); + roleId = event.roleId; + emit(AssignAreaLoaded(assignedArea: response, roleId: roleId!)); + } catch (e) { + emit(PassCheckErrorState(message: e.toString())); + } + }); + on((event, emit) { + otherInputs = event.includeOtherInputs; + checkerId = event.checkerId; + io = event.entranceExit; + token = event.token; + roleId = event.roleId; + assignedArea = event.assignedArea; + emit(SettingSaved( + assignedArea: assignedArea, + checker: checkerId!, + io: io!, + otherInputs: otherInputs!, + roleId: roleId!, + token: token!)); + }); + on((event, emit) { + emit(SettingSaved( + assignedArea: assignedArea, + checker: checkerId!, + io: io!, + otherInputs: otherInputs!, + roleId: roleId!, + token: token!)); + }); + on((event, emit) { + add(PerformPostLogs( + checkerId: checkerId!, + cpId: cpId, + destination: null, + io: io!.toLowerCase() == "incoming" ? "i" : "o", + otherInputs: otherInputs!, + passerId: uuid!, + roleId: roleId!, + stationId: stationId, + temp: event.temp)); + }); + + on((event, emit) { + add(PerformPostLogs( + checkerId: checkerId!, + cpId: cpId, + destination: event.destination, + io: io!.toLowerCase() == "incoming" ? "i" : "o", + otherInputs: otherInputs!, + passerId: uuid!, + roleId: roleId!, + stationId: stationId, + temp: null)); + }); + on((event, emit) async { + ScanResult result = await QRCodeBarCodeScanner.instance.scanner(); + if (result.rawContent.toString().isNotEmpty) { + uuid = result.rawContent.toString(); + emit(PassCheckLoadingState()); + try { + PasserInfo? passerInfo = await PassCheckServices.instance + .getPasserInfo(uuid: uuid!, token: event.token); + if (roleId == 41 || roleId == 13 || roleId == 17 || roleId == 22) { + stationId = assignedArea.id; + } else if (roleId == 7) { + cpId = assignedArea.brgycode; + } else if (roleId == 10) { + cpId = assignedArea.purokdesc; + } else if (roleId == 16) { + cpId = assignedArea.id; + } + if (passerInfo == null) { + Fluttertoast.showToast( + msg: "QR CODE IS INVALID", + fontSize: 24, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.black, + textColor: Colors.white); + emit(QRInvalid(token: token!)); + } else { + if (otherInputs!) { + if (io?.toLowerCase() == 'incoming') { + emit(IncomingScanState()); + } else { + emit(OutGoingScanState()); + } + } else { + add(PerformPostLogs( + checkerId: checkerId!, + cpId: cpId, + destination: null, + io: io!.toLowerCase() == "incoming" ? "i" : "o", + otherInputs: otherInputs!, + passerId: uuid!, + roleId: roleId!, + stationId: stationId, + temp: null)); + } + } + } catch (e) { + emit(PassCheckErrorState(message: e.toString())); + } + } else { + emit(SettingSaved( + assignedArea: assignedArea, + checker: checkerId!, + io: io!, + otherInputs: otherInputs!, + roleId: roleId!, + token: token!)); + } + }); + on((event, emit) async { + emit(PassCheckLoadingState()); + try { + final bool success = await PassCheckServices.instance.performPostLogs( + passerId: event.passerId, + chekerId: event.checkerId, + temp: event.temp, + destination: event.destination, + io: event.io, + stationId: event.stationId, + cpId: event.cpId, + otherInputs: event.otherInputs, + roleid: event.roleId); + if (success) { + Fluttertoast.showToast( + msg: "SUCCESSFULLY SAVED", + fontSize: 24, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.black, + textColor: Colors.white); + emit(ScanSuccess(token: token!)); + } else { + Fluttertoast.showToast( + msg: "SCAN FAILED", + fontSize: 24, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.black, + textColor: Colors.white); + emit(ScanFailed(token: token!)); + } + } catch (e) { + emit(PassCheckErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role/pass_check/pass_check_event.dart b/lib/bloc/role/pass_check/pass_check_event.dart new file mode 100644 index 0000000..0cfe95b --- /dev/null +++ b/lib/bloc/role/pass_check/pass_check_event.dart @@ -0,0 +1,70 @@ +part of 'pass_check_bloc.dart'; + +abstract class PassCheckEvent extends Equatable { + const PassCheckEvent(); + + @override + List get props => []; +} + +class GetPassCheckAreas extends PassCheckEvent { + final int roleId; + final int userId; + const GetPassCheckAreas({required this.roleId, required this.userId}); +} + +class SetScannerSettings extends PassCheckEvent { + final int roleId; + final String token; + final dynamic assignedArea; + final bool includeOtherInputs; + final String entranceExit; + final int checkerId; + const SetScannerSettings( + {required this.assignedArea, + required this.checkerId, + required this.entranceExit, + required this.includeOtherInputs, + required this.roleId, + required this.token}); +} + +class ScanQr extends PassCheckEvent { + final String token; + + const ScanQr({required this.token}); +} + +class PerformPostLogs extends PassCheckEvent { + final String passerId; + final int checkerId; + final String io; + final bool otherInputs; + final String? cpId; + final int? stationId; + final String? destination; + final double? temp; + final int roleId; + const PerformPostLogs( + {required this.checkerId, + required this.cpId, + required this.destination, + required this.io, + required this.otherInputs, + required this.passerId, + required this.roleId, + required this.stationId, + required this.temp}); +} + +class PerformIncomingPostLog extends PassCheckEvent{ + final double temp; + const PerformIncomingPostLog({required this.temp}); +} +class PerformOutgoingPostLog extends PassCheckEvent{ + final String destination; + const PerformOutgoingPostLog({required this.destination}); +} +class ScanError extends PassCheckEvent{ + +} \ No newline at end of file diff --git a/lib/bloc/role/pass_check/pass_check_state.dart b/lib/bloc/role/pass_check/pass_check_state.dart new file mode 100644 index 0000000..fe93067 --- /dev/null +++ b/lib/bloc/role/pass_check/pass_check_state.dart @@ -0,0 +1,67 @@ +part of 'pass_check_bloc.dart'; + +abstract class PassCheckState extends Equatable { + const PassCheckState(); + + @override + List get props => []; +} + +class PassCheckInitial extends PassCheckState {} + +class PassCheckErrorState extends PassCheckState { + final String message; + const PassCheckErrorState({required this.message}); +} + +class QRInvalid extends PassCheckState{ + final String token; + const QRInvalid({required this.token}); +} + +class PassCheckLoadingState extends PassCheckState {} + +class AssignAreaLoaded extends PassCheckState { + final List assignedArea; + final int roleId; + const AssignAreaLoaded({required this.assignedArea, required this.roleId}); +} + +class SettingSaved extends PassCheckState { + final dynamic assignedArea; + final String token; + final String io; + final int checker; + final bool otherInputs; + final int roleId; + const SettingSaved( + {required this.assignedArea, + required this.checker, + required this.io, + required this.otherInputs, + required this.roleId, + required this.token}); +} + +class IncomingScanState extends PassCheckState { + +} + +class OutGoingScanState extends PassCheckState { + +} + +class ScanSuccess extends PassCheckState{ + final String token; +const ScanSuccess({required this.token}); +} + +class ScanFailed extends PassCheckState{ + final String token; +const ScanFailed({required this.token}); +} + +class QRCodeInvalid extends PassCheckState{ + final String token; + const QRCodeInvalid({required this.token}); +} diff --git a/lib/bloc/role_assignment/role_assignment_bloc.dart b/lib/bloc/role_assignment/role_assignment_bloc.dart new file mode 100644 index 0000000..8f06a0d --- /dev/null +++ b/lib/bloc/role_assignment/role_assignment_bloc.dart @@ -0,0 +1,93 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import '../../model/profile/basic_information/primary-information.dart'; +import '../../model/rbac/assigned_role.dart'; +import '../../model/rbac/rbac.dart'; +import '../../sevices/roles/rbac_operations/role_assignment_services.dart'; +import '../../sevices/roles/rbac_operations/role_services.dart'; + +part 'role_assignment_event.dart'; +part 'role_assignment_state.dart'; + +class RoleAssignmentBloc + extends Bloc { + RoleAssignmentBloc() : super(RoleAssignmentInitial()) { + List assignedRoles = []; + int userId; + String? fname; + String? lname; + String? fullname; + Profile? profile; + List roles = []; + on((event, emit) async { + emit(RoleAssignmentLoadingState()); + fname = event.firstname; + lname = event.lastname; + fullname = "${event.firstname} ${event.lastname}"; + try { + profile = await RbacRoleAssignmentServices.instance.searchUser( + page: 1, name: event.firstname, lastname: event.lastname); + if (profile != null && profile?.id != null) { + assignedRoles = await RbacRoleAssignmentServices.instance + .getAssignedRoles( + firstname: event.firstname, lastname: event.lastname); + + if (roles.isEmpty) { + roles = await RbacRoleServices.instance.getRbacRoles(); + } + emit(AssignedRoleLoaded( + assignedRoles: assignedRoles, fullname: fullname!, roles: roles)); + } else { + emit(UserNotExistError()); + } + + + } catch (e) { + emit(RoleAssignmentErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(AssignedRoleLoaded( + assignedRoles: assignedRoles, fullname: fullname!, roles: roles)); + }); + on((event, emit) async { + emit(RoleAssignmentLoadingState()); + try { + bool success = await RbacRoleAssignmentServices.instance + .deleteAssignedRole(roleId: event.roleId); + if (success) { + assignedRoles.removeWhere((element) => element.id == event.roleId); + emit(AssignedRoleDeletedState(success: success)); + } else { + emit(AssignedRoleDeletedState(success: success)); + } + } catch (e) { + emit(RoleAssignmentErrorState(message: e.toString())); + } + }); + on((event, emit) async { + emit(RoleAssignmentLoadingState()); + try { + Map statusResponse = + await RbacRoleAssignmentServices.instance.add( + userId: profile!.webuserId!, + assignerId: event.assignerId, + roles: event.roles); + if (statusResponse['success']) { + assignedRoles = []; + statusResponse['data'].forEach((var roles) { + AssignedRole newAssignRole = AssignedRole.fromJson(roles); + if (!event.roles.contains(newAssignRole.id)) { + assignedRoles.add(newAssignRole); + } + }); + emit(AssignedRoleAddedState(response: statusResponse)); + } else { + emit(AssignedRoleAddedState(response: statusResponse)); + } + } catch (e) { + emit(RoleAssignmentErrorState(message: e.toString())); + } + }); + } +} diff --git a/lib/bloc/role_assignment/role_assignment_event.dart b/lib/bloc/role_assignment/role_assignment_event.dart new file mode 100644 index 0000000..016ce40 --- /dev/null +++ b/lib/bloc/role_assignment/role_assignment_event.dart @@ -0,0 +1,28 @@ +part of 'role_assignment_bloc.dart'; + +abstract class RoleAssignmentEvent extends Equatable { + const RoleAssignmentEvent(); + + @override + List get props => []; +} + +class GetAssignedRoles extends RoleAssignmentEvent { + final String firstname; + final String lastname; + const GetAssignedRoles({required this.firstname, required this.lastname}); +} + +class DeleteAssignRole extends RoleAssignmentEvent { + final int roleId; + const DeleteAssignRole({required this.roleId}); +} + +class LoadAssignedRole extends RoleAssignmentEvent {} + +class AssignRole extends RoleAssignmentEvent { + final List roles; + final int assignerId; + const AssignRole( + {required this.assignerId, required this.roles}); +} diff --git a/lib/bloc/role_assignment/role_assignment_state.dart b/lib/bloc/role_assignment/role_assignment_state.dart new file mode 100644 index 0000000..98dc25a --- /dev/null +++ b/lib/bloc/role_assignment/role_assignment_state.dart @@ -0,0 +1,37 @@ +part of 'role_assignment_bloc.dart'; + +abstract class RoleAssignmentState extends Equatable { + const RoleAssignmentState(); + + @override + List get props => []; +} + +class RoleAssignmentInitial extends RoleAssignmentState {} + +class AssignedRoleLoaded extends RoleAssignmentState { + final String fullname; + final List assignedRoles; + final List roles; + const AssignedRoleLoaded( + {required this.assignedRoles, required this.fullname, required this.roles}); +} + +class RoleAssignmentLoadingState extends RoleAssignmentState {} + +class RoleAssignmentErrorState extends RoleAssignmentState { + final String message; + const RoleAssignmentErrorState({required this.message}); +} +class UserNotExistError extends RoleAssignmentState{ + +} +class AssignedRoleDeletedState extends RoleAssignmentState { + final bool success; + const AssignedRoleDeletedState({required this.success}); +} + +class AssignedRoleAddedState extends RoleAssignmentState { + final Map response; + const AssignedRoleAddedState({required this.response}); +} diff --git a/lib/bloc/sos/sos_bloc.dart b/lib/bloc/sos/sos_bloc.dart new file mode 100644 index 0000000..beb2c0f --- /dev/null +++ b/lib/bloc/sos/sos_bloc.dart @@ -0,0 +1,106 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:location/location.dart'; +import 'package:unit2/model/sos/session.dart'; +import 'package:unit2/sevices/sos/sos_service.dart'; + +import '../../utils/global.dart'; + +part 'sos_event.dart'; +part 'sos_state.dart'; + +class SosBloc extends Bloc { + SosBloc() : super(SosInitial()) { + LocationData? locationData; + String? mobile1; + String? mobile2; + String? sessionToken; + ////get user location + on((event, emit) async { + emit(const LoadingState(message: "Getting Location")); + mobile1 = await SOS!.get('mobile1'); + mobile2 = await SOS!.get('mobile2'); + sessionToken = await SOS!.get('session_token'); + if (mobile1 != null) { + if (sessionToken != null) { + add(CheckAcknowledgement(sessionToken: sessionToken!)); + } else { + try { + LocationData? newLocationData = + await SosService.instance.getUserLocation(); + locationData = newLocationData; + + emit(RequestSosState( + locationData: locationData!, + mobile1: mobile1!, + mobile2: mobile2)); + } catch (e) { + emit(ErrorState(message: e.toString())); + } + } + } else { + try { + LocationData? newLocationData = + await SosService.instance.getUserLocation(); + locationData = newLocationData; + + emit(UserLocationLoaded(locationData: locationData!)); + } catch (e) { + emit(ErrorState(message: e.toString())); + } + } + }); + ////submit mobile + on((event, emit) async { + emit(const LoadingState(message: "")); + mobile1 = event.mobile1; + mobile2 = event.mobile2; + await SOS!.put('mobile1', event.mobile1); + await SOS!.put('mobile2', event.mobile2); + emit(RequestSosState( + locationData: locationData!, + mobile1: event.mobile1, + mobile2: event.mobile2)); + }); + + //// send SOS + on((event, emit) async { + SessionData sessionData; + emit(const LoadingState(message: "Sending emergency response request")); + try { + sessionData = await SosService.instance.requestSos( + location: locationData!, + mobile1: mobile1!, + mobile2: mobile2, + msg: event.msg, + requestedDate: event.requestDate); + await SOS!.put('session_token', sessionData.sessionToken); + emit(SOSReceivedState(sessionToken: sessionData.sessionToken!)); + } catch (e) { + emit(ErrorState(message: e.toString())); + } + }); + //// check acknowledgement + on((event, emit) async { + SessionData sessionData; + try { + SessionData? newSessionData = + await SosService.instance.checkAcknowledgement(event.sessionToken); + if (newSessionData.acknowledgeDate == null) { + debugPrint(newSessionData.sessionToken); + emit(SOSReceivedState(sessionToken: newSessionData.sessionToken!)); + } else { + sessionData = newSessionData; + emit(SoSAcknowledgementConfirm(sessionData: sessionData)); + } + } catch (e) { + emit(ErrorState(message: e.toString())); + } + }); + on((event, emit) async { + await SOS!.delete('session_token'); + add(LoadUserLocation()); + }); + } +} diff --git a/lib/bloc/sos/sos_event.dart b/lib/bloc/sos/sos_event.dart new file mode 100644 index 0000000..db341cd --- /dev/null +++ b/lib/bloc/sos/sos_event.dart @@ -0,0 +1,43 @@ +part of 'sos_bloc.dart'; + +abstract class SosEvent extends Equatable { + const SosEvent(); + + @override + List get props => []; +} + +class LoadUserLocation extends SosEvent { + @override + List get props => []; +} + +class SubmitMobile extends SosEvent { + final String mobile1; + final String? mobile2; + const + SubmitMobile({required this.mobile1,required this.mobile2}); + @override + List get props => []; + +} + +class SendSOS extends SosEvent { + final String msg; + final String requestDate; + const SendSOS({required this.msg, required this.requestDate}); + @override + List get props => [msg, requestDate]; +} + +class CheckAcknowledgement extends SosEvent { + final String sessionToken; + const CheckAcknowledgement({required this.sessionToken}); + @override + List get props => [sessionToken]; +} + +class OnDoneRequest extends SosEvent { + @override + List get props => []; +} \ No newline at end of file diff --git a/lib/bloc/sos/sos_state.dart b/lib/bloc/sos/sos_state.dart new file mode 100644 index 0000000..44ca7a8 --- /dev/null +++ b/lib/bloc/sos/sos_state.dart @@ -0,0 +1,50 @@ +part of 'sos_bloc.dart'; + +abstract class SosState extends Equatable { + const SosState(); + + @override + List get props => []; +} + +class SosInitial extends SosState {} + +class UserLocationLoaded extends SosState { + final LocationData locationData; + const UserLocationLoaded({required this.locationData}); + @override + List get props => [locationData]; +} +class ErrorState extends SosState{ + final String message; + const ErrorState({required this.message}); + @override + List get props => [message]; +} +class RequestSosState extends SosState{ + final LocationData locationData; + final String mobile1; + final String? mobile2; + + const RequestSosState({required this.locationData, required this.mobile1, required this.mobile2}); + @override + List get props => [locationData,mobile1]; +} + +class LoadingState extends SosState{ + final String message; + const LoadingState({required this.message}); +} +class SOSReceivedState extends SosState { + final String sessionToken; + const SOSReceivedState({required this.sessionToken}); + @override + List get props => [sessionToken]; +} + +class SoSAcknowledgementConfirm extends SosState{ + final SessionData sessionData; + const SoSAcknowledgementConfirm({required this.sessionData}); + @override + List get props => [sessionData]; +} diff --git a/lib/bloc/user/user_bloc.dart b/lib/bloc/user/user_bloc.dart new file mode 100644 index 0000000..16ff38f --- /dev/null +++ b/lib/bloc/user/user_bloc.dart @@ -0,0 +1,161 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:barcode_scan2/barcode_scan2.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:unit2/model/login_data/user_info/assigned_area.dart'; +import 'package:unit2/model/login_data/user_info/role.dart'; +import 'package:unit2/model/login_data/user_info/user_data.dart'; +import 'package:unit2/model/login_data/version_info.dart'; +import 'package:unit2/screens/unit2/login/functions/get_app_version.dart'; +import 'package:unit2/sevices/login_service/auth_service.dart'; +import 'package:unit2/utils/global.dart'; +import '../../utils/scanner.dart'; +import '../../utils/text_container.dart'; +part 'user_event.dart'; +part 'user_state.dart'; + +class UserBloc extends Bloc { + UserData? _userData; + VersionInfo? _versionInfo; + String? _apkVersion; + bool save = false; + String? uuid; + List establishmentPointPersonAssignedAreas = []; + UserBloc() : super(UserInitial()) { + //// this event is called when opening the app to check if + //// there is new app version + on((event, emit) async { + try { + emit(SplashScreen()); + save = false; + if (_versionInfo == null) { + VersionInfo versionInfo = await AuthService.instance.getVersionInfo(); + _versionInfo = versionInfo; + } + String apkVersion = await getAppVersion(); + _apkVersion = apkVersion; + final String? saved = CREDENTIALS?.get('saved'); + final String? username = CREDENTIALS?.get('username'); + final String? password = CREDENTIALS?.get('password'); + if (saved != null) { + save = true; + add(UserLogin(username: username, password: password)); + } else { + emit(VersionLoaded( + versionInfo: _versionInfo, + apkVersion: _apkVersion, + username: null, + password: null)); + } + } catch (e) { + emit(UserError( + message: e.toString(), + )); + } + }); +////Loading the current version of the app + on((event, emit) { + emit(VersionLoaded( + versionInfo: _versionInfo, + apkVersion: _apkVersion, + username: event.username, + password: event.password)); + }); +////userlogin + on((event, emit) async { + try { + Map response = await AuthService.instance + .webLogin(username: event.username, password: event.password); + if (response['status'] == true) { + UserData userData = UserData.fromJson(response['data']); + Role? estPointPerson; + if (userData.user?.login?.user?.roles != null && + userData.user!.login!.user!.roles!.isNotEmpty) { + userData.user!.login!.user!.roles!.forEach((element) { + if (element!.name!.toLowerCase() == 'establishment point-person') { + estPointPerson = element; + } + }); + if (estPointPerson != null && + estPointPerson!.assignedArea!.isNotEmpty) { + estPointPerson!.assignedArea!.forEach((element) { + establishmentPointPersonAssignedAreas.add(element!); + }); + } + } + + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: userData, + success: true, + message: response['message'], + savedCredentials: save)); + } else { + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: null, + success: false, + message: response['message'], + savedCredentials: save)); + } + } + on TimeoutException catch (_) { + emit(InternetTimeout(message: timeoutError)); + } on SocketException catch (_) { + emit(InternetTimeout(message: timeoutError)); + } on Error catch (e) { + emit(LoginErrorState(message: e.toString())); + } + }); + on((event, emit) async { + try { + Map response = await AuthService.instance + .qrLogin(uuid: event.uuid, password: event.password); + if (response['status'] == true) { + UserData userData = UserData.fromJson(response['data']); + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: userData, + success: true, + message: response['message'], + savedCredentials: save)); + } else { + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: null, + success: false, + message: response['message'], + savedCredentials: save)); + } + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: _userData, + savedCredentials: save)); + } on TimeoutException catch (_) { + emit(InternetTimeout(message: timeoutError)); + } on SocketException catch (_) { + emit(InternetTimeout(message: timeoutError)); + } on Error catch (e) { + emit(LoginErrorState(message: e.toString())); + } + }); + on((event, emit) { + emit(UserLoggedIn( + estPersonAssignedArea: establishmentPointPersonAssignedAreas, + userData: _userData, + savedCredentials: save)); + }); + on((event, emit) async { + ScanResult result = await QRCodeBarCodeScanner.instance.scanner(); + if (result.rawContent.toString().isNotEmpty) { + uuid = result.rawContent.toString(); + emit(UuidLoaded(uuid: uuid!)); + } + }); + on((event, emit) { + emit(UuidLoaded(uuid: uuid!)); + }); + } +} diff --git a/lib/bloc/user/user_event.dart b/lib/bloc/user/user_event.dart new file mode 100644 index 0000000..002410e --- /dev/null +++ b/lib/bloc/user/user_event.dart @@ -0,0 +1,46 @@ +part of 'user_bloc.dart'; + +abstract class UserEvent extends Equatable { + @override + List get props => []; +} + +class GetApkVersion extends UserEvent { + GetApkVersion(); + @override + List get props => []; +} + +class UserLogin extends UserEvent { + final String? username; + final String? password; + UserLogin({this.username, this.password}); + @override + List get props => [username!, password!]; +} + +class LoadLoggedInUser extends UserEvent { + LoadLoggedInUser(); +} + +class GetUuid extends UserEvent { + GetUuid(); +} +class LoadUuid extends UserEvent{ + LoadUuid(); +} + + +class LoadVersion extends UserEvent { + final String? username; + final String? password; + LoadVersion({this.password,this.username}); +} + +class UuidLogin extends UserEvent { + final String? uuid; + final String? password; + UuidLogin({this.uuid, this.password}); + @override + List get props => [uuid!, password!]; +} diff --git a/lib/bloc/user/user_state.dart b/lib/bloc/user/user_state.dart new file mode 100644 index 0000000..c63fbf7 --- /dev/null +++ b/lib/bloc/user/user_state.dart @@ -0,0 +1,73 @@ +part of 'user_bloc.dart'; + +abstract class UserState extends Equatable { + + @override + List get props => []; +} + +class UserInitial extends UserState { + UserInitial(); + @override + List get props => []; +} + +class UserLoading extends UserState { + final String? message; + UserLoading({this.message}); + @override + List get props => [message!]; +} + +class SplashScreen extends UserState { + + @override + List get props => []; +} + +class UserError extends UserState { + final String? message; + UserError({this.message}); + @override + List get props => []; +} +class UserLoggedIn extends UserState{ + final List? estPersonAssignedArea; + final UserData? userData; + final String? message; + final bool? success; + final bool? savedCredentials; + UserLoggedIn({this.userData,this.message,this.success,this.savedCredentials, required this.estPersonAssignedArea}); +} + +class VersionLoaded extends UserState { + final VersionInfo? versionInfo; + final String? apkVersion; + final String? username; + final String? password; + VersionLoaded({this.versionInfo,this.apkVersion, this.password,this.username}); + @override + List get props => [versionInfo!]; +} +class UuidLoaded extends UserState{ + final String uuid; + UuidLoaded({required this.uuid}); + @override + List get props => [uuid]; +} + +class InternetTimeout extends UserState{ + final String message; + InternetTimeout({required this.message}); + @override + List get props => [message]; +} + +class InvalidCredentials extends UserState{ + final String message ; + InvalidCredentials ({required this.message}); +} +class LoginErrorState extends UserState{ + final String message; + LoginErrorState({required this.message}); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..d88fa6c --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/utils/app_router.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:path_provider/path_provider.dart' as path_provider; +import './utils/global.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + var appDirectory = await path_provider.getApplicationDocumentsDirectory(); + await Hive.initFlutter(appDirectory.path); + CREDENTIALS = await Hive.openBox('credentials'); + SOS = await Hive.openBox('soscontacts'); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) + .then((_) { + runApp(MyApp()); + }); +} + +// void main() => runApp( +// DevicePreview( +// enabled: !kReleaseMode, +// builder: (context) => const MyApp(), // Wrap your app +// ), +// ); + +class MyApp extends StatelessWidget { + AppRouter? _appRouter; + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + _appRouter = AppRouter(); + final mediaQueryData = + MediaQueryData.fromWindow(WidgetsBinding.instance.window); + screenWidth = mediaQueryData.size.width; + screenHeight = mediaQueryData.size.height; + blockSizeHorizontal = screenWidth / 100; + blockSizeVertical = screenHeight / 100; + safeAreaHorizontal = + mediaQueryData.padding.left + mediaQueryData.padding.right; + safeAreaVertical = + mediaQueryData.padding.top + mediaQueryData.padding.bottom; + safeBlockHorizontal = (screenWidth - safeAreaHorizontal) / 100; + safeBlockVertical = (screenHeight - safeAreaVertical) / 100; + + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (_) => UserBloc(), + ), + BlocProvider( + create: (_) => ProfileBloc(), + ), + ], + child: MaterialApp( + navigatorKey: NavigationService.navigatorKey, + // useInheritedMediaQuery: true, + // locale: DevicePreview.locale(context), + // builder: DevicePreview.appBuilder, + // routeInformationParser: goRouter.routeInformationParser, + // routerDelegate: goRouter.routerDelegate, + // routeInformationProvider: goRouter.routeInformationProvider, + + title: 'uniT2 - Universal Tracker and Tracer', + theme: ThemeData( + primarySwatch: Colors.red, + appBarTheme: const AppBarTheme( + systemOverlayStyle: SystemUiOverlayStyle( + statusBarBrightness: Brightness.dark, + statusBarColor: Colors.black), + ), + fontFamily: 'LexendDeca', + ), + debugShowCheckedModeBanner: false, + onGenerateRoute: _appRouter!.onGenerateRoute, + ), + ); + } +} diff --git a/lib/model/docsms/document.dart b/lib/model/docsms/document.dart new file mode 100644 index 0000000..354ca18 --- /dev/null +++ b/lib/model/docsms/document.dart @@ -0,0 +1,207 @@ +// To parse this JSON data, do +// +// final document = documentFromJson(jsonString); + +class Document { + Document({ + required this.id, + required this.sk, + required this.dsk, + required this.slug, + required this.files, + required this.title, + required this.agency, + required this.office, + required this.subject, + required this.fileType, + required this.isPublic, + required this.createdAt, + required this.createdBy, + required this.validatedAt, + required this.validatedBy, + required this.documentType, + required this.documentRoutes, + required this.alternateMobile, + required this.attachedDocument, + required this.enableNotification, + required this.createdByPersonId, + }); + + final int? id; + final String? sk; + final String? dsk; + final String? slug; + final List? files; + final String? title; + final String? agency; + final String? office; + final String? subject; + final FileType? fileType; + final bool? isPublic; + final String? createdAt; + final String? createdBy; + final String? validatedAt; + final String? validatedBy; + final DocumentType? documentType; + final dynamic documentRoutes; + final AlternateMobile? alternateMobile; + final dynamic attachedDocument; + final bool? enableNotification; + final int? createdByPersonId; + + factory Document.fromJson(Map json) => Document( + id: json["id"], + sk: json["sk"], + dsk: json["dsk"], + slug: json["slug"], + files: List.from(json["files"].map((x) => FileElement.fromJson(x))), + title: json["title"], + agency: json["agency"], + office: json["office"], + subject: json["subject"], + fileType: FileType.fromJson(json["file_type"]), + isPublic: json["is_public"], + createdAt: json["created_at"], + createdBy: json["created_by"], + validatedAt: json["validated_at"], + validatedBy: json["validated_by"], + documentType: DocumentType.fromJson(json["document_type"]), + documentRoutes: json["document_routes"], + alternateMobile: AlternateMobile.fromJson(json["alternate_mobile"]), + attachedDocument: json["attached_document"], + enableNotification: json["enable_notification"], + createdByPersonId: json["created_by_person_id"], + ); + + Map toJson() => { + "id": id, + "sk": sk, + "dsk": dsk, + "slug": slug, + "files": List.from(files!.map((x) => x.toJson())), + "title": title, + "agency": agency, + "office": office, + "subject": subject, + "file_type": fileType?.toJson(), + "is_public": isPublic, + "created_at": createdAt, + "created_by": createdBy, + "validated_at": validatedAt, + "validated_by": validatedBy, + "document_type": documentType?.toJson(), + "document_routes": documentRoutes, + "alternate_mobile": alternateMobile?.toJson(), + "attached_document": attachedDocument, + "enable_notification": enableNotification, + "created_by_person_id": createdByPersonId, + }; +} + +class AlternateMobile { + AlternateMobile({ + required this.id, + required this.mobileNo, + required this.documentId, + }); + + final dynamic id; + final dynamic mobileNo; + final dynamic documentId; + + factory AlternateMobile.fromJson(Map json) => AlternateMobile( + id: json["id"], + mobileNo: json["mobile_no"], + documentId: json["document_id"], + ); + + Map toJson() => { + "id": id, + "mobile_no": mobileNo, + "document_id": documentId, + }; +} + +class DocumentType { + DocumentType({ + required this.id, + required this.name, + required this.slug, + required this.categoryId, + required this.priorityNumber, + }); + + final int id; + final String name; + final dynamic slug; + final int categoryId; + final dynamic priorityNumber; + + factory DocumentType.fromJson(Map json) => DocumentType( + id: json["id"], + name: json["name"], + slug: json["slug"], + categoryId: json["category_id"], + priorityNumber: json["priority_number"], + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "category_id": categoryId, + "priority_number": priorityNumber, + }; +} + +class FileType { + FileType({ + required this.id, + required this.name, + required this.isActive, + required this.extensions, + }); + + final int id; + final String name; + final bool isActive; + final List extensions; + + factory FileType.fromJson(Map json) => FileType( + id: json["id"], + name: json["name"], + isActive: json["is_active"], + extensions: List.from(json["extensions"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "name": name, + "is_active": isActive, + "extensions": List.from(extensions.map((x) => x)), + }; +} + +class FileElement { + FileElement({ + required this.path, + required this.extnsn, + required this.dateTime, + }); + + final String path; + final String extnsn; + final String dateTime; + + factory FileElement.fromJson(Map json) => FileElement( + path: json["path"], + extnsn: json["extnsn"], + dateTime: json["date_time"], + ); + + Map toJson() => { + "path": path, + "extnsn": extnsn, + "date_time": dateTime, + }; +} diff --git a/lib/model/location/address_category.dart b/lib/model/location/address_category.dart new file mode 100644 index 0000000..0916912 --- /dev/null +++ b/lib/model/location/address_category.dart @@ -0,0 +1,23 @@ +class AddressCategory { + AddressCategory({ + required this.id, + required this.name, + required this.type, + }); + + final int? id; + final String? name; + final String? type; + + factory AddressCategory.fromJson(Map json) => AddressCategory( + id: json["id"], + name: json["name"], + type: json["type"], + ); + + Map toJson() => { + "id": id, + "name": name, + "type": type, + }; +} \ No newline at end of file diff --git a/lib/model/location/barangay.dart b/lib/model/location/barangay.dart new file mode 100644 index 0000000..f36032c --- /dev/null +++ b/lib/model/location/barangay.dart @@ -0,0 +1,41 @@ +// To parse this JSON data, do +// +// final barangay = barangayFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'city.dart'; +import 'provinces.dart'; + +Barangay barangayFromJson(String str) => Barangay.fromJson(json.decode(str)); + +String barangayToJson(Barangay data) => json.encode(data.toJson()); + +class Barangay { + Barangay({ + required this.code, + required this.description, + required this.cityMunicipality, + }); + + final String? code; + final String? description; + final CityMunicipality? cityMunicipality; + + factory Barangay.fromJson(Map json) => Barangay( + code: json["code"], + description: json["description"], + cityMunicipality: json['city_municipality'] == null? null: CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "code": code, + "description": description, + "city_municipality": cityMunicipality!.toJson(), + }; +} + + + + diff --git a/lib/model/location/city.dart b/lib/model/location/city.dart new file mode 100644 index 0000000..1fc77cd --- /dev/null +++ b/lib/model/location/city.dart @@ -0,0 +1,51 @@ +// To parse this JSON data, do +// +// final city = cityFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'provinces.dart'; +import 'region.dart'; + +CityMunicipality cityFromJson(String str) => CityMunicipality.fromJson(json.decode(str)); + +String cityToJson(CityMunicipality data) => json.encode(data.toJson()); + +class CityMunicipality { + CityMunicipality({ + required this.code, + required this.description, + required this.province, + required this.psgcCode, + required this.zipcode, + }); + + final String? code; + final String? description; + final Province? province; + final String? psgcCode; + final String? zipcode; + + factory CityMunicipality.fromJson(Map json) => CityMunicipality( + code: json["code"], + description: json["description"], + province: json['province'] == null? null : Province.fromJson(json["province"]), + psgcCode: json["psgc_code"], + zipcode: json["zipcode"], + ); + + Map toJson() => { + "code": code, + "description": description, + "province": province?.toJson(), + "psgc_code": psgcCode, + "zipcode": zipcode, + }; + @override + String toString(){ + return 'CityMunicipality{code:$code, description:$description, provice:${province.toString()} }'; + } +} + + diff --git a/lib/model/location/country.dart b/lib/model/location/country.dart new file mode 100644 index 0000000..fe54ce8 --- /dev/null +++ b/lib/model/location/country.dart @@ -0,0 +1,40 @@ +// To parse this JSON data, do +// +// final country = countryFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +Country countryFromJson(String str) => Country.fromJson(json.decode(str)); + +String countryToJson(Country data) => json.encode(data.toJson()); + +class Country { + Country({ + required this.id, + required this.name, + required this.code, + }); + + final int? id; + final String? name; + final String? code; + + factory Country.fromJson(Map json) => Country( + id: json["id"], + name: json["name"], + code: json["code"].toString(), + ); + + Map toJson() => { + "id": id, + "name": name, + "code": code, + }; + + @override + String toString() { + return '$id $name $code '; + + } +} diff --git a/lib/model/location/provinces.dart b/lib/model/location/provinces.dart new file mode 100644 index 0000000..597587d --- /dev/null +++ b/lib/model/location/provinces.dart @@ -0,0 +1,49 @@ +// To parse this JSON data, do +// +// final province = provinceFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'region.dart'; + +Province provinceFromJson(String str) => Province.fromJson(json.decode(str)); + +String provinceToJson(Province data) => json.encode(data.toJson()); + +class Province { + Province({ + required this.code, + required this.description, + required this.region, + required this.psgcCode, + required this.shortname, + }); + + final String? code; + final String? description; + final Region? region; + final String? psgcCode; + final String? shortname; + + factory Province.fromJson(Map json) => Province( + code: json["code"], + description: json["description"], + region: json['region'] == null? null: Region.fromJson(json["region"]), + psgcCode: json["psgc_code"], + shortname: json["shortname"], + ); + + Map toJson() => { + "code": code, + "description": description, + "region": region!.toJson(), + "psgc_code": psgcCode, + "shortname": shortname, + }; + + @override + String toString(){ + return 'Province(name:$description ${region.toString()})'; + } +} diff --git a/lib/model/location/purok.dart b/lib/model/location/purok.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/model/location/region.dart b/lib/model/location/region.dart new file mode 100644 index 0000000..17bd41d --- /dev/null +++ b/lib/model/location/region.dart @@ -0,0 +1,39 @@ +// To parse this JSON data, do +// +// final region = regionFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +Region regionFromJson(String str) => Region.fromJson(json.decode(str)); + +String regionToJson(Region data) => json.encode(data.toJson()); + +class Region { + Region({ + required this.code, + required this.description, + required this.psgcCode, + }); + + final int? code; + final String? description; + final String? psgcCode; + + factory Region.fromJson(Map json) => Region( + code: json["code"], + description: json["description"], + psgcCode: json["psgc_code"], + ); + + Map toJson() => { + "code": code, + "description": description, + "psgc_code": psgcCode, + }; + + @override + String toString(){ + return 'Region(name:$description)'; + } +} diff --git a/lib/model/location/subdivision.dart b/lib/model/location/subdivision.dart new file mode 100644 index 0000000..950d80e --- /dev/null +++ b/lib/model/location/subdivision.dart @@ -0,0 +1,23 @@ +class Subdivision { + Subdivision({ + this.id, + this.lotNo, + this.blockNo, + }); + + final int? id; + final int? lotNo; + final int? blockNo; + + factory Subdivision.fromJson(Map json) => Subdivision( + id: json["id"], + lotNo: json["lot_no"], + blockNo: json["block_no"], + ); + + Map toJson() => { + "id": id, + "lot_no": lotNo, + "block_no": blockNo, + }; +} \ No newline at end of file diff --git a/lib/model/login_data/employee_info/department.dart b/lib/model/login_data/employee_info/department.dart new file mode 100644 index 0000000..59755b6 --- /dev/null +++ b/lib/model/login_data/employee_info/department.dart @@ -0,0 +1,41 @@ +import 'package:unit2/model/login_data/employee_info/head.dart'; + +class Department { + Department({ + this.id, + this.code, + this.head, + this.name, + this.acronym, + this.parentStationId, + this.fullCode, + }); + + int? id; + String? code; + Head? head; + String? name; + int? acronym; + int? parentStationId; + String? fullCode; + + factory Department.fromJson(Map json) => Department( + id: json["id"], + code: json["code"], + head:json["head"]==null?null:Head.fromJson(json["head"]), + name: json["name"], + acronym: json["acronym"], + parentStationId: json["parent_station_id"], + fullCode: json["full_code"], + ); + + Map toJson() => { + "id": id, + "code": code, + "head": head, + "name": name, + "acronym": acronym, + "parent_station_id": parentStationId, + "full_code": fullCode, + }; +} \ No newline at end of file diff --git a/lib/model/login_data/employee_info/employee_info.dart b/lib/model/login_data/employee_info/employee_info.dart new file mode 100644 index 0000000..20166df --- /dev/null +++ b/lib/model/login_data/employee_info/employee_info.dart @@ -0,0 +1,41 @@ +import 'package:unit2/model/login_data/employee_info/office.dart'; +import 'package:unit2/model/profile/profileInfomation.dart'; + +import '../../profile/basic_information/primary-information.dart'; + +class EmployeeInfo { + EmployeeInfo({ + this.employeeId, + this.empid, + this.classid, + this.uuid, + this.office, + this.profile, + }); + + String? employeeId; + int? empid; + String? classid; + String? uuid; + Office? office; + Profile? profile; + + factory EmployeeInfo.fromJson(Map json) => EmployeeInfo( + employeeId: json["employee_id"], + empid: json["empid"], + classid: json["classid"], + uuid: json["uuid"], + office: json["office"]==null?null:Office.fromJson(json["office"]), + profile: json["profile"]==null?null:Profile.fromJson(json["profile"]), + ); + + Map toJson() => { + "employee_id": employeeId, + "empid": empid, + "classid": classid, + "uuid": uuid, + "office": office!.toJson(), + "profile": profile!.toJson(), + }; +} + diff --git a/lib/model/login_data/employee_info/head.dart b/lib/model/login_data/employee_info/head.dart new file mode 100644 index 0000000..afeee07 --- /dev/null +++ b/lib/model/login_data/employee_info/head.dart @@ -0,0 +1,44 @@ + +class Head { + Head({ + this.id, + this.title, + this.classid, + this.fullName, + this.personId, + this.employeeid, + this.officeposid, + this.lastFullName, + }); + + int? id; + String? title; + String? classid; + String? fullName; + int? personId; + String? employeeid; + int? officeposid; + String? lastFullName; + + factory Head.fromJson(Map json) => Head( + id: json["id"], + title: json["title"], + classid: json["classid"], + fullName: json["full_name"], + personId: json["person_id"], + employeeid: json["employeeid"], + officeposid: json["officeposid"], + lastFullName: json["last_full_name"], + ); + + Map toJson() => { + "id": id, + "title": title, + "classid": classid, + "full_name": fullName, + "person_id": personId, + "employeeid": employeeid, + "officeposid": officeposid, + "last_full_name": lastFullName, + }; +} \ No newline at end of file diff --git a/lib/model/login_data/employee_info/office.dart b/lib/model/login_data/employee_info/office.dart new file mode 100644 index 0000000..7d31f52 --- /dev/null +++ b/lib/model/login_data/employee_info/office.dart @@ -0,0 +1,47 @@ +import 'department.dart'; +import 'position_class.dart'; + +class Office { + Office({ + this.unit, + this.section, + this.division, + this.posstatid, + this.department, + this.stationId, + this.positionClass, + this.positionSpecificrole, + }); + + Department? unit; + Department? section; + Department? division; + int? posstatid; + Department? department; + int? stationId; + PositionClass? positionClass; + PositionSpecificrole? positionSpecificrole; + + factory Office.fromJson(Map json) => Office( + unit: json["unit"]==null?null:Department.fromJson(json["unit"]), + section: json["section"]==null?null:Department.fromJson(json["section"]), + division: json["division"] ==null? null:Department.fromJson(json["division"]), + posstatid: json["posstatid"], + department: json["department"]==null?null:Department.fromJson(json["department"]), + stationId: json["station_id"], + positionClass: json["position_class"]==null?null:PositionClass.fromJson(json["position_class"]), + positionSpecificrole:json["position_specificrole"]==null?null: + PositionSpecificrole.fromJson(json["position_specificrole"]), + ); + + Map toJson() => { + "unit": unit!.toJson(), + "section": section!.toJson(), + "division": division!.toJson(), + "posstatid": posstatid, + "department": department!.toJson(), + "station_id": stationId, + "position_class": positionClass!.toJson(), + "position_specificrole": positionSpecificrole!.toJson(), + }; +} \ No newline at end of file diff --git a/lib/model/login_data/employee_info/position_class.dart b/lib/model/login_data/employee_info/position_class.dart new file mode 100644 index 0000000..be7bff8 --- /dev/null +++ b/lib/model/login_data/employee_info/position_class.dart @@ -0,0 +1,65 @@ +class PositionClass { + PositionClass({ + this.level, + this.classid, + this.groupcode, + this.salarygrade, + this.classSuffix, + this.classTitleid, + this.qualificationid, + this.competencyModelId, + }); + + int? level; + String? classid; + String? groupcode; + int? salarygrade; + String? classSuffix; + PositionSpecificrole? classTitleid; + int? qualificationid; + int? competencyModelId; + + factory PositionClass.fromJson(Map json) => PositionClass( + level: json["level"], + classid: json["classid"], + groupcode: json["groupcode"], + salarygrade: json["salarygrade"], + classSuffix: json["class_suffix"], + classTitleid:json["class_titleid"]==null?null: PositionSpecificrole.fromJson(json["class_titleid"]), + qualificationid: json["qualificationid"], + competencyModelId: json["competency_model_id"], + ); + + Map toJson() => { + "level": level, + "classid": classid, + "groupcode": groupcode, + "salarygrade": salarygrade, + "class_suffix": classSuffix, + "class_titleid": classTitleid!.toJson(), + "qualificationid": qualificationid, + "competency_model_id": competencyModelId, + }; +} + + +class PositionSpecificrole { + PositionSpecificrole({ + this.title, + this.titleid, + }); + + String? title; + int? titleid; + + factory PositionSpecificrole.fromJson(Map json) => + PositionSpecificrole( + title: json["title"], + titleid: json["titleid"], + ); + + Map toJson() => { + "title": title, + "titleid": titleid, + }; +} \ No newline at end of file diff --git a/lib/model/login_data/user_info/assigned_area.dart b/lib/model/login_data/user_info/assigned_area.dart new file mode 100644 index 0000000..d67b215 --- /dev/null +++ b/lib/model/login_data/user_info/assigned_area.dart @@ -0,0 +1,31 @@ +class AssignedArea { + AssignedArea({ + this.id, + this.areaid, + this.isactive, + this.areaName, + this.areaTypeName, + }); + + int? id; + String? areaid; + bool? isactive; + String? areaName; + String? areaTypeName; + + factory AssignedArea.fromJson(Map json) => AssignedArea( + id: json["id"], + areaid: json["areaid"], + isactive: json["isactive"], + areaName: json["area_name"], + areaTypeName: json["area_type_name"], + ); + + Map toJson() => { + "id": id, + "areaid": areaid, + "isactive": isactive, + "area_name": areaName, + "area_type_name": areaTypeName, + }; +} \ No newline at end of file diff --git a/lib/model/login_data/user_info/login_user.dart b/lib/model/login_data/user_info/login_user.dart new file mode 100644 index 0000000..8d492b7 --- /dev/null +++ b/lib/model/login_data/user_info/login_user.dart @@ -0,0 +1,48 @@ +import 'role.dart'; +class LoginUser { + LoginUser({ + this.id, + this.profileId, + this.firstName, + this.lastName, + this.username, + this.email, + this.staff, + this.roles, + }); + + int? id; + int? profileId; + String? firstName; + String? lastName; + String? username; + String? email; + bool? staff; + List? roles; + + factory LoginUser.fromJson(Map json) => LoginUser( + id: json["id"], + profileId: json["profile_id"], + firstName: json["first_name"], + lastName: json["last_name"], + username: json["username"], + email: json["email"], + staff: json["staff"], + roles: json["roles"] == null + ? [] + : List.from(json["roles"]!.map((x) => Role.fromJson(x))), + ); + + Map toJson() => { + "id": id, + "profile_id": profileId, + "first_name": firstName, + "last_name": lastName, + "username": username, + "email": email, + "staff": staff, + "roles": roles == null + ? [] + : List.from(roles!.map((x) => x!.toJson())), + }; +} \ No newline at end of file diff --git a/lib/model/login_data/user_info/module.dart b/lib/model/login_data/user_info/module.dart new file mode 100644 index 0000000..a72f278 --- /dev/null +++ b/lib/model/login_data/user_info/module.dart @@ -0,0 +1,68 @@ +class Module { + Module({ + this.id, + this.icon, + this.name, + this.slug, + this.objects, + }); + + int? id; + String? icon; + String? name; + String? slug; + List? objects; + + factory Module.fromJson(Map json) => Module( + id: json["id"], + icon: json["icon"], + name: json["name"], + slug: json["slug"], + objects: json["objects"] == null + ? [] + : List.from( + json["objects"]!.map((x) => ModuleObject.fromJson(x))), + ); + + Map toJson() => { + "id": id, + "icon": icon, + "name": name, + "slug": slug, + "objects": objects == null + ? [] + : List.from(objects!.map((x) => x!.toJson())), + }; +} + +class ModuleObject { + ModuleObject({ + this.id, + this.name, + this.slug, + this.operations, + }); + + int? id; + String? name; + String? slug; + List? operations; + + factory ModuleObject.fromJson(Map json) => ModuleObject( + id: json["id"], + name: json["name"], + slug: json["slug"], + operations: json["operations"] == null + ? [] + : List.from(json["operations"]!.map((x) => x)), + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "operations": operations == null + ? [] + : List.from(operations!.map((x) => x)), + }; +} \ No newline at end of file diff --git a/lib/model/login_data/user_info/role.dart b/lib/model/login_data/user_info/role.dart new file mode 100644 index 0000000..ff7c545 --- /dev/null +++ b/lib/model/login_data/user_info/role.dart @@ -0,0 +1,44 @@ +import 'assigned_area.dart'; +import 'module.dart'; + +class Role { + Role({ + this.id, + this.name, + this.modules, + this.assignedArea, + }); + + int? id; + String? name; + List? modules; + List? assignedArea; + + factory Role.fromJson(Map json) => Role( + id: json["id"], + name: json["name"], + modules: json["modules"] == null + ? [] + : List.from( + json["modules"]!.map((x) => Module.fromJson(x))), + assignedArea: json["assigned_area"] == null + ? [] + : json["assigned_area"] == null + ? [] + : List.from(json["assigned_area"]! + .map((x) => AssignedArea.fromJson(x))), + ); + + Map toJson() => { + "id": id, + "name": name, + "modules": modules == null + ? [] + : List.from(modules!.map((x) => x!.toJson())), + "assigned_area": assignedArea == null + ? [] + : assignedArea == null + ? [] + : List.from(assignedArea!.map((x) => x!.toJson())), + }; +} \ No newline at end of file diff --git a/lib/model/login_data/user_info/user_data.dart b/lib/model/login_data/user_info/user_data.dart new file mode 100644 index 0000000..470404c --- /dev/null +++ b/lib/model/login_data/user_info/user_data.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; + +import 'package:unit2/model/login_data/employee_info/employee_info.dart'; + +import 'login_user.dart'; + +UserData? userDataFromJson(String str) => UserData.fromJson(json.decode(str)); + +String userDataToJson(UserData? data) => json.encode(data!.toJson()); + +class UserData { + UserData({ + this.user, + this.employeeInfo, + }); + + UserDataUser? user; + EmployeeInfo? employeeInfo; + + factory UserData.fromJson(Map json) => UserData( + user: UserDataUser.fromJson(json["user"]), + employeeInfo: EmployeeInfo.fromJson(json["employee_info"]), + ); + + Map toJson() => { + "user": user!.toJson(), + "employee_info": employeeInfo!.toJson(), + }; +} + +class UserDataUser { + UserDataUser({ + this.login, + }); + + Login? login; + + factory UserDataUser.fromJson(Map json) => UserDataUser( + login: Login.fromJson(json["login"]), + ); + + Map toJson() => { + "login": login!.toJson(), + }; +} + +class Login { + Login({ + this.dateTime, + this.token, + this.user, + }); + + DateTime? dateTime; + String? token; + LoginUser? user; + + factory Login.fromJson(Map json) => Login( + dateTime: DateTime.parse(json["date_time"]), + token: json["token"], + user: LoginUser.fromJson(json["user"]), + ); + + Map toJson() => { + "date_time": dateTime?.toIso8601String(), + "token": token, + "user": user!.toJson(), + }; +} + + diff --git a/lib/model/login_data/version_info.dart b/lib/model/login_data/version_info.dart new file mode 100644 index 0000000..12ae4fb --- /dev/null +++ b/lib/model/login_data/version_info.dart @@ -0,0 +1,48 @@ +class VersionInfo { + VersionInfo({ + this.version, + this.versionInfo, + this.dateReleased, + this.development, + this.production, + this.downloadUrl, + this.arm64v8aDownloadUrl, + this.armeabiv7aDownloadUrl, + this.x8664DownloadUrl, + }); + + String? version; + String? versionInfo; + DateTime? dateReleased; + bool? development; + bool? production; + String? downloadUrl; + String? arm64v8aDownloadUrl; + String? armeabiv7aDownloadUrl; + String? x8664DownloadUrl; + + factory VersionInfo.fromJson(Map json) => VersionInfo( + version: json["version"], + versionInfo: json["version_info"], + dateReleased: DateTime.parse(json["date_released"]), + development: json["development"], + production: json["production"], + downloadUrl: json["download_url"], + arm64v8aDownloadUrl: json["arm64_v8a_download_url"], + armeabiv7aDownloadUrl: json["armeabi_v7a_download_url"], + x8664DownloadUrl: json["x86_64_down_download_url"], + ); + + Map toJson() => { + "version": version, + "version_info": versionInfo, + "date_released": + "${dateReleased!.year.toString().padLeft(4, '0')}-${dateReleased!.month.toString().padLeft(2, '0')}-${dateReleased!.day.toString().padLeft(2, '0')}", + "development": development, + "production": production, + "download_url": downloadUrl, + "arm64_v8a_download_url": arm64v8aDownloadUrl, + "armeabi_v7a_download_url": armeabiv7aDownloadUrl, + "x86_64_down_download_url": x8664DownloadUrl, + }; +} diff --git a/lib/model/passo/additional_items.dart b/lib/model/passo/additional_items.dart new file mode 100644 index 0000000..9f89494 --- /dev/null +++ b/lib/model/passo/additional_items.dart @@ -0,0 +1,93 @@ +// To parse this JSON data, do +// +// final additionalItems = additionalItemsFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +AdditionalItems additionalItemsFromJson(String str) => + AdditionalItems.fromJson(json.decode(str)); + +String additionalItemsToJson(AdditionalItems data) => + json.encode(data.toJson()); + +class AdditionalItems { + final int id; + final int bldgapprDetailsId; + final int classId; + final String className; + final String structType; + final dynamic unitValue; + final dynamic baseUnitValue; + final dynamic area; + final dynamic marketValue; + final dynamic depreciationRate; + final dynamic adjustedMarketVal; + final dynamic amtDepreciation; + final bool painted; + final bool secondhand; + final dynamic paintedUnitval; + final dynamic secondhandUnitval; + final String actualUse; + + AdditionalItems({ + required this.id, + required this.bldgapprDetailsId, + required this.classId, + required this.className, + required this.structType, + required this.unitValue, + required this.baseUnitValue, + required this.area, + required this.marketValue, + required this.depreciationRate, + required this.adjustedMarketVal, + required this.amtDepreciation, + required this.painted, + required this.secondhand, + required this.paintedUnitval, + required this.secondhandUnitval, + required this.actualUse, + }); + + factory AdditionalItems.fromJson(Map json) => + AdditionalItems( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + classId: json["class_id"], + className: json["class_name"], + structType: json["struct_type"], + unitValue: json["unit_value"], + baseUnitValue: json["base_unit_value"], + area: json["area"], + marketValue: json["market_value"], + depreciationRate: json["depreciation_rate"], + adjustedMarketVal: json["adjusted_market_val"], + amtDepreciation: json["amt_depreciation"], + painted: json["painted"], + secondhand: json["secondhand"], + paintedUnitval: json["painted_unitval"], + secondhandUnitval: json["secondhand_unitval"], + actualUse: json["actual_use"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "class_id": classId, + "class_name": className, + "struct_type": structType, + "unit_value": unitValue, + "base_unit_value": baseUnitValue, + "area": area, + "market_value": marketValue, + "depreciation_rate": depreciationRate, + "adjusted_market_val": adjustedMarketVal, + "amt_depreciation": amtDepreciation, + "painted": painted, + "secondhand": secondhand, + "painted_unitval": paintedUnitval, + "secondhand_unitval": secondhandUnitval, + "actual_use": actualUse, + }; +} diff --git a/lib/model/passo/barangay.dart b/lib/model/passo/barangay.dart new file mode 100644 index 0000000..6dacfa1 --- /dev/null +++ b/lib/model/passo/barangay.dart @@ -0,0 +1,37 @@ +// To parse this JSON data, do +// +// final barangay = barangayFromJson(jsonString); + +import 'dart:convert'; + +Brgy barangayFromJson(String str) => Brgy.fromJson(json.decode(str)); + +String barangayToJson(Brgy data) => json.encode(data.toJson()); + +class Brgy { + final int? barangayId; + final String? barangayCode; + final String? cityCode; + final String? barangayDescription; + + Brgy({ + this.barangayId, + this.barangayCode, + this.cityCode, + this.barangayDescription, + }); + + factory Brgy.fromJson(Map json) => Brgy( + barangayId: json["barangay_id"], + barangayCode: json["barangay_code"], + cityCode: json["city_code"], + barangayDescription: json["barangay_description"], + ); + + Map toJson() => { + "barangay_id": barangayId, + "barangay_code": barangayCode, + "city_code": cityCode, + "barangay_description": barangayDescription, + }; +} diff --git a/lib/model/passo/bldg_loc.dart b/lib/model/passo/bldg_loc.dart new file mode 100644 index 0000000..06714fb --- /dev/null +++ b/lib/model/passo/bldg_loc.dart @@ -0,0 +1,65 @@ +// To parse this JSON data, do +// +// final bldgLoc = bldgLocFromJson(jsonString); + +import 'dart:convert'; + +BldgLoc bldgLocFromJson(String str) => BldgLoc.fromJson(json.decode(str)); + +String bldgLocToJson(BldgLoc data) => json.encode(data.toJson()); + +class BldgLoc { + final int? id; + final int? bldgapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final dynamic street; + final dynamic barangay; + final dynamic municipality; + final dynamic province; + + BldgLoc({ + this.id, + this.bldgapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.street, + this.barangay, + this.municipality, + this.province, + }); + + factory BldgLoc.fromJson(Map json) => BldgLoc( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + street: json["street"], + barangay: json["barangay"], + municipality: json["municipality"], + province: json["province"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "street": street, + "barangay": barangay, + "municipality": municipality, + "province": province, + }; +} diff --git a/lib/model/passo/city.dart b/lib/model/passo/city.dart new file mode 100644 index 0000000..eb22f22 --- /dev/null +++ b/lib/model/passo/city.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final city = cityFromJson(jsonString); + +import 'dart:convert'; + +City cityFromJson(String str) => City.fromJson(json.decode(str)); + +String cityToJson(City data) => json.encode(data.toJson()); + +class City { + final String? cityCode; + final String? cityDescription; + + City({ + this.cityCode, + this.cityDescription, + }); + + factory City.fromJson(Map json) => City( + cityCode: json["city_code"], + cityDescription: json["city_description"], + ); + + Map toJson() => { + "city_code": cityCode, + "city_description": cityDescription, + }; +} diff --git a/lib/model/passo/class_components.dart b/lib/model/passo/class_components.dart new file mode 100644 index 0000000..b9ce05b --- /dev/null +++ b/lib/model/passo/class_components.dart @@ -0,0 +1,93 @@ +// To parse this JSON data, do +// +// final classComponents = classComponentsFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +ClassComponents classComponentsFromJson(String str) => + ClassComponents.fromJson(json.decode(str)); + +String classComponentsToJson(ClassComponents data) => + json.encode(data.toJson()); + +class ClassComponents { + final int id; + final String componentName; + final String minBaseUnitvalPercent; + final String maxBaseUnitvalPercent; + final String minUnitvalSqrmtr; + final String maxUnitvalSqrmtr; + final String minAddBaseunitval; + final String maxAddBaseunitval; + final String minDeductBaserate; + final String maxDeductBaserate; + final String minLinearMeter; + final String maxLinearMeter; + final String minSpacing; + final String maxSpacing; + final String roughFinish; + final String highFinish; + final bool withoutBucc; + + ClassComponents({ + required this.id, + required this.componentName, + required this.minBaseUnitvalPercent, + required this.maxBaseUnitvalPercent, + required this.minUnitvalSqrmtr, + required this.maxUnitvalSqrmtr, + required this.minAddBaseunitval, + required this.maxAddBaseunitval, + required this.minDeductBaserate, + required this.maxDeductBaserate, + required this.minLinearMeter, + required this.maxLinearMeter, + required this.minSpacing, + required this.maxSpacing, + required this.roughFinish, + required this.highFinish, + required this.withoutBucc, + }); + + factory ClassComponents.fromJson(Map json) => + ClassComponents( + id: json["id"], + componentName: json["component_name"], + minBaseUnitvalPercent: json["min_base_unitval_percent"], + maxBaseUnitvalPercent: json["max_base_unitval_percent"], + minUnitvalSqrmtr: json["min_unitval_sqrmtr"], + maxUnitvalSqrmtr: json["max_unitval_sqrmtr"], + minAddBaseunitval: json["min_add_baseunitval"], + maxAddBaseunitval: json["max_add_baseunitval"], + minDeductBaserate: json["min_deduct_baserate"], + maxDeductBaserate: json["max_deduct_baserate"], + minLinearMeter: json["min_linear_meter"], + maxLinearMeter: json["max_linear_meter"], + minSpacing: json["min_spacing"], + maxSpacing: json["max_spacing"], + roughFinish: json["rough_finish"], + highFinish: json["high_finish"], + withoutBucc: json["without_bucc"], + ); + + Map toJson() => { + "id": id, + "component_name": componentName, + "min_base_unitval_percent": minBaseUnitvalPercent, + "max_base_unitval_percent": maxBaseUnitvalPercent, + "min_unitval_sqrmtr": minUnitvalSqrmtr, + "max_unitval_sqrmtr": maxUnitvalSqrmtr, + "min_add_baseunitval": minAddBaseunitval, + "max_add_baseunitval": maxAddBaseunitval, + "min_deduct_baserate": minDeductBaserate, + "max_deduct_baserate": maxDeductBaserate, + "min_linear_meter": minLinearMeter, + "max_linear_meter": maxLinearMeter, + "min_spacing": minSpacing, + "max_spacing": maxSpacing, + "rough_finish": roughFinish, + "high_finish": highFinish, + "without_bucc": withoutBucc, + }; +} diff --git a/lib/model/passo/general_description.dart b/lib/model/passo/general_description.dart new file mode 100644 index 0000000..68002a5 --- /dev/null +++ b/lib/model/passo/general_description.dart @@ -0,0 +1,137 @@ +// To parse this JSON data, do +// +// final generalDesc = generalDescFromJson(jsonString); + +import 'dart:convert'; + +GeneralDesc generalDescFromJson(String str) => + GeneralDesc.fromJson(json.decode(str)); + +String generalDescToJson(GeneralDesc data) => json.encode(data.toJson()); + +class GeneralDesc { + final int? id; + final int? bldgapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? bldgKind; + final String? strucType; + final String? bldgPermit; + final DateTime? dateIssued; + final String? cct; + final DateTime? certCompletionIssued; + final DateTime? certOccupancyIssued; + final DateTime? dateCompleted; + final DateTime? dateOccupied; + final int? bldgAge; + final int? noStoreys; + final String? area1Stfloor; + final String? area2Ndfloor; + final String? area3Rdfloor; + final String? area4Thfloor; + final String? totalFloorArea; + final dynamic floorSketch; + final String? actualUse; + + GeneralDesc({ + this.id, + this.bldgapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.bldgKind, + this.strucType, + this.bldgPermit, + this.dateIssued, + this.cct, + this.certCompletionIssued, + this.certOccupancyIssued, + this.dateCompleted, + this.dateOccupied, + this.bldgAge, + this.noStoreys, + this.area1Stfloor, + this.area2Ndfloor, + this.area3Rdfloor, + this.area4Thfloor, + this.totalFloorArea, + this.floorSketch, + this.actualUse, + }); + + factory GeneralDesc.fromJson(Map json) => GeneralDesc( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + bldgKind: json["bldg_kind"], + strucType: json["struc_type"], + bldgPermit: json["bldg_permit"], + dateIssued: json["date_issued"] == null + ? null + : DateTime.parse(json["date_issued"]), + cct: json["cct"], + certCompletionIssued: json["cert_completion_issued"] == null + ? null + : DateTime.parse(json["cert_completion_issued"]), + certOccupancyIssued: json["cert_occupancy_issued"] == null + ? null + : DateTime.parse(json["cert_occupancy_issued"]), + dateCompleted: json["date_completed"] == null + ? null + : DateTime.parse(json["date_completed"]), + dateOccupied: json["date_occupied"] == null + ? null + : DateTime.parse(json["date_occupied"]), + bldgAge: json["bldg_age"], + noStoreys: json["no_storeys"], + area1Stfloor: json["area_1stfloor"], + area2Ndfloor: json["area_2ndfloor"], + area3Rdfloor: json["area_3rdfloor"], + area4Thfloor: json["area_4thfloor"], + totalFloorArea: json["total_floor_area"], + floorSketch: json["floor_sketch"], + actualUse: json["actual_use"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "bldg_kind": bldgKind, + "struc_type": strucType, + "bldg_permit": bldgPermit, + "date_issued": + "${dateIssued!.year.toString().padLeft(4, '0')}-${dateIssued!.month.toString().padLeft(2, '0')}-${dateIssued!.day.toString().padLeft(2, '0')}", + "cct": cct, + "cert_completion_issued": + "${certCompletionIssued!.year.toString().padLeft(4, '0')}-${certCompletionIssued!.month.toString().padLeft(2, '0')}-${certCompletionIssued!.day.toString().padLeft(2, '0')}", + "cert_occupancy_issued": + "${certOccupancyIssued!.year.toString().padLeft(4, '0')}-${certOccupancyIssued!.month.toString().padLeft(2, '0')}-${certOccupancyIssued!.day.toString().padLeft(2, '0')}", + "date_completed": + "${dateCompleted!.year.toString().padLeft(4, '0')}-${dateCompleted!.month.toString().padLeft(2, '0')}-${dateCompleted!.day.toString().padLeft(2, '0')}", + "date_occupied": + "${dateOccupied!.year.toString().padLeft(4, '0')}-${dateOccupied!.month.toString().padLeft(2, '0')}-${dateOccupied!.day.toString().padLeft(2, '0')}", + "bldg_age": bldgAge, + "no_storeys": noStoreys, + "area_1stfloor": area1Stfloor, + "area_2ndfloor": area2Ndfloor, + "area_3rdfloor": area3Rdfloor, + "area_4thfloor": area4Thfloor, + "total_floor_area": totalFloorArea, + "floor_sketch": floorSketch, + "actual_use": actualUse, + }; +} diff --git a/lib/model/passo/land_appr.dart b/lib/model/passo/land_appr.dart new file mode 100644 index 0000000..91e9b1b --- /dev/null +++ b/lib/model/passo/land_appr.dart @@ -0,0 +1,49 @@ +// To parse this JSON data, do +// +// final landAppr = landApprFromJson(jsonString); + +import 'dart:convert'; + +LandAppr landApprFromJson(String str) => LandAppr.fromJson(json.decode(str)); + +String landApprToJson(LandAppr data) => json.encode(data.toJson()); + +class LandAppr { + final int? id; + final int? landapprDetailsId; + final String? classification; + final String? subClass; + final String? area; + final String? unitValue; + final String? baseMarketval; + + LandAppr({ + this.id, + this.landapprDetailsId, + this.classification, + this.subClass, + this.area, + this.unitValue, + this.baseMarketval, + }); + + factory LandAppr.fromJson(Map json) => LandAppr( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + classification: json["classification"], + subClass: json["sub_class"], + area: json["area"], + unitValue: json["unit_value"], + baseMarketval: json["base_marketval"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "classification": classification, + "sub_class": subClass, + "area": area, + "unit_value": unitValue, + "base_marketval": baseMarketval, + }; +} diff --git a/lib/model/passo/land_classification.dart b/lib/model/passo/land_classification.dart new file mode 100644 index 0000000..0315271 --- /dev/null +++ b/lib/model/passo/land_classification.dart @@ -0,0 +1,36 @@ +// To parse this JSON data, do +// +// final landClassification = landClassificationFromJson(jsonString); + +import 'dart:convert'; + +LandClassification landClassificationFromJson(String str) => + LandClassification.fromJson(json.decode(str)); + +String landClassificationToJson(LandClassification data) => + json.encode(data.toJson()); + +class LandClassification { + final int? id; + final String? classificationCode; + final String? description; + + LandClassification({ + this.id, + this.classificationCode, + this.description, + }); + + factory LandClassification.fromJson(Map json) => + LandClassification( + id: json["id"], + classificationCode: json["classification_code"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "classification_code": classificationCode, + "description": description, + }; +} diff --git a/lib/model/passo/land_ext.dart b/lib/model/passo/land_ext.dart new file mode 100644 index 0000000..5c935f8 --- /dev/null +++ b/lib/model/passo/land_ext.dart @@ -0,0 +1,124 @@ +// To parse this JSON data, do +// +// final landExt = landExtFromJson(jsonString); + +import 'dart:convert'; + +LandExt landExtFromJson(String str) => LandExt.fromJson(json.decode(str)); + +String landExtToJson(LandExt data) => json.encode(data.toJson()); + +class LandExt { + final int? id; + final int? landapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final bool? taxable; + final bool? exempt; + final int? qtr; + final int? yr; + final String? appraisedbyName; + final DateTime? appraisedbyDate; + final String? recommendapprName; + final DateTime? recommendapprDate; + final String? approvedbyName; + final DateTime? approvedbyDate; + final String? memoranda; + final String? swornstatementNo; + final DateTime? dateReceived; + final DateTime? entryDateAssessment; + final String? entryDateBy; + + LandExt({ + this.id, + this.landapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.taxable, + this.exempt, + this.qtr, + this.yr, + this.appraisedbyName, + this.appraisedbyDate, + this.recommendapprName, + this.recommendapprDate, + this.approvedbyName, + this.approvedbyDate, + this.memoranda, + this.swornstatementNo, + this.dateReceived, + this.entryDateAssessment, + this.entryDateBy, + }); + + factory LandExt.fromJson(Map json) => LandExt( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + taxable: json["taxable"], + exempt: json["exempt"], + qtr: json["qtr"], + yr: json["yr"], + appraisedbyName: json["appraisedby_name"], + appraisedbyDate: json["appraisedby_date"] == null + ? null + : DateTime.parse(json["appraisedby_date"]), + recommendapprName: json["recommendappr_name"], + recommendapprDate: json["recommendappr_date"] == null + ? null + : DateTime.parse(json["recommendappr_date"]), + approvedbyName: json["approvedby_name"], + approvedbyDate: json["approvedby_date"] == null + ? null + : DateTime.parse(json["approvedby_date"]), + memoranda: json["memoranda"], + swornstatementNo: json["swornstatement_no"], + dateReceived: json["date_received"] == null + ? null + : DateTime.parse(json["date_received"]), + entryDateAssessment: json["entry_date_assessment"] == null + ? null + : DateTime.parse(json["entry_date_assessment"]), + entryDateBy: json["entry_date_by"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "taxable": taxable, + "exempt": exempt, + "qtr": qtr, + "yr": yr, + "appraisedby_name": appraisedbyName, + "appraisedby_date": + "${appraisedbyDate!.year.toString().padLeft(4, '0')}-${appraisedbyDate!.month.toString().padLeft(2, '0')}-${appraisedbyDate!.day.toString().padLeft(2, '0')}", + "recommendappr_name": recommendapprName, + "recommendappr_date": + "${recommendapprDate!.year.toString().padLeft(4, '0')}-${recommendapprDate!.month.toString().padLeft(2, '0')}-${recommendapprDate!.day.toString().padLeft(2, '0')}", + "approvedby_name": approvedbyName, + "approvedby_date": + "${approvedbyDate!.year.toString().padLeft(4, '0')}-${approvedbyDate!.month.toString().padLeft(2, '0')}-${approvedbyDate!.day.toString().padLeft(2, '0')}", + "memoranda": memoranda, + "swornstatement_no": swornstatementNo, + "date_received": + "${dateReceived!.year.toString().padLeft(4, '0')}-${dateReceived!.month.toString().padLeft(2, '0')}-${dateReceived!.day.toString().padLeft(2, '0')}", + "entry_date_assessment": + "${entryDateAssessment!.year.toString().padLeft(4, '0')}-${entryDateAssessment!.month.toString().padLeft(2, '0')}-${entryDateAssessment!.day.toString().padLeft(2, '0')}", + "entry_date_by": entryDateBy, + }; +} diff --git a/lib/model/passo/land_property_assessment.dart b/lib/model/passo/land_property_assessment.dart new file mode 100644 index 0000000..cbab632 --- /dev/null +++ b/lib/model/passo/land_property_assessment.dart @@ -0,0 +1,56 @@ +// To parse this JSON data, do +// +// final landPropertyAssessment = landPropertyAssessmentFromJson(jsonString); + +import 'dart:convert'; + +LandPropertyAssessment landPropertyAssessmentFromJson(String str) => + LandPropertyAssessment.fromJson(json.decode(str)); + +String landPropertyAssessmentToJson(LandPropertyAssessment data) => + json.encode(data.toJson()); + +class LandPropertyAssessment { + final int? id; + final int? landapprDetailsId; + final String? actualUse; + final String? marketval; + final String? assessmentLevel; + final String? assessedValue; + final String? totalMarketval; + final String? totalAssessedval; + + LandPropertyAssessment({ + this.id, + this.landapprDetailsId, + this.actualUse, + this.marketval, + this.assessmentLevel, + this.assessedValue, + this.totalMarketval, + this.totalAssessedval, + }); + + factory LandPropertyAssessment.fromJson(Map json) => + LandPropertyAssessment( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + actualUse: json["actual_use"], + marketval: json["marketval"], + assessmentLevel: json["assessment_level"], + assessedValue: json["assessed_value"], + totalMarketval: json["total_marketval"], + totalAssessedval: json["total_assessedval"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "actual_use": actualUse, + "marketval": marketval, + "assessment_level": assessmentLevel, + "assessed_value": assessedValue, + "total_marketval": totalMarketval, + "total_assessedval": totalAssessedval, + }; +} diff --git a/lib/model/passo/land_property_boundaries.dart b/lib/model/passo/land_property_boundaries.dart new file mode 100644 index 0000000..49a3ada --- /dev/null +++ b/lib/model/passo/land_property_boundaries.dart @@ -0,0 +1,72 @@ +// To parse this JSON data, do +// +// final landPropertyBoundaries = landPropertyBoundariesFromJson(jsonString); + +import 'dart:convert'; + +LandPropertyBoundaries landPropertyBoundariesFromJson(String str) => + LandPropertyBoundaries.fromJson(json.decode(str)); + +String landPropertyBoundariesToJson(LandPropertyBoundaries data) => + json.encode(data.toJson()); + +class LandPropertyBoundaries { + final int? id; + final int? landapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? north; + final String? east; + final String? south; + final String? west; + final dynamic sketch; + + LandPropertyBoundaries({ + this.id, + this.landapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.north, + this.east, + this.south, + this.west, + this.sketch, + }); + + factory LandPropertyBoundaries.fromJson(Map json) => + LandPropertyBoundaries( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + north: json["north"], + east: json["east"], + south: json["south"], + west: json["west"], + sketch: json["sketch"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "north": north, + "east": east, + "south": south, + "west": west, + "sketch": sketch, + }; +} diff --git a/lib/model/passo/land_property_loc.dart b/lib/model/passo/land_property_loc.dart new file mode 100644 index 0000000..25a7466 --- /dev/null +++ b/lib/model/passo/land_property_loc.dart @@ -0,0 +1,68 @@ +// To parse this JSON data, do +// +// final lnadPropertyLoc = lnadPropertyLocFromJson(jsonString); + +import 'dart:convert'; + +LandPropertyLoc lnadPropertyLocFromJson(String str) => + LandPropertyLoc.fromJson(json.decode(str)); + +String lnadPropertyLocToJson(LandPropertyLoc data) => + json.encode(data.toJson()); + +class LandPropertyLoc { + final int? id; + final int? landapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? street; + final String? municipality; + final String? barangay; + final String? province; + + LandPropertyLoc({ + this.id, + this.landapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.street, + this.municipality, + this.barangay, + this.province, + }); + + factory LandPropertyLoc.fromJson(Map json) => + LandPropertyLoc( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + street: json["street"], + municipality: json["municipality"], + barangay: json["barangay"], + province: json["province"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "street": street, + "municipality": municipality, + "barangay": barangay, + "province": province, + }; +} diff --git a/lib/model/passo/land_property_owner.dart b/lib/model/passo/land_property_owner.dart new file mode 100644 index 0000000..9c644af --- /dev/null +++ b/lib/model/passo/land_property_owner.dart @@ -0,0 +1,117 @@ +// To parse this JSON data, do +// +// final landPropertyOwner = landPropertyOwnerFromJson(jsonString); + +import 'dart:convert'; + +LandPropertyOwner landPropertyOwnerFromJson(String str) => + LandPropertyOwner.fromJson(json.decode(str)); + +String landPropertyOwnerToJson(LandPropertyOwner data) => + json.encode(data.toJson()); + +class LandPropertyOwner { + final int? id; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? transCode; + final String? tdn; + final String? pin; + final String? cloaNo; + final DateTime? dated; + final String? surveyNo; + final String? lotNo; + final String? blkNo; + final String? owner; + final String? address; + final String? telno; + final String? tin; + final String? adminUser; + final String? adminAddress; + final String? adminTelno; + final String? adminTin; + final String? faasType; + + LandPropertyOwner({ + this.id, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.transCode, + this.tdn, + this.pin, + this.cloaNo, + this.dated, + this.surveyNo, + this.lotNo, + this.blkNo, + this.owner, + this.address, + this.telno, + this.tin, + this.adminUser, + this.adminAddress, + this.adminTelno, + this.adminTin, + this.faasType, + }); + + factory LandPropertyOwner.fromJson(Map json) => + LandPropertyOwner( + id: json["id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + transCode: json["trans_code"], + tdn: json["tdn"], + pin: json["pin"], + cloaNo: json["cloa_no"], + dated: json["dated"] == null ? null : DateTime.parse(json["dated"]), + surveyNo: json["survey_no"], + lotNo: json["lot_no"], + blkNo: json["blk_no"], + owner: json["owner"], + address: json["address"], + telno: json["telno"], + tin: json["tin"], + adminUser: json["admin_user"], + adminAddress: json["admin_address"], + adminTelno: json["admin_telno"], + adminTin: json["admin_tin"], + faasType: json["faas_type"], + ); + + Map toJson() => { + "id": id, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "trans_code": transCode, + "tdn": tdn, + "pin": pin, + "cloa_no": cloaNo, + "dated": + "${dated!.year.toString().padLeft(4, '0')}-${dated!.month.toString().padLeft(2, '0')}-${dated!.day.toString().padLeft(2, '0')}", + "survey_no": surveyNo, + "lot_no": lotNo, + "blk_no": blkNo, + "owner": owner, + "address": address, + "telno": telno, + "tin": tin, + "admin_user": adminUser, + "admin_address": adminAddress, + "admin_telno": adminTelno, + "admin_tin": adminTin, + "faas_type": faasType, + }; +} diff --git a/lib/model/passo/land_ref.dart b/lib/model/passo/land_ref.dart new file mode 100644 index 0000000..8f4649d --- /dev/null +++ b/lib/model/passo/land_ref.dart @@ -0,0 +1,77 @@ +// To parse this JSON data, do +// +// final landRef = landRefFromJson(jsonString); + +import 'dart:convert'; + +LandRef landRefFromJson(String str) => LandRef.fromJson(json.decode(str)); + +String landRefToJson(LandRef data) => json.encode(data.toJson()); + +class LandRef { + final int? id; + final int? bldgapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final dynamic owner; + final dynamic cloaNo; + final dynamic lotNo; + final dynamic tdn; + final dynamic area; + final dynamic surveyNo; + final dynamic blkNo; + + LandRef({ + this.id, + this.bldgapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.owner, + this.cloaNo, + this.lotNo, + this.tdn, + this.area, + this.surveyNo, + this.blkNo, + }); + + factory LandRef.fromJson(Map json) => LandRef( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + owner: json["owner"], + cloaNo: json["cloa_no"], + lotNo: json["lot_no"], + tdn: json["tdn"], + area: json["area"], + surveyNo: json["survey_no"], + blkNo: json["blk_no"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "owner": owner, + "cloa_no": cloaNo, + "lot_no": lotNo, + "tdn": tdn, + "area": area, + "survey_no": surveyNo, + "blk_no": blkNo, + }; +} diff --git a/lib/model/passo/land_subclassification.dart b/lib/model/passo/land_subclassification.dart new file mode 100644 index 0000000..8bb042a --- /dev/null +++ b/lib/model/passo/land_subclassification.dart @@ -0,0 +1,48 @@ +// To parse this JSON data, do +// +// final landSubClassification = landSubClassificationFromJson(jsonString); + +import 'dart:convert'; + +LandSubClassification landSubClassificationFromJson(String str) => + LandSubClassification.fromJson(json.decode(str)); + +String landSubClassificationToJson(LandSubClassification data) => + json.encode(data.toJson()); + +class LandSubClassification { + final int? id; + final int? classificationId; + final String? cityCode; + final String? subclassCode; + final String? subclassDescription; + final String? baseUnitMarketval; + + LandSubClassification({ + this.id, + this.classificationId, + this.cityCode, + this.subclassCode, + this.subclassDescription, + this.baseUnitMarketval, + }); + + factory LandSubClassification.fromJson(Map json) => + LandSubClassification( + id: json["id"], + classificationId: json["classification_id"], + cityCode: json["city_code"], + subclassCode: json["subclass_code"], + subclassDescription: json["subclass_description"], + baseUnitMarketval: json["base_unit_marketval"], + ); + + Map toJson() => { + "id": id, + "classification_id": classificationId, + "city_code": cityCode, + "subclass_code": subclassCode, + "subclass_description": subclassDescription, + "base_unit_marketval": baseUnitMarketval, + }; +} diff --git a/lib/model/passo/land_value_adjustment.dart b/lib/model/passo/land_value_adjustment.dart new file mode 100644 index 0000000..33bdc59 --- /dev/null +++ b/lib/model/passo/land_value_adjustment.dart @@ -0,0 +1,52 @@ +// To parse this JSON data, do +// +// final valueAdjustments = valueAdjustmentsFromJson(jsonString); + +import 'dart:convert'; + +ValueAdjustments valueAdjustmentsFromJson(String str) => + ValueAdjustments.fromJson(json.decode(str)); + +String valueAdjustmentsToJson(ValueAdjustments data) => + json.encode(data.toJson()); + +class ValueAdjustments { + final int? id; + final int? landapprDetailsId; + final String? baseMarketval; + final String? adjustmentFactors; + final String? adjustment; + final String? valueAdjustment; + final String? marketValue; + + ValueAdjustments({ + this.id, + this.landapprDetailsId, + this.baseMarketval, + this.adjustmentFactors, + this.adjustment, + this.valueAdjustment, + this.marketValue, + }); + + factory ValueAdjustments.fromJson(Map json) => + ValueAdjustments( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + baseMarketval: json["base_marketval"], + adjustmentFactors: json["adjustment_factors"], + adjustment: json["adjustment"], + valueAdjustment: json["value_adjustment"], + marketValue: json["market_value"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "base_marketval": baseMarketval, + "adjustment_factors": adjustmentFactors, + "adjustment": adjustment, + "value_adjustment": valueAdjustment, + "market_value": marketValue, + }; +} diff --git a/lib/model/passo/memoranda.dart b/lib/model/passo/memoranda.dart new file mode 100644 index 0000000..8c629fd --- /dev/null +++ b/lib/model/passo/memoranda.dart @@ -0,0 +1,33 @@ +// To parse this JSON data, do +// +// final memoranda = memorandaFromJson(jsonString); + +import 'dart:convert'; + +Memoranda memorandaFromJson(String str) => Memoranda.fromJson(json.decode(str)); + +String memorandaToJson(Memoranda data) => json.encode(data.toJson()); + +class Memoranda { + final int? id; + final String? code; + final String? memoranda; + + Memoranda({ + this.id, + this.code, + this.memoranda, + }); + + factory Memoranda.fromJson(Map json) => Memoranda( + id: json["id"], + code: json["code"], + memoranda: json["memoranda"], + ); + + Map toJson() => { + "id": id, + "code": code, + "memoranda": memoranda, + }; +} diff --git a/lib/model/passo/other_improvements.dart b/lib/model/passo/other_improvements.dart new file mode 100644 index 0000000..bb36523 --- /dev/null +++ b/lib/model/passo/other_improvements.dart @@ -0,0 +1,64 @@ +// To parse this JSON data, do +// +// final otherImprovements = otherImprovementsFromJson(jsonString); + +import 'dart:convert'; + +OtherImprovements otherImprovementsFromJson(String str) => + OtherImprovements.fromJson(json.decode(str)); + +String otherImprovementsToJson(OtherImprovements data) => + json.encode(data.toJson()); + +class OtherImprovements { + final int? id; + final int? landapprDetailsId; + final String? kindsOfTrees; + final String? subclassAge; + final int? quantity; + final String? unitValue; + final String? baseMarketval; + final int? noOfProductive; + final int? noOfNonproductive; + final bool? fruitBearing; + + OtherImprovements({ + this.id, + this.landapprDetailsId, + this.kindsOfTrees, + this.subclassAge, + this.quantity, + this.unitValue, + this.baseMarketval, + this.noOfProductive, + this.noOfNonproductive, + this.fruitBearing, + }); + + factory OtherImprovements.fromJson(Map json) => + OtherImprovements( + id: json["id"], + landapprDetailsId: json["landappr_details_id"], + kindsOfTrees: json["kinds_of_trees"], + subclassAge: json["subclass_age"], + quantity: json["quantity"], + unitValue: json["unit_value"], + baseMarketval: json["base_marketval"], + noOfProductive: json["no_of_productive"], + noOfNonproductive: json["no_of_nonproductive"], + fruitBearing: json["fruit_bearing"], + ); + + Map toJson() => { + "id": id, + "landappr_details_id": landapprDetailsId, + "kinds_of_trees": kindsOfTrees, + "subclass_age": subclassAge, + "quantity": quantity, + "unit_value": unitValue, + "base_marketval": baseMarketval, + "no_of_productive": noOfProductive, + "no_of_nonproductive": noOfNonproductive, + "fruit_bearing": fruitBearing, + }; +} diff --git a/lib/model/passo/property_appraisal.dart b/lib/model/passo/property_appraisal.dart new file mode 100644 index 0000000..9ebe509 --- /dev/null +++ b/lib/model/passo/property_appraisal.dart @@ -0,0 +1,91 @@ +// To parse this JSON data, do +// +// final propertyAppraisal = propertyAppraisalFromJson(jsonString); + +import 'dart:convert'; + +PropertyAppraisal propertyAppraisalFromJson(String str) => + PropertyAppraisal.fromJson(json.decode(str)); + +String propertyAppraisalToJson(PropertyAppraisal data) => + json.encode(data.toJson()); + +class PropertyAppraisal { + final int? id; + final int? bldgapprDetailsId; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? unitconstructCost; + final String? buildingCore; + final String? unitconstructSubtotal; + final String? depreciationRate; + final String? depreciationCost; + final String? costAddItems; + final String? addItemsSubtotal; + final String? totalpercentDepreciation; + final String? marketValue; + final String? totalArea; + + PropertyAppraisal( + {this.id, + this.bldgapprDetailsId, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.unitconstructCost, + this.buildingCore, + this.unitconstructSubtotal, + this.depreciationRate, + this.depreciationCost, + this.costAddItems, + this.addItemsSubtotal, + this.totalpercentDepreciation, + this.marketValue, + this.totalArea}); + + factory PropertyAppraisal.fromJson(Map json) => + PropertyAppraisal( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + unitconstructCost: json["unitconstruct_cost"], + buildingCore: json["building_core"], + unitconstructSubtotal: json["unitconstruct_subtotal"], + depreciationRate: json["depreciation_rate"], + depreciationCost: json["depreciation_cost"], + costAddItems: json["cost_add_items"], + addItemsSubtotal: json["add_items_subtotal"], + totalpercentDepreciation: json["totalpercent_depreciation"], + marketValue: json["market_value"], + totalArea: json["total_area"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "unitconstruct_cost": unitconstructCost, + "building_core": buildingCore, + "unitconstruct_subtotal": unitconstructSubtotal, + "depreciation_rate": depreciationRate, + "depreciation_cost": depreciationCost, + "cost_add_items": costAddItems, + "add_items_subtotal": addItemsSubtotal, + "totalpercent_depreciation": totalpercentDepreciation, + "market_value": marketValue, + "total_area": totalArea + }; +} diff --git a/lib/model/passo/property_appraisal_edit.dart b/lib/model/passo/property_appraisal_edit.dart new file mode 100644 index 0000000..43e37ee --- /dev/null +++ b/lib/model/passo/property_appraisal_edit.dart @@ -0,0 +1,71 @@ +// To parse this JSON data, do +// +// final propertyAppraisal = propertyAppraisalFromJson(jsonString); + +import 'dart:convert'; + +PropertyAppraisalEdit propertyAppraisalFromJson(String str) => + PropertyAppraisalEdit.fromJson(json.decode(str)); + +String propertyAppraisalToJson(PropertyAppraisalEdit data) => + json.encode(data.toJson()); + +class PropertyAppraisalEdit { + final int? id; + final int? bldgapprDetailsId; + final String? unitconstructCost; + final String? buildingCore; + final String? unitconstructSubtotal; + final String? depreciationRate; + final String? depreciationCost; + final String? costAddItems; + final String? addItemsSubtotal; + final String? totalpercentDepreciation; + final String? marketValue; + final String? totalArea; + + PropertyAppraisalEdit( + {this.id, + this.bldgapprDetailsId, + this.unitconstructCost, + this.buildingCore, + this.unitconstructSubtotal, + this.depreciationRate, + this.depreciationCost, + this.costAddItems, + this.addItemsSubtotal, + this.totalpercentDepreciation, + this.marketValue, + this.totalArea}); + + factory PropertyAppraisalEdit.fromJson(Map json) => + PropertyAppraisalEdit( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + unitconstructCost: json["unitconstruct_cost"], + buildingCore: json["building_core"], + unitconstructSubtotal: json["unitconstruct_subtotal"], + depreciationRate: json["depreciation_rate"], + depreciationCost: json["depreciation_cost"], + costAddItems: json["cost_add_items"], + addItemsSubtotal: json["add_items_subtotal"], + totalpercentDepreciation: json["totalpercent_depreciation"], + marketValue: json["market_value"], + totalArea: json["total_area"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "unitconstruct_cost": unitconstructCost, + "building_core": buildingCore, + "unitconstruct_subtotal": unitconstructSubtotal, + "depreciation_rate": depreciationRate, + "depreciation_cost": depreciationCost, + "cost_add_items": costAddItems, + "add_items_subtotal": addItemsSubtotal, + "totalpercent_depreciation": totalpercentDepreciation, + "market_value": marketValue, + "total_area": totalArea + }; +} diff --git a/lib/model/passo/property_assessment.dart b/lib/model/passo/property_assessment.dart new file mode 100644 index 0000000..fb91bff --- /dev/null +++ b/lib/model/passo/property_assessment.dart @@ -0,0 +1,109 @@ +// To parse this JSON data, do +// +// final propertyAssessment = propertyAssessmentFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +PropertyAssessment propertyAssessmentFromJson(String str) => + PropertyAssessment.fromJson(json.decode(str)); + +String propertyAssessmentToJson(PropertyAssessment data) => + json.encode(data.toJson()); + +class PropertyAssessment { + final int id; + final int bldgapprDetailsId; + final String actualUse; + final String marketValue; + final String assessmentLevel; + final String assessedValue; + final bool taxable; + final bool exempt; + final int qtr; + final int yr; + final String appraisedbyName; + final DateTime appraisedbyDate; + final String recommendapprName; + final DateTime recommendapprDate; + final String approvedbyName; + final String memoranda; + final String swornstatementNo; + final DateTime dateReceived; + final DateTime entryDateAssessment; + final String entryDateBy; + + PropertyAssessment({ + required this.id, + required this.bldgapprDetailsId, + required this.actualUse, + required this.marketValue, + required this.assessmentLevel, + required this.assessedValue, + required this.taxable, + required this.exempt, + required this.qtr, + required this.yr, + required this.appraisedbyName, + required this.appraisedbyDate, + required this.recommendapprName, + required this.recommendapprDate, + required this.approvedbyName, + required this.memoranda, + required this.swornstatementNo, + required this.dateReceived, + required this.entryDateAssessment, + required this.entryDateBy, + }); + + factory PropertyAssessment.fromJson(Map json) => + PropertyAssessment( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + actualUse: json["actual_use"], + marketValue: json["market_value"], + assessmentLevel: json["assessment_level"], + assessedValue: json["assessed_value"], + taxable: json["taxable"], + exempt: json["exempt"], + qtr: json["qtr"], + yr: json["yr"], + appraisedbyName: json["appraisedby_name"], + appraisedbyDate: DateTime.parse(json["appraisedby_date"]), + recommendapprName: json["recommendappr_name"], + recommendapprDate: DateTime.parse(json["recommendappr_date"]), + approvedbyName: json["approvedby_name"], + memoranda: json["memoranda"], + swornstatementNo: json["swornstatement_no"], + dateReceived: DateTime.parse(json["date_received"]), + entryDateAssessment: DateTime.parse(json["entry_date_assessment"]), + entryDateBy: json["entry_date_by"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "actual_use": actualUse, + "market_value": marketValue, + "assessment_level": assessmentLevel, + "assessed_value": assessedValue, + "taxable": taxable, + "exempt": exempt, + "qtr": qtr, + "yr": yr, + "appraisedby_name": appraisedbyName, + "appraisedby_date": + "${appraisedbyDate.year.toString().padLeft(4, '0')}-${appraisedbyDate.month.toString().padLeft(2, '0')}-${appraisedbyDate.day.toString().padLeft(2, '0')}", + "recommendappr_name": recommendapprName, + "recommendappr_date": + "${recommendapprDate.year.toString().padLeft(4, '0')}-${recommendapprDate.month.toString().padLeft(2, '0')}-${recommendapprDate.day.toString().padLeft(2, '0')}", + "approvedby_name": approvedbyName, + "memoranda": memoranda, + "swornstatement_no": swornstatementNo, + "date_received": + "${dateReceived.year.toString().padLeft(4, '0')}-${dateReceived.month.toString().padLeft(2, '0')}-${dateReceived.day.toString().padLeft(2, '0')}", + "entry_date_assessment": + "${entryDateAssessment.year.toString().padLeft(4, '0')}-${entryDateAssessment.month.toString().padLeft(2, '0')}-${entryDateAssessment.day.toString().padLeft(2, '0')}", + "entry_date_by": entryDateBy, + }; +} diff --git a/lib/model/passo/property_assessment_edit.dart b/lib/model/passo/property_assessment_edit.dart new file mode 100644 index 0000000..5e0ee15 --- /dev/null +++ b/lib/model/passo/property_assessment_edit.dart @@ -0,0 +1,109 @@ +// To parse this JSON data, do +// +// final propertyAssessment = propertyAssessmentFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +PropertyAssessmentEdit propertyAssessmentFromJson(String str) => + PropertyAssessmentEdit.fromJson(json.decode(str)); + +String propertyAssessmentToJson(PropertyAssessmentEdit data) => + json.encode(data.toJson()); + +class PropertyAssessmentEdit { + final int? id; + final int? bldgapprDetailsId; + final String? actualUse; + final String? marketValue; + final String? assessmentLevel; + final String? assessedValue; + final bool? taxable; + final bool? exempt; + final int? qtr; + final int? yr; + final String? appraisedbyName; + final DateTime? appraisedbyDate; + final String? recommendapprName; + final DateTime? recommendapprDate; + final String? approvedbyName; + final String? memoranda; + final String? swornstatementNo; + final DateTime? dateReceived; + final DateTime? entryDateAssessment; + final String? entryDateBy; + + PropertyAssessmentEdit({ + this.id, + this.bldgapprDetailsId, + this.actualUse, + this.marketValue, + this.assessmentLevel, + this.assessedValue, + this.taxable, + this.exempt, + this.qtr, + this.yr, + this.appraisedbyName, + this.appraisedbyDate, + this.recommendapprName, + this.recommendapprDate, + this.approvedbyName, + this.memoranda, + this.swornstatementNo, + this.dateReceived, + this.entryDateAssessment, + this.entryDateBy, + }); + + factory PropertyAssessmentEdit.fromJson(Map json) => + PropertyAssessmentEdit( + id: json["id"], + bldgapprDetailsId: json["bldgappr_details_id"], + actualUse: json["actual_use"], + marketValue: json["market_value"], + assessmentLevel: json["assessment_level"], + assessedValue: json["assessed_value"], + taxable: json["taxable"], + exempt: json["exempt"], + qtr: json["qtr"], + yr: json["yr"], + appraisedbyName: json["appraisedby_name"], + appraisedbyDate: DateTime.parse(json["appraisedby_date"]), + recommendapprName: json["recommendappr_name"], + recommendapprDate: DateTime.parse(json["recommendappr_date"]), + approvedbyName: json["approvedby_name"], + memoranda: json["memoranda"], + swornstatementNo: json["swornstatement_no"], + dateReceived: DateTime.parse(json["date_received"]), + entryDateAssessment: DateTime.parse(json["entry_date_assessment"]), + entryDateBy: json["entry_date_by"], + ); + + Map toJson() => { + "id": id, + "bldgappr_details_id": bldgapprDetailsId, + "actual_use": actualUse, + "market_value": marketValue, + "assessment_level": assessmentLevel, + "assessed_value": assessedValue, + "taxable": taxable, + "exempt": exempt, + "qtr": qtr, + "yr": yr, + "appraisedby_name": appraisedbyName, + "appraisedby_date": + "${appraisedbyDate!.year.toString().padLeft(4, '0')}-${appraisedbyDate!.month.toString().padLeft(2, '0')}-${appraisedbyDate!.day.toString().padLeft(2, '0')}", + "recommendappr_name": recommendapprName, + "recommendappr_date": + "${recommendapprDate!.year.toString().padLeft(4, '0')}-${recommendapprDate!.month.toString().padLeft(2, '0')}-${recommendapprDate!.day.toString().padLeft(2, '0')}", + "approvedby_name": approvedbyName, + "memoranda": memoranda, + "swornstatement_no": swornstatementNo, + "date_received": + "${dateReceived!.year.toString().padLeft(4, '0')}-${dateReceived!.month.toString().padLeft(2, '0')}-${dateReceived!.day.toString().padLeft(2, '0')}", + "entry_date_assessment": + "${entryDateAssessment!.year.toString().padLeft(4, '0')}-${entryDateAssessment!.month.toString().padLeft(2, '0')}-${entryDateAssessment!.day.toString().padLeft(2, '0')}", + "entry_date_by": entryDateBy, + }; +} diff --git a/lib/model/passo/property_info.dart b/lib/model/passo/property_info.dart new file mode 100644 index 0000000..68406e2 --- /dev/null +++ b/lib/model/passo/property_info.dart @@ -0,0 +1,94 @@ +// To parse this JSON data, do +// +// final propertyInfo = propertyInfoFromJson(jsonString); + +import 'dart:convert'; + +PropertyInfo propertyInfoFromJson(String str) => + PropertyInfo.fromJson(json.decode(str)); + +String propertyInfoToJson(PropertyInfo data) => json.encode(data.toJson()); + +class PropertyInfo { + final int? id; + final String? assessedById; + final String? assessedByName; + final DateTime? dateCreated; + final DateTime? dateModified; + final String? transCode; + final String? tdn; + final String? pin; + final String? owner; + final String? address; + final String? telno; + final String? tin; + final String? adminUser; + final String? adminAddress; + final String? adminTelno; + final String? adminTin; + final String? faasType; + + PropertyInfo({ + this.id, + this.assessedById, + this.assessedByName, + this.dateCreated, + this.dateModified, + this.transCode, + this.tdn, + this.pin, + this.owner, + this.address, + this.telno, + this.tin, + this.adminUser, + this.adminAddress, + this.adminTelno, + this.adminTin, + this.faasType, + }); + + factory PropertyInfo.fromJson(Map json) => PropertyInfo( + id: json["id"], + assessedById: json["assessed_by_id"], + assessedByName: json["assessed_by_name"], + dateCreated: json["date_created"] == null + ? null + : DateTime.parse(json["date_created"]), + dateModified: json["date_modified"] == null + ? null + : DateTime.parse(json["date_modified"]), + transCode: json["trans_code"], + tdn: json["tdn"], + pin: json["pin"], + owner: json["owner"], + address: json["address"], + telno: json["telno"], + tin: json["tin"], + adminUser: json["admin_user"], + adminAddress: json["admin_address"], + adminTelno: json["admin_telno"], + adminTin: json["admin_tin"], + faasType: json["faas_type"], + ); + + Map toJson() => { + "id": id, + "assessed_by_id": assessedById, + "assessed_by_name": assessedByName, + "date_created": dateCreated?.toIso8601String(), + "date_modified": dateModified?.toIso8601String(), + "trans_code": transCode, + "tdn": tdn, + "pin": pin, + "owner": owner, + "address": address, + "telno": telno, + "tin": tin, + "admin_user": adminUser, + "admin_address": adminAddress, + "admin_telno": adminTelno, + "admin_tin": adminTin, + "faas_type": faasType, + }; +} diff --git a/lib/model/passo/signatories.dart b/lib/model/passo/signatories.dart new file mode 100644 index 0000000..641f491 --- /dev/null +++ b/lib/model/passo/signatories.dart @@ -0,0 +1,42 @@ +// To parse this JSON data, do +// +// final signatories = signatoriesFromJson(jsonString); + +import 'dart:convert'; + +Signatories signatoriesFromJson(String str) => + Signatories.fromJson(json.decode(str)); + +String signatoriesToJson(Signatories data) => json.encode(data.toJson()); + +class Signatories { + final int? id; + final int signatoryId; + final String firstname; + final String middlename; + final String lastname; + + Signatories({ + this.id, + required this.signatoryId, + required this.firstname, + required this.middlename, + required this.lastname, + }); + + factory Signatories.fromJson(Map json) => Signatories( + id: json["id"], + signatoryId: json["signatory_id"], + firstname: json["firstname"], + middlename: json["middlename"], + lastname: json["lastname"], + ); + + Map toJson() => { + "id": id, + "signatory_id": signatoryId, + "firstname": firstname, + "middlename": middlename, + "lastname": lastname, + }; +} diff --git a/lib/model/passo/structural_materials_ii.dart b/lib/model/passo/structural_materials_ii.dart new file mode 100644 index 0000000..cfa3ec2 --- /dev/null +++ b/lib/model/passo/structural_materials_ii.dart @@ -0,0 +1,60 @@ +// To parse this JSON data, do +// +// final structureMaterialsIi = structureMaterialsIiFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +StructureMaterialsII structureMaterialsIiFromJson(String str) => + StructureMaterialsII.fromJson(json.decode(str)); + +String structureMaterialsIiToJson(StructureMaterialsII data) => + json.encode(data.toJson()); + +class StructureMaterialsII { + final int? id; + final List? foundation; + final List? columns; + final List? beams; + final List? trussFraming; + final List? roof; + final List? flooring; + final List? walls; + final List? others; + + StructureMaterialsII( + {this.id, + this.foundation, + this.columns, + this.beams, + this.trussFraming, + this.roof, + this.flooring, + this.walls, + this.others}); + + factory StructureMaterialsII.fromJson(Map json) => + StructureMaterialsII( + id: json["id"], + foundation: List.from(json["foundation"].map((x) => x)), + columns: List.from(json["columns"].map((x) => x)), + beams: List.from(json["beams"].map((x) => x)), + trussFraming: List.from(json["truss_framing"].map((x) => x)), + roof: List.from(json["roof"].map((x) => x)), + flooring: List.from(json["flooring"].map((x) => x)), + walls: List.from(json["walls"].map((x) => x)), + others: List.from(json["others"].map((x) => x)), + ); + + Map toJson() => { + "id": id, + "foundation": List.from(foundation!.map((x) => x)), + "columns": List.from(columns!.map((x) => x)), + "beams": List.from(beams!.map((x) => x)), + "truss_framing": List.from(trussFraming!.map((x) => x)), + "roof": List.from(roof!.map((x) => x)), + "flooring": List.from(flooring!.map((x) => x)), + "walls": List.from(walls!.map((x) => x)), + "others": List.from(others!.map((x) => x)), + }; +} diff --git a/lib/model/passo/structureMaterial.dart b/lib/model/passo/structureMaterial.dart new file mode 100644 index 0000000..4c07c23 --- /dev/null +++ b/lib/model/passo/structureMaterial.dart @@ -0,0 +1,57 @@ +// To parse this JSON data, do +// +// final structureMaterials = structureMaterialsFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +StructureMaterials structureMaterialsFromJson(String str) => + StructureMaterials.fromJson(json.decode(str)); + +String structureMaterialsToJson(StructureMaterials data) => + json.encode(data.toJson()); + +class StructureMaterials { + final int? id; + final String? foundation; + final String? columns; + final String? beams; + final String? trussFraming; + final String? roof; + final String? flooring; + final String? walls; + + StructureMaterials({ + this.id, + this.foundation, + this.columns, + this.beams, + this.trussFraming, + this.roof, + this.flooring, + this.walls, + }); + + factory StructureMaterials.fromJson(Map json) => + StructureMaterials( + id: json["id"], + foundation: json["foundation"], + columns: json["columns"], + beams: json["beams"], + trussFraming: json["truss_framing"], + roof: json["roof"], + flooring: json["flooring"], + walls: json["walls"], + ); + + Map toJson() => { + "id": id, + "foundation": foundation, + "columns": columns, + "beams": beams, + "truss_framing": trussFraming, + "roof": roof, + "flooring": flooring, + "walls": walls, + }; +} diff --git a/lib/model/passo/trees_improvements.dart b/lib/model/passo/trees_improvements.dart new file mode 100644 index 0000000..cc72f4a --- /dev/null +++ b/lib/model/passo/trees_improvements.dart @@ -0,0 +1,40 @@ +// To parse this JSON data, do +// +// final treesImprovements = treesImprovementsFromJson(jsonString); + +import 'dart:convert'; + +TreesImprovements treesImprovementsFromJson(String str) => + TreesImprovements.fromJson(json.decode(str)); + +String treesImprovementsToJson(TreesImprovements data) => + json.encode(data.toJson()); + +class TreesImprovements { + final int? id; + final String? improvement; + final String? pricePerTree; + final dynamic subclassCode; + + TreesImprovements({ + this.id, + this.improvement, + this.pricePerTree, + this.subclassCode, + }); + + factory TreesImprovements.fromJson(Map json) => + TreesImprovements( + id: json["id"], + improvement: json["improvement"], + pricePerTree: json["price_per_tree"], + subclassCode: json["subclass_code"], + ); + + Map toJson() => { + "id": id, + "improvement": improvement, + "price_per_tree": pricePerTree, + "subclass_code": subclassCode, + }; +} diff --git a/lib/model/passo/type_of_location.dart b/lib/model/passo/type_of_location.dart new file mode 100644 index 0000000..9990236 --- /dev/null +++ b/lib/model/passo/type_of_location.dart @@ -0,0 +1,38 @@ +// To parse this JSON data, do +// +// final typeOfLocation = typeOfLocationFromJson(jsonString); + +import 'dart:convert'; + +TypeOfLocation typeOfLocationFromJson(String str) => + TypeOfLocation.fromJson(json.decode(str)); + +String typeOfLocationToJson(TypeOfLocation data) => json.encode(data.toJson()); + +class TypeOfLocation { + final int? id; + final String? distanceKm; + final String? allRoadTypes; + final String? localTradingCenter; + + TypeOfLocation({ + this.id, + this.distanceKm, + this.allRoadTypes, + this.localTradingCenter, + }); + + factory TypeOfLocation.fromJson(Map json) => TypeOfLocation( + id: json["id"], + distanceKm: json["distance_km"], + allRoadTypes: json["all_road_types"], + localTradingCenter: json["local_trading_center"], + ); + + Map toJson() => { + "id": id, + "distance_km": distanceKm, + "all_road_types": allRoadTypes, + "local_trading_center": localTradingCenter, + }; +} diff --git a/lib/model/passo/type_of_road.dart b/lib/model/passo/type_of_road.dart new file mode 100644 index 0000000..e545e29 --- /dev/null +++ b/lib/model/passo/type_of_road.dart @@ -0,0 +1,34 @@ +// To parse this JSON data, do +// +// final typeOfRoad = typeOfRoadFromJson(jsonString); + +import 'dart:convert'; + +TypeOfRoad typeOfRoadFromJson(String str) => + TypeOfRoad.fromJson(json.decode(str)); + +String typeOfRoadToJson(TypeOfRoad data) => json.encode(data.toJson()); + +class TypeOfRoad { + final int? id; + final String? roadType; + final String? deduction; + + TypeOfRoad({ + this.id, + this.roadType, + this.deduction, + }); + + factory TypeOfRoad.fromJson(Map json) => TypeOfRoad( + id: json["id"], + roadType: json["road_type"], + deduction: json["deduction"], + ); + + Map toJson() => { + "id": id, + "road_type": roadType, + "deduction": deduction, + }; +} diff --git a/lib/model/passo/unit_construct.dart b/lib/model/passo/unit_construct.dart new file mode 100644 index 0000000..bc97fa3 --- /dev/null +++ b/lib/model/passo/unit_construct.dart @@ -0,0 +1,38 @@ +// To parse this JSON data, do +// +// final unitConstruct = unitConstructFromJson(jsonString); + +import 'dart:convert'; + +UnitConstruct unitConstructFromJson(String str) => + UnitConstruct.fromJson(json.decode(str)); + +String unitConstructToJson(UnitConstruct data) => json.encode(data.toJson()); + +class UnitConstruct { + final int id; + final String bldgType; + final String building; + final String unitValue; + + UnitConstruct({ + required this.id, + required this.bldgType, + required this.building, + required this.unitValue, + }); + + factory UnitConstruct.fromJson(Map json) => UnitConstruct( + id: json["id"], + bldgType: json["bldg_type"], + building: json["building"], + unitValue: json["unit_value"], + ); + + Map toJson() => { + "id": id, + "bldg_type": bldgType, + "building": building, + "unit_value": unitValue, + }; +} diff --git a/lib/model/profile/attachment.dart b/lib/model/profile/attachment.dart new file mode 100644 index 0000000..f0676f8 --- /dev/null +++ b/lib/model/profile/attachment.dart @@ -0,0 +1,118 @@ + +import 'dart:convert'; + +Attachment attachmentFromJson(String str) => + Attachment.fromJson(json.decode(str)); + +String attachmentToJson(Attachment data) => json.encode(data.toJson()); + +class Attachment { + final int? id; + final String? source; + final AttachmentCategory? category; + final String? filename; + final Subclass? subclass; + final DateTime? createdAt; + + Attachment({ + required this.id, + required this.source, + required this.category, + required this.filename, + required this.subclass, + required this.createdAt, + }); + + factory Attachment.fromJson(Map json) => Attachment( + id: json["id"], + source: json["source"], + category: json['category'] == null + ? null + : AttachmentCategory.fromJson(json["category"]), + filename: json["filename"], + subclass: json['subclass'] == null + ? null + : Subclass.fromJson(json["subclass"]), + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json["created_at"]), + ); + + Map toJson() => { + "id": id, + "source": source, + "category": category?.toJson(), + "filename": filename, + "subclass": subclass?.toJson(), + "created_at": createdAt?.toIso8601String(), + }; +} + +class AttachmentCategory { + final int? id; + final Subclass? subclass; + final String? description; + + AttachmentCategory({ + required this.id, + required this.subclass, + required this.description, + }); + + factory AttachmentCategory.fromJson(Map json) => AttachmentCategory( + id: json["id"], + subclass:json['subclass'] == null? null: Subclass.fromJson(json["subclass"]), + description: json["description"], + ); + + Map toJson() => { + "id": id, + "subclass": subclass?.toJson(), + "description": description, + }; +} + +class Subclass { + final int? id; + final String? name; + final AttachmentClass? attachmentClass; + + Subclass({ + required this.id, + required this.name, + required this.attachmentClass, + }); + + factory Subclass.fromJson(Map json) => Subclass( + id: json["id"], + name: json["name"], + attachmentClass: json['attachment_class'] == null? null: AttachmentClass.fromJson(json["attachment_class"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "attachment_class": attachmentClass?.toJson(), + }; +} + +class AttachmentClass { + final int? id; + final String? name; + + AttachmentClass({ + required this.id, + required this.name, + }); + + factory AttachmentClass.fromJson(Map json) => + AttachmentClass( + id: json["id"], + name: json["name"], + ); + + Map toJson() => { + "id": id, + "name": name, + }; +} diff --git a/lib/model/profile/basic_info.dart b/lib/model/profile/basic_info.dart new file mode 100644 index 0000000..c2a9b31 --- /dev/null +++ b/lib/model/profile/basic_info.dart @@ -0,0 +1,14 @@ +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/model/profile/basic_information/citizenship.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/model/profile/basic_information/identification_information.dart'; +import 'package:unit2/model/profile/basic_information/primary-information.dart'; + +class BasicInfo{ + List contactInformation; + List identifications; + List citizenships; + List addresses; + BasicInfo({required this.addresses, required this.contactInformation,required this.identifications,required this.citizenships}); + +} \ No newline at end of file diff --git a/lib/model/profile/basic_information/adress.dart b/lib/model/profile/basic_information/adress.dart new file mode 100644 index 0000000..4e941ec --- /dev/null +++ b/lib/model/profile/basic_information/adress.dart @@ -0,0 +1,76 @@ + + +import '../../location/barangay.dart'; +import '../../location/city.dart'; +import '../../location/country.dart'; +import '../../location/subdivision.dart'; +import '../../utils/category.dart'; + +class MainAdress { + MainAdress({ + this.id, + this.address, + this.details, + this.subdivision, + }); + + final int? id; + final AddressClass? address; + final String? details; + final Subdivision? subdivision; + + factory MainAdress.fromJson(Map json) => MainAdress( + id: json["id"], + address: json["address"] == null ? null : AddressClass.fromJson(json["address"]), + details: json["details"], + subdivision: json["subdivision"] == null ? null : Subdivision.fromJson(json["subdivision"]), + ); + + Map toJson() => { + "id": id, + "address": address?.toJson(), + "details": details, + "subdivision": subdivision?.toJson(), + }; +} + +class AddressClass { + AddressClass({ + this.id, + this.country, + this.barangay, + this.category, + this.areaClass, + this.cityMunicipality, + }); + + final int? id; + final Country? country; + final Barangay? barangay; + final Category? category; + final String? areaClass; + final CityMunicipality? cityMunicipality; + + factory AddressClass.fromJson(Map json) => AddressClass( + id: json["id"], + country: json["country"] == null ? null : Country.fromJson(json["country"]), + barangay: json["barangay"] == null ? null : Barangay.fromJson(json["barangay"]), + category: json["category"] == null ? null : Category.fromJson(json["category"]), + areaClass: json["area_class"], + cityMunicipality: json["city_municipality"] == null ? null : CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "country": country?.toJson(), + "barangay": barangay?.toJson(), + "category": category?.toJson(), + "area_class": areaClass, + "city_municipality": cityMunicipality?.toJson(), + }; +} + + + + + diff --git a/lib/model/profile/basic_information/citizenship.dart b/lib/model/profile/basic_information/citizenship.dart new file mode 100644 index 0000000..1c694ed --- /dev/null +++ b/lib/model/profile/basic_information/citizenship.dart @@ -0,0 +1,22 @@ + +import '../../location/country.dart'; + +class Citizenship { + Citizenship({ + required this.country, + required this.naturalBorn, + }); + + final Country? country; + final bool? naturalBorn; + + factory Citizenship.fromJson(Map json) => Citizenship( + country: Country.fromJson(json["country"]), + naturalBorn: json["natural_born"], + ); + + Map toJson() => { + "country": country!.toJson(), + "natural_born": naturalBorn, + }; +} diff --git a/lib/model/profile/basic_information/contact_information.dart b/lib/model/profile/basic_information/contact_information.dart new file mode 100644 index 0000000..3c182e9 --- /dev/null +++ b/lib/model/profile/basic_information/contact_information.dart @@ -0,0 +1,107 @@ +// To parse this JSON data, do +// +// final contactInformation = contactInformationFromJson(jsonString); + + +import '../../utils/agency.dart'; + +class ContactInfo { + ContactInfo({ + required this.id, + required this.active, + required this.primary, + required this.numbermail, + required this.commService, + }); + + int? id; + bool? active; + bool? primary; + String? numbermail; + CommService? commService; + + factory ContactInfo.fromJson(Map json) => ContactInfo( + id: json["id"], + active: json["active"], + primary: json["primary"], + numbermail: json["numbermail"], + commService: json["comm_service"]==null?null: CommService.fromJson(json["comm_service"]), + ); + + Map toJson() => { + "id": id, + "active": active, + "primary": primary, + "numbermail": numbermail, + "comm_service": commService!.toJson(), + }; +} + +class CommService { + CommService({ + required this.id, + required this.serviceType, + required this.serviceProvider, + }); + + int? id; + ServiceType? serviceType; + ServiceProvider? serviceProvider; + + factory CommService.fromJson(Map json) => CommService( + id: json["id"], + serviceType: json["service_type"]==null?null: ServiceType.fromJson(json["service_type"]), + serviceProvider: json["service_provider"] == null?null: ServiceProvider.fromJson(json["service_provider"]), + ); + + Map toJson() => { + "id": id, + "service_type": serviceType!.toJson(), + "service_provider": serviceProvider!.toJson(), + }; +} + +class ServiceProvider { + ServiceProvider({ + required this.id, + required this.alias, + required this.agency, + }); + + int? id; + String? alias; + Agency? agency; + + factory ServiceProvider.fromJson(Map json) => ServiceProvider( + id: json["id"], + alias: json["alias"], + agency: json["agency"] == null? null: Agency.fromJson(json["agency"]), + ); + + Map toJson() => { + "id": id, + "alias": alias, + "agency": agency!.toJson(), + }; +} + + +class ServiceType { + ServiceType({ + required this.id, + required this.name, + }); + + int? id; + String? name; + + factory ServiceType.fromJson(Map json) => ServiceType( + id: json["id"], + name: json["name"], + ); + + Map toJson() => { + "id": id, + "name": name, + }; +} diff --git a/lib/model/profile/basic_information/identification_information.dart b/lib/model/profile/basic_information/identification_information.dart new file mode 100644 index 0000000..61411c1 --- /dev/null +++ b/lib/model/profile/basic_information/identification_information.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; + +import '../../location/city.dart'; +import '../../location/country.dart'; +import '../../utils/agency.dart'; + +Identification identificationFromJson(String str) => Identification.fromJson(json.decode(str)); + +String identificationToJson(Identification data) => json.encode(data.toJson()); + +class Identification { + Identification({ + required this.id, + required this.agency, + required this.issuedAt, + this.dateIssued, + this.expirationDate, + required this.asPdfReference, + required this.identificationNumber, + }); + + int? id; + Agency? agency; + IssuedAt? issuedAt; + DateTime? dateIssued; + DateTime? expirationDate; + bool? asPdfReference; + String? identificationNumber; + + factory Identification.fromJson(Map json) => Identification( + id: json["id"], + agency:json["agency"] == null? null: Agency.fromJson(json["agency"]), + issuedAt: json["issued_at"] == null? null:IssuedAt.fromJson(json["issued_at"]), + dateIssued:json["date_issued"]==null?null:DateTime.parse(json["date_issued"]), + expirationDate:json["expiration_date"]==null?null:DateTime.parse(json["expiration_date"]), + asPdfReference: json["as_pdf_reference"], + identificationNumber: json["identification_number"], + ); + + Map toJson() => { + "id": id, + "agency": agency!.toJson(), + "issued_at": issuedAt!.toJson(), + "date_issued": dateIssued, + "expiration_date": expirationDate, + "as_pdf_reference": asPdfReference, + "identification_number": identificationNumber, + }; +} + + +class IssuedAt { + IssuedAt({ + required this.id, + this.issuedAtClass, + required this.country, + this.barangay, + required this.addressCategory, + required this.cityMunicipality, + }); + + int? id; + dynamic issuedAtClass; + Country? country; + dynamic barangay; + AddressCategory? addressCategory; + CityMunicipality? cityMunicipality; + + factory IssuedAt.fromJson(Map json) => IssuedAt( + id: json["id"], + issuedAtClass: json["class"], + country: json['country'] == null? null: Country.fromJson(json["country"]), + barangay: json["barangay"], + addressCategory: json["address_category"] == null? null: AddressCategory.fromJson(json["address_category"]), + cityMunicipality:json["city_municipality"] == null? null: CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "class": issuedAtClass, + "country": country!.toJson(), + "barangay": barangay, + "address_category": addressCategory!.toJson(), + "city_municipality": cityMunicipality!.toJson(), + }; +} + +class AddressCategory { + AddressCategory({ + required this.id, + required this.name, + required this.type, + }); + + int? id; + String? name; + String? type; + + factory AddressCategory.fromJson(Map json) => AddressCategory( + id: json["id"], + name: json["name"], + type: json["type"], + ); + + Map toJson() => { + "id": id, + "name": name, + "type": type, + }; +} diff --git a/lib/model/profile/basic_information/primary-information.dart b/lib/model/profile/basic_information/primary-information.dart new file mode 100644 index 0000000..c936a39 --- /dev/null +++ b/lib/model/profile/basic_information/primary-information.dart @@ -0,0 +1,125 @@ +// To parse this JSON data, do +// +// final primaryInformation = primaryInformationFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'package:unit2/model/profile/family_backround.dart'; + +import '../../../screens/profile/components/basic_information/profile_other_info.dart'; + +Profile primaryInformationFromJson(String str) => Profile.fromJson(json.decode(str)); + +String primaryInformationToJson(Profile data) => json.encode(data.toJson()); + +class Profile { + int? webuserId; + int? id; + String? lastName; + String? firstName; + String? middleName; + String? nameExtension; + String? sex; + DateTime? birthdate; + String? civilStatus; + String? bloodType; + double? heightM; + double? weightKg; + String? photoPath; + String? esigPath; + MaidenName? maidenName; + bool? deceased; + String? uuidQrcode; + String? titlePrefix; + String? titleSuffix; + bool? showTitleId; + String? ethnicity; + String? disability; + String? gender; + String? religion; + String? ip; + + Profile({ + required this.webuserId, + required this.id, + required this.lastName, + required this.firstName, + required this.middleName, + required this.nameExtension, + required this.sex, + required this.birthdate, + required this.civilStatus, + required this.bloodType, + required this.heightM, + required this.weightKg, + required this.photoPath, + required this.esigPath, + required this.maidenName, + required this.deceased, + required this.uuidQrcode, + required this.titlePrefix, + required this.titleSuffix, + required this.showTitleId, + required this.ethnicity, + required this.disability, + required this.gender, + required this.religion, + required this.ip, + }); + + factory Profile.fromJson(Map json) => Profile( + webuserId: null, + id: json["id"], + lastName: json["last_name"], + firstName: json["first_name"], + middleName: json["middle_name"], + nameExtension: json["name_extension"], + sex: json["sex"], + birthdate:json['birthdate'] ==null?null: DateTime.parse(json["birthdate"]), + civilStatus: json["civil_status"], + bloodType: json["blood_type"], + heightM: json["height_m"]?.toDouble(), + weightKg: json["weight_kg"]?.toDouble(), + photoPath: json["photo_path"], + esigPath: json["esig_path"], + maidenName: json["maiden_name"]==null?null:MaidenName.fromJson(json["maiden_name"]), + deceased: json["deceased"], + uuidQrcode: json["uuid_qrcode"], + titlePrefix: json["title_prefix"], + titleSuffix: json["title_suffix"], + showTitleId: json["show_title_id"], + ethnicity: json["ethnicity"]== null?null:json["ethnicity"]['name'], + disability: json["disability"] == null?null:json['disability']['name'], + gender: json["gender"] == null?null:json['gender']['name'], + religion: json["religion"] == null?null:json['religion']['name'], + ip: json["ip"]==null?null:json['ip']['name'], + ); + + Map toJson() => { + "id": id, + "last_name": lastName, + "first_name": firstName, + "middle_name": middleName, + "name_extension": nameExtension, + "sex": sex, + "birthdate": "${birthdate?.year.toString().padLeft(4, '0')}-${birthdate?.month.toString().padLeft(2, '0')}-${birthdate?.day.toString().padLeft(2, '0')}", + "civil_status": civilStatus, + "blood_type": bloodType, + "height_m": heightM, + "weight_kg": weightKg, + "photo_path": photoPath, + "esig_path": esigPath, + "maiden_name": maidenName, + "deceased": deceased, + "uuid_qrcode": uuidQrcode, + "title_prefix": titlePrefix, + "title_suffix": titleSuffix, + "show_title_id": showTitleId, + "ethnicity": ethnicity, + "disability": disability, + "gender": gender, + "religion": religion, + "ip": ip, + }; +} diff --git a/lib/model/profile/educational_background.dart b/lib/model/profile/educational_background.dart new file mode 100644 index 0000000..843aed0 --- /dev/null +++ b/lib/model/profile/educational_background.dart @@ -0,0 +1,147 @@ +// To parse this JSON data, do +// +// final educationalBackground = educationalBackgroundFromJson(jsonString); + +import 'dart:convert'; + +import 'package:unit2/model/profile/attachment.dart'; + +EducationalBackground educationalBackgroundFromJson(String str) => EducationalBackground.fromJson(json.decode(str)); + +String educationalBackgroundToJson(EducationalBackground data) => json.encode(data.toJson()); + +class EducationalBackground { + EducationalBackground({ + this.id, + this.honors, + this.education, + this.periodTo, + this.attachments, + this.periodFrom, + this.unitsEarned, + this.yearGraduated, + }); + + final int? id; + final List? honors; + final Education? education; + final String? periodTo; + List? attachments; + final String? periodFrom; + final int? unitsEarned; + final String? yearGraduated; + + factory EducationalBackground.fromJson(Map json) => EducationalBackground( + id: json["id"], + honors: json["honors"] == null ? [] : List.from(json["honors"]!.map((x) => Honor.fromJson(x))), + education: json["education"] == null ? null : Education.fromJson(json["education"]), + periodTo: json["period_to"], + attachments: json['attachments'] ==null?null: List.from(json["attachments"].map((x) => Attachment.fromJson(x))), + periodFrom: json["period_from"], + unitsEarned: json["units_earned"], + yearGraduated: json["year_graduated"], + ); + + Map toJson() => { + "id": id, + "honors": honors == null ? [] : List.from(honors!.map((x) => x.toJson())), + "education": education?.toJson(), + "period_to": periodTo, + "attachments": attachments, + "period_from": periodFrom, + "units_earned": unitsEarned, + "year_graduated": yearGraduated, + }; +} + +class Education { + Education({ + this.id, + this.level, + this.course, + this.school, + }); + + final int? id; + final String? level; + final Course? course; + final School? school; + + factory Education.fromJson(Map json) => Education( + id: json["id"], + level: json["level"], + course: json["course"] == null ? null : Course.fromJson(json["course"]), + school: json["school"] == null ? null : School.fromJson(json["school"]), + ); + + Map toJson() => { + "id": id, + "level": level, + "course": course?.toJson(), + "school": school?.toJson(), + }; +} + +class Course { + Course({ + this.id, + this.program, + }); + + final int? id; + final String? program; + + factory Course.fromJson(Map json) => Course( + id: json["id"], + program: json["program"], + ); + + Map toJson() => { + "id": id, + "program": program, + }; +} + +class School { + School({ + this.id, + this.name, + }); + + final int? id; + final String? name; + + factory School.fromJson(Map json) => School( + id: json["id"], + name: json["name"], + ); + + Map toJson() => { + "id": id, + "name": name, + }; +} + +class Honor { + Honor({ + this.id, + this.name, + this.academ, + }); + + final int? id; + final String? name; + final bool? academ; + + factory Honor.fromJson(Map json) => Honor( + id: json["id"], + name: json["name"], + academ: json["academ"], + ); + + Map toJson() => { + "id": id, + "name": name, + "academ": academ, + }; +} diff --git a/lib/model/profile/eligibility.dart b/lib/model/profile/eligibility.dart new file mode 100644 index 0000000..5a8f7c7 --- /dev/null +++ b/lib/model/profile/eligibility.dart @@ -0,0 +1,125 @@ +// To parse this JSON data, do +// +// final eligibity = eligibityFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'package:unit2/model/location/region.dart'; +import 'package:unit2/model/profile/attachment.dart'; + +import '../location/address_category.dart'; +import '../location/city.dart'; +import '../location/country.dart'; +import '../utils/eligibility.dart'; + +EligibityCert eligibityFromJson(String str) => + EligibityCert.fromJson(json.decode(str)); + +String eligibityToJson(EligibityCert data) => json.encode(data.toJson()); + +class EligibityCert { + EligibityCert({ + required this.id, + required this.rating, + required this.examDate, + required this.attachments, + required this.eligibility, + required this.examAddress, + required this.validityDate, + required this.licenseNumber, + required this.overseas, + }); + bool? overseas; + final int? id; + final double? rating; + final DateTime? examDate; + List? attachments; + + final Eligibility? eligibility; + final ExamAddress? examAddress; + final DateTime? validityDate; + final String? licenseNumber; + + factory EligibityCert.fromJson(Map json) => EligibityCert( + id: json["id"], + rating: json["rating"]?.toDouble(), + examDate: json['exam_date'] == null + ? null + : DateTime.parse(json["exam_date"]), + attachments: json['attachments'] ==null?null: List.from(json["attachments"].map((x) => Attachment.fromJson(x))), + eligibility: json['eligibility'] == null + ? null + : Eligibility.fromJson(json["eligibility"]), + examAddress: json['exam_address'] == null + ? null + : ExamAddress.fromJson(json["exam_address"]), + validityDate: json['validity_date'] == null + ? null + : DateTime.parse(json["validity_date"]), + licenseNumber: json["license_number"], + overseas: null, + ); + + Map toJson() => { + "id": id, + "rating": rating, + "exam_date": + "${examDate!.year.toString().padLeft(4, '0')}-${examDate!.month.toString().padLeft(2, '0')}-${examDate!.day.toString().padLeft(2, '0')}", + "attachments": attachments, + "eligibility": eligibility!.toJson(), + "exam_address": examAddress!.toJson(), + "validity_date": "${validityDate!.year.toString().padLeft(4, '0')}-${validityDate!.month.toString().padLeft(2, '0')}-${validityDate!.day.toString().padLeft(2, '0')}", + "license_number": licenseNumber, + }; + @override + String toString() { + return 'eligibility:${eligibility.toString()}, rating:$rating, examDate:${examDate.toString()},validydate:${validityDate.toString()}, lisence:$licenseNumber, examAddress:${examAddress.toString()}'; + } +} + +class ExamAddress { + ExamAddress({ + required this.id, + required this.examAddressClass, + required this.country, + required this.barangay, + required this.addressCategory, + required this.cityMunicipality, + }); + + final int? id; + final dynamic examAddressClass; + final Country? country; + final dynamic barangay; + final AddressCategory? addressCategory; + final CityMunicipality? cityMunicipality; + + factory ExamAddress.fromJson(Map json) => ExamAddress( + id: json["id"], + examAddressClass: json["class"], + country: + json["country"] == null ? null : Country.fromJson(json["country"]), + barangay: json["barangay"], + addressCategory: json["address_category"] == null + ? null + : AddressCategory.fromJson(json["address_category"]), + cityMunicipality: json["city_municipality"] == null + ? null + : CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "class": examAddressClass, + "country": country!.toJson(), + "barangay": barangay, + "address_category": addressCategory!.toJson(), + "city_municipality": cityMunicipality!.toJson(), + }; + + @override + String toString() { + return 'country:${country.toString()} , address:${cityMunicipality.toString()}'; + } +} diff --git a/lib/model/profile/family_backround.dart b/lib/model/profile/family_backround.dart new file mode 100644 index 0000000..fb8a397 --- /dev/null +++ b/lib/model/profile/family_backround.dart @@ -0,0 +1,292 @@ +// To parse this JSON data, do +// +// final familyBackground = familyBackgroundFromJson(jsonString); + +import 'dart:convert'; +import 'dart:ffi'; + +import '../utils/category.dart'; +import '../utils/position.dart'; + +FamilyBackground familyBackgroundFromJson(String str) => + FamilyBackground.fromJson(json.decode(str)); + +String familyBackgroundToJson(FamilyBackground data) => + json.encode(data.toJson()); + +class FamilyBackground { + FamilyBackground({ + this.company, + this.position, + this.relationship, + this.relatedPerson, + this.companyAddress, + this.emergencyContact, + this.incaseOfEmergency, + this.companyContactNumber, + }); + + final Company? company; + final PositionTitle? position; + final Relationship? relationship; + final RelatedPerson? relatedPerson; + final String? companyAddress; + final List? emergencyContact; + final bool? incaseOfEmergency; + final String? companyContactNumber; + + factory FamilyBackground.fromJson(Map json) => + FamilyBackground( + company: + json["company"] == null ? null : Company.fromJson(json["company"]), + position: json["position"] == null + ? null + : PositionTitle.fromJson(json["position"]), + relationship: json["relationship"] == null + ? null + : Relationship.fromJson(json["relationship"]), + relatedPerson: json["related_person"] == null + ? null + : RelatedPerson.fromJson(json["related_person"]), + companyAddress: json["company_address"], + emergencyContact: json["emergency_contact"] == null + ? [] + : List.from(json["emergency_contact"]! + .map((x) => EmergencyContact.fromJson(x))), + incaseOfEmergency: json["incase_of_emergency"], + companyContactNumber: json["company_contact_number"], + ); + + Map toJson() => { + "company": company?.toJson(), + "position": position?.toJson(), + "relationship": relationship?.toJson(), + "related_person": relatedPerson?.toJson(), + "company_address": companyAddress, + "emergency_contact": emergencyContact == null + ? [] + : List.from(emergencyContact!.map((x) => x.toJson())), + "incase_of_emergency": incaseOfEmergency, + "company_contact_number": companyContactNumber, + }; +} + +class Company { + Company({ + this.id, + this.name, + this.category, + this.privateEntity, + }); + + final int? id; + final String? name; + final Category? category; + final bool? privateEntity; + + factory Company.fromJson(Map json) => Company( + id: json["id"], + name: json["name"], + category: json["category"] == null + ? null + : Category.fromJson(json["category"]), + privateEntity: json["private_entity"], + ); + + Map toJson() => { + "id": id, + "name": name, + "category": category?.toJson(), + "private_entity": privateEntity, + }; +} + +class EmergencyContact { + EmergencyContact({ + this.telco, + this.isactive, + this.provider, + this.isprimary, + this.numbermail, + this.serviceType, + this.contactinfoid, + this.commServiceId, + }); + + final String? telco; + final bool? isactive; + final int? provider; + final bool? isprimary; + final String? numbermail; + final int? serviceType; + final int? contactinfoid; + final int? commServiceId; + + factory EmergencyContact.fromJson(Map json) => + EmergencyContact( + telco: json["telco"], + isactive: json["isactive"], + provider: json["provider"], + isprimary: json["isprimary"], + numbermail: json["numbermail"], + serviceType: json["service_type"], + contactinfoid: json["contactinfoid"], + commServiceId: json["comm_service_id"], + ); + + Map toJson() => { + "telco": telco, + "isactive": isactive, + "provider": provider, + "isprimary": isprimary, + "numbermail": numbermail, + "service_type": serviceType, + "contactinfoid": contactinfoid, + "comm_service_id": commServiceId, + }; +} + +class RelatedPerson { + RelatedPerson({ + required this.id, + required this.gender, + required this.sex, + required this.deceased, + required this.heightM, + required this.birthdate, + required this.esigPath, + required this.lastName, + required this.weightKg, + required this.bloodType, + required this.firstName, + required this.photoPath, + required this.maidenName, + required this.middleName, + required this.uuidQrcode, + required this.civilStatus, + required this.titlePrefix, + required this.titleSuffix, + required this.showTitleId, + required this.nameExtension, + }); + + final int? id; + final String? sex; + final bool? deceased; + final String? gender; + final double? heightM; + final DateTime? birthdate; + final String? esigPath; + final String? lastName; + final double? weightKg; + final String? bloodType; + final String? firstName; + final String? photoPath; + final MaidenName? maidenName; + final String? middleName; + final String? uuidQrcode; + final String? civilStatus; + final String? titlePrefix; + final String? titleSuffix; + final bool? showTitleId; + final String? nameExtension; + + factory RelatedPerson.fromJson(Map json) => RelatedPerson( + id: json["id"], + sex: json["sex"], + gender: json["gender"], + deceased: json["deceased"], + heightM: json["height_m"] == null + ? null + : double.parse(json["height_m"].toString()), + birthdate: json["birthdate"] == null + ? null + : DateTime.parse(json["birthdate"]), + esigPath: json["esig_path"], + lastName: json["last_name"], + weightKg: json["weight_kg"] == null + ? null + : double.parse(json["weight_kg"].toString()), + bloodType: json["blood_type"], + firstName: json["first_name"], + photoPath: json["photo_path"], + maidenName: json["maiden_name"] == null + ? null + : MaidenName.fromJson(json['maiden_name']), + middleName: json["middle_name"], + uuidQrcode: json["uuid_qrcode"], + civilStatus: json["civil_status"], + titlePrefix: json["title_prefix"], + titleSuffix: json["title_suffix"], + showTitleId: json["show_title_id"], + nameExtension: json["name_extension"], + ); + + Map toJson() => { + "id": id, + "sex": sex, + "gender": gender, + "deceased": deceased, + "height_m": heightM, + "birthdate": + "${birthdate!.year.toString().padLeft(4, '0')}-${birthdate!.month.toString().padLeft(2, '0')}-${birthdate!.day.toString().padLeft(2, '0')}", + "esig_path": esigPath, + "last_name": lastName, + "weight_kg": weightKg, + "blood_type": bloodType, + "first_name": firstName, + "photo_path": photoPath, + "maiden_name": maidenName, + "middle_name": middleName, + "uuid_qrcode": uuidQrcode, + "civil_status": civilStatus, + "title_prefix": titlePrefix, + "title_suffix": titleSuffix, + "show_title_id": showTitleId, + "name_extension": nameExtension, + }; +} + +class Relationship { + Relationship({ + this.id, + this.type, + this.category, + }); + + final int? id; + final String? type; + final String? category; + + factory Relationship.fromJson(Map json) => Relationship( + id: json["id"], + type: json["type"], + category: json["category"], + ); + + Map toJson() => { + "id": id, + "type": type, + "category": category, + }; +} + +class MaidenName { + final String? lastName; + final String? middleName; + + MaidenName({ + required this.lastName, + required this.middleName, + }); + + factory MaidenName.fromJson(Map json) => MaidenName( + lastName: json["last_name"], + middleName: json["middle_name"], + ); + + Map toJson() => { + "last_name": lastName, + "middle_name": middleName, + }; +} diff --git a/lib/model/profile/learning_development.dart b/lib/model/profile/learning_development.dart new file mode 100644 index 0000000..58fa2ed --- /dev/null +++ b/lib/model/profile/learning_development.dart @@ -0,0 +1,183 @@ +// To parse this JSON data, do +// +// final learningDevelopement = learningDevelopementFromJson(jsonString); + +import 'dart:convert'; + +import 'package:unit2/model/location/barangay.dart'; + +import '../location/city.dart'; +import '../location/country.dart'; +import '../utils/agency.dart'; +import '../utils/industry_class.dart'; +import 'attachment.dart'; + +LearningDevelopement learningDevelopementFromJson(String str) => LearningDevelopement.fromJson(json.decode(str)); + +String learningDevelopementToJson(LearningDevelopement data) => json.encode(data.toJson()); + +class LearningDevelopement { + LearningDevelopement({ + this.attachments, + this.sponsoredBy, + this.conductedTraining, + this.totalHoursAttended, + }); + + List? attachments; + final Agency? sponsoredBy; + final ConductedTraining? conductedTraining; + final double? totalHoursAttended; + + factory LearningDevelopement.fromJson(Map json) => LearningDevelopement( + attachments: json['attachments'] ==null?null: List.from(json["attachments"].map((x) => Attachment.fromJson(x))), + sponsoredBy: json["sponsored_by"] == null ? null : Agency.fromJson(json["sponsored_by"]), + conductedTraining: json["conducted_training"] == null ? null : ConductedTraining.fromJson(json["conducted_training"]), + totalHoursAttended: json["total_hours_attended"], + ); + + Map toJson() => { + "attachments": attachments, + "sponsored_by": sponsoredBy?.toJson(), + "conducted_training": conductedTraining?.toJson(), + "total_hours_attended": totalHoursAttended, + }; +} + +class ConductedTraining { + ConductedTraining({ + this.id, + this.title, + this.topic, + this.venue, + this.locked, + this.toDate, + this.fromDate, + this.totalHours, + this.conductedBy, + this.sessionsAttended, + this.learningDevelopmentType, + }); + + final int? id; + final LearningDevelopmentType? title; + final LearningDevelopmentType? topic; + final Venue? venue; + final bool? locked; + final DateTime? toDate; + final DateTime? fromDate; + final double? totalHours; + final Agency? conductedBy; + final List? sessionsAttended; + final LearningDevelopmentType? learningDevelopmentType; + + factory ConductedTraining.fromJson(Map json) => ConductedTraining( + id: json["id"], + title: json["title"] == null ? null : LearningDevelopmentType.fromJson(json["title"]), + topic: json["topic"] == null ? null : LearningDevelopmentType.fromJson(json["topic"]), + venue: json["venue"] == null ? null : Venue.fromJson(json["venue"]), + locked: json["locked"], + toDate: json["to_date"] == null ? null : DateTime.parse(json["to_date"]), + fromDate: json["from_date"] == null ? null : DateTime.parse(json["from_date"]), + totalHours: double.parse(json["total_hours"].toString()), + conductedBy: json["conducted_by"] == null ? null : Agency.fromJson(json["conducted_by"]), + sessionsAttended: json["sessions_attended"] == null ? [] : List.from(json["sessions_attended"]!.map((x) => x)), + learningDevelopmentType: json["learning_development_type"] == null ? null : LearningDevelopmentType.fromJson(json["learning_development_type"]), + ); + + Map toJson() => { + "id": id, + "title": title?.toJson(), + "topic": topic?.toJson(), + "venue": venue?.toJson(), + "locked": locked, + "to_date": "${toDate!.year.toString().padLeft(4, '0')}-${toDate!.month.toString().padLeft(2, '0')}-${toDate!.day.toString().padLeft(2, '0')}", + "from_date": "${fromDate!.year.toString().padLeft(4, '0')}-${fromDate!.month.toString().padLeft(2, '0')}-${fromDate!.day.toString().padLeft(2, '0')}", + "total_hours": totalHours, + "conducted_by": conductedBy?.toJson(), + "sessions_attended": sessionsAttended == null ? [] : List.from(sessionsAttended!.map((x) => x)), + "learning_development_type": learningDevelopmentType?.toJson(), + }; +} + + +class LearningDevelopmentType { + LearningDevelopmentType({ + this.id, + this.title, + }); + + final int? id; + final String? title; + + factory LearningDevelopmentType.fromJson(Map json) => LearningDevelopmentType( + id: json["id"], + title: json["title"], + ); + + Map toJson() => { + "id": id, + "title": title, + }; +} + +class Venue { + Venue({ + this.id, + this.country, + this.barangay, + this.category, + this.areaClass, + this.cityMunicipality, + }); + + final int? id; + final Country? country; + final Barangay? barangay; + final VenueCategory? category; + final dynamic areaClass; + final CityMunicipality? cityMunicipality; + + factory Venue.fromJson(Map json) => Venue( + id: json["id"], + country: json["country"] == null ? null : Country.fromJson(json["country"]), + barangay:json["barangay"] == null ? null : Barangay.fromJson(json["country"]), + category: json["category"] == null ? null : VenueCategory.fromJson(json["category"]), + areaClass: json["area_class"], + cityMunicipality: json["city_municipality"] == null ? null : CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "country": country?.toJson(), + "barangay": barangay, + "category": category?.toJson(), + "area_class": areaClass, + "city_municipality": cityMunicipality?.toJson(), + }; +} + +class VenueCategory { + VenueCategory({ + this.id, + this.name, + this.type, + }); + + final int? id; + final String? name; + final String? type; + + factory VenueCategory.fromJson(Map json) => VenueCategory( + id: json["id"], + name: json["name"], + type: json["type"], + ); + + Map toJson() => { + "id": id, + "name": name, + "type": type, + }; +} + diff --git a/lib/model/profile/other_information/non_acedimic_recognition.dart b/lib/model/profile/other_information/non_acedimic_recognition.dart new file mode 100644 index 0000000..7d277e0 --- /dev/null +++ b/lib/model/profile/other_information/non_acedimic_recognition.dart @@ -0,0 +1,37 @@ +// To parse this JSON data, do +// +// final nonAcademicRecognition = nonAcademicRecognitionFromJson(jsonString); + +import 'dart:convert'; + +import 'package:unit2/model/utils/agency.dart'; + +NonAcademicRecognition nonAcademicRecognitionFromJson(String str) => NonAcademicRecognition.fromJson(json.decode(str)); + +String nonAcademicRecognitionToJson(NonAcademicRecognition data) => json.encode(data.toJson()); + +class NonAcademicRecognition { + NonAcademicRecognition({ + this.id, + this.title, + this.presenter, + }); + + final int? id; + final String? title; + final Agency? presenter; + + factory NonAcademicRecognition.fromJson(Map json) => NonAcademicRecognition( + id: json["id"], + title: json["title"], + presenter: json["presenter"] == null ? null : Agency.fromJson(json["presenter"]), + ); + + Map toJson() => { + "id": id, + "title": title, + "presenter": presenter?.toJson(), + }; +} + + diff --git a/lib/model/profile/other_information/organization_memberships.dart b/lib/model/profile/other_information/organization_memberships.dart new file mode 100644 index 0000000..9d690a4 --- /dev/null +++ b/lib/model/profile/other_information/organization_memberships.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final organizationMembership = organizationMembershipFromJson(jsonString); + +import 'dart:convert'; + +import '../../utils/agency.dart'; + +OrganizationMembership organizationMembershipFromJson(String str) => OrganizationMembership.fromJson(json.decode(str)); + +String organizationMembershipToJson(OrganizationMembership data) => json.encode(data.toJson()); + +class OrganizationMembership { + OrganizationMembership({ + this.agency, + }); + + final Agency? agency; + + factory OrganizationMembership.fromJson(Map json) => OrganizationMembership( + agency: json["agency"] == null ? null : Agency.fromJson(json["agency"]), + ); + + Map toJson() => { + "agency": agency?.toJson(), + }; +} + + diff --git a/lib/model/profile/other_information/skills_and_hobbies.dart b/lib/model/profile/other_information/skills_and_hobbies.dart new file mode 100644 index 0000000..4d7cff3 --- /dev/null +++ b/lib/model/profile/other_information/skills_and_hobbies.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final skillsHobbies = skillsHobbiesFromJson(jsonString); + +import 'dart:convert'; + +SkillsHobbies skillsHobbiesFromJson(String str) => SkillsHobbies.fromJson(json.decode(str)); + +String skillsHobbiesToJson(SkillsHobbies data) => json.encode(data.toJson()); + +class SkillsHobbies { + SkillsHobbies({ + this.id, + this.name, + }); + + final int? id; + final String? name; + + factory SkillsHobbies.fromJson(Map json) => SkillsHobbies( + id: json["id"], + name: json["name"], + ); + + Map toJson() => { + "id": id, + "name": name, + }; +} diff --git a/lib/model/profile/profileInfomation.dart b/lib/model/profile/profileInfomation.dart new file mode 100644 index 0000000..53fc065 --- /dev/null +++ b/lib/model/profile/profileInfomation.dart @@ -0,0 +1,22 @@ +import 'package:unit2/model/profile/basic_info.dart'; +import 'package:unit2/model/profile/basic_information/primary-information.dart'; +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/model/profile/eligibility.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import 'package:unit2/model/profile/learning_development.dart'; +import 'package:unit2/model/profile/references.dart'; +import 'package:unit2/model/profile/voluntary_works.dart'; +import 'package:unit2/model/profile/work_history.dart'; + +class ProfileInformation{ + final BasicInfo basicInfo; + // OtherInformation otherInformation; + // List eligibilities; + // List references; + // List learningsAndDevelopment; + // List educationalBackgrounds; + // List families; + // ListworkExperiences; + // List voluntaryWorks; + ProfileInformation({required this.basicInfo}); +} \ No newline at end of file diff --git a/lib/model/profile/references.dart b/lib/model/profile/references.dart new file mode 100644 index 0000000..d7e1e05 --- /dev/null +++ b/lib/model/profile/references.dart @@ -0,0 +1,84 @@ +// To parse this JSON data, do +// +// final references = referencesFromJson(jsonString); +import '../location/address_category.dart'; +import '../location/barangay.dart'; +import '../location/city.dart'; +import '../location/country.dart'; +import '../location/provinces.dart'; + +class PersonalReference { + PersonalReference({ + required this.id, + required this.address, + required this.lastName, + required this.contactNo, + required this.firstName, + required this.middleName, + }); + + final int? id; + final Address? address; + final String? lastName; + final String? contactNo; + final String? firstName; + final String? middleName; + + factory PersonalReference.fromJson(Map json) => PersonalReference( + id: json["id"], + address: json['address'] == null?null: Address.fromJson(json["address"]), + lastName: json["last_name"], + contactNo: json["contact_no"], + firstName: json["first_name"], + middleName: json["middle_name"], + ); + + Map toJson() => { + "id": id, + "address": address!.toJson(), + "last_name": lastName, + "contact_no": contactNo, + "first_name": firstName, + "middle_name": middleName, + }; +} + +class Address { + Address({ + required this.id, + required this.addressClass, + required this.country, + required this.barangay, + required this.addressCategory, + required this.cityMunicipality, + }); + + final int? id; + final String? addressClass; + final Country? country; + final Barangay? barangay; + final AddressCategory? addressCategory; + final CityMunicipality? cityMunicipality; + + factory Address.fromJson(Map json) => Address( + id: json["id"], + addressClass: json["class"], + country: json['country']== null?null: Country.fromJson(json["country"]), + barangay:json["barangay"]== null?null: Barangay.fromJson(json["barangay"]), + addressCategory: json["address_category"]== null? null: AddressCategory.fromJson(json["address_category"]), + cityMunicipality: json["city_municipality"]==null?null: CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "class": addressClass, + "country": country!.toJson(), + "barangay": barangay!.toJson(), + "address_category": addressCategory!.toJson(), + "city_municipality": cityMunicipality!.toJson(), + }; +} + + + + diff --git a/lib/model/profile/voluntary_works.dart b/lib/model/profile/voluntary_works.dart new file mode 100644 index 0000000..491c776 --- /dev/null +++ b/lib/model/profile/voluntary_works.dart @@ -0,0 +1,95 @@ +// To parse this JSON data, do +// +// final voluntaryWork = voluntaryWorkFromJson(jsonString); + +import 'dart:convert'; + +import '../location/address_category.dart'; +import '../location/city.dart'; +import '../location/country.dart'; +import '../utils/agency.dart'; +import '../utils/position.dart'; + +VoluntaryWork voluntaryWorkFromJson(String str) => VoluntaryWork.fromJson(json.decode(str)); + +String voluntaryWorkToJson(VoluntaryWork data) => json.encode(data.toJson()); + +class VoluntaryWork { + VoluntaryWork({ + this.agency, + this.address, + this.toDate, + this.position, + this.fromDate, + this.totalHours, + }); + + final Agency? agency; + final Address? address; + final DateTime? toDate; + final PositionTitle? position; + final DateTime? fromDate; + final double? totalHours; + + factory VoluntaryWork.fromJson(Map json) => VoluntaryWork( + agency: json["agency"] == null ? null : Agency.fromJson(json["agency"]), + address: json["address"] == null ? null : Address.fromJson(json["address"]), + toDate: json["to_date"] == null? null : DateTime.parse(json['to_date']), + position: json["position"] == null ? null : PositionTitle.fromJson(json["position"]), + fromDate: json["from_date"] == null ? null : DateTime.parse(json["from_date"]), + totalHours: json["total_hours"], + ); + + Map toJson() => { + "agency": agency?.toJson(), + "address": address?.toJson(), + "to_date": toDate, + "position": position?.toJson(), + "from_date": "${fromDate!.year.toString().padLeft(4, '0')}-${fromDate!.month.toString().padLeft(2, '0')}-${fromDate!.day.toString().padLeft(2, '0')}", + "total_hours": totalHours, + }; +} + +class Address { + Address({ + this.id, + this.addressClass, + this.country, + this.barangay, + this.addressCategory, + this.cityMunicipality, + }); + + final int? id; + final dynamic addressClass; + final Country? country; + final dynamic barangay; + final AddressCategory? addressCategory; + final CityMunicipality? cityMunicipality; + + factory Address.fromJson(Map json) => Address( + id: json["id"], + addressClass: json["class"], + country: json["country"] == null ? null : Country.fromJson(json["country"]), + barangay: json["barangay"], + addressCategory: json["address_category"] == null ? null : AddressCategory.fromJson(json["address_category"]), + cityMunicipality: json["city_municipality"] == null ? null : CityMunicipality.fromJson(json["city_municipality"]), + ); + + Map toJson() => { + "id": id, + "class": addressClass, + "country": country?.toJson(), + "barangay": barangay, + "address_category": addressCategory?.toJson(), + "city_municipality": cityMunicipality?.toJson(), + }; +} + + + + + + + + diff --git a/lib/model/profile/work_history.dart b/lib/model/profile/work_history.dart new file mode 100644 index 0000000..538e6f4 --- /dev/null +++ b/lib/model/profile/work_history.dart @@ -0,0 +1,163 @@ +import 'package:unit2/model/utils/industry_class.dart'; + +import '../utils/agency.dart'; +import '../utils/position.dart'; + +class WorkHistory { + final PositionTitle? position; + final Agency? agency; + final Supervisor? supervisor; + final int? id; + final DateTime? fromDate; + final DateTime? toDate; + final int? agencydepid; + final double? monthlysalary; + final String? statusAppointment; + final int? salarygrade; + final int? sgstep; + final List? accomplishment; + final List? actualDuties; + + WorkHistory({ + required this.position, + required this.agency, + required this.supervisor, + required this.id, + required this.fromDate, + required this.toDate, + required this.agencydepid, + required this.monthlysalary, + required this.statusAppointment, + required this.salarygrade, + required this.sgstep, + required this.accomplishment, + required this.actualDuties, + }); + + factory WorkHistory.fromJson(Map json) => WorkHistory( + position: PositionTitle.fromJson(json["position"]), + agency: json['agency'] == null?null: Agency.fromJson(json["agency"]), + supervisor: json['supervisor'] == null?null: Supervisor.fromJson(json["supervisor"]), + id: json["id"], + fromDate: json['from_date'] == null?null: DateTime.tryParse(json["from_date"]), + toDate: json['to_date'] == null?null: DateTime.tryParse(json["to_date"]), + agencydepid: json["agencydepid"], + monthlysalary: json["monthlysalary"], + statusAppointment: json["status_appointment"], + salarygrade: json["salarygrade"], + sgstep: json["sgstep"], + accomplishment:json['accomplishment'] == null?null: json['accomplishment'] == null?null: List.from( + json["accomplishment"].map((x) => Accomplishment.fromJson(x))), + actualDuties: json['actual_duties'] == null?null: List.from( + json["actual_duties"].map((x) => ActualDuty.fromJson(x))), + ); + + Map toJson() => { + "position": position?.toJson(), + "agency": agency?.toJson(), + "supervisor": supervisor?.toJson(), + "id": id, + "from_date": + "${fromDate?.year.toString().padLeft(4, '0')}-${fromDate?.month.toString().padLeft(2, '0')}-${fromDate?.day.toString().padLeft(2, '0')}", + "to_date": toDate, + "agencydepid": agencydepid, + "monthlysalary": monthlysalary, + "status_appointment": statusAppointment, + "salarygrade": salarygrade, + "sgstep": sgstep, + "accomplishment": + List.from(accomplishment!.map((x) => x.toJson())), + "actual_duties": + List.from(actualDuties!.map((x) => x.toJson())), + }; +} + +class Accomplishment { + final int? id; + final int? workExperienceId; + final String? accomplishment; + + Accomplishment({ + required this.id, + required this.workExperienceId, + required this.accomplishment, + }); + + factory Accomplishment.fromJson(Map json) => Accomplishment( + id: json["id"], + workExperienceId: json["work_experience_id"], + accomplishment: json["accomplishment"], + ); + + Map toJson() => { + "id": id, + "work_experience_id": workExperienceId, + "accomplishment": accomplishment, + }; +} + +class ActualDuty { + final int? id; + final int? workExperienceId; + final String description; + + ActualDuty({ + required this.id, + required this.workExperienceId, + required this.description, + }); + + factory ActualDuty.fromJson(Map json) => ActualDuty( + id: json["id"], + workExperienceId: json["work_experience_id"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "work_experience_id": workExperienceId, + "description": description, + }; +} + + + +class Supervisor { + final int? id; + final int? agencyId; + final String? lastname; + final String? firstname; + final String? middlename; + final String? stationName; + + Supervisor({ + required this.id, + required this.agencyId, + required this.lastname, + required this.firstname, + required this.middlename, + required this.stationName, + }); + + factory Supervisor.fromJson(Map json) => Supervisor( + id: json["id"], + agencyId: json["agency_id"], + lastname: json["lastname"], + firstname: json["firstname"], + middlename: json["middlename"], + stationName: json["station_name"], + ); + + Map toJson() => { + "id": id, + "agency_id": agencyId, + "lastname": lastname, + "firstname": firstname, + "middlename": middlename, + "station_name": stationName, + }; +} + + + + diff --git a/lib/model/rbac/assigned_role.dart b/lib/model/rbac/assigned_role.dart new file mode 100644 index 0000000..52a1b78 --- /dev/null +++ b/lib/model/rbac/assigned_role.dart @@ -0,0 +1,130 @@ +// To parse this JSON data, do +// +// final assignedRole = assignedRoleFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +AssignedRole assignedRoleFromJson(String str) => AssignedRole.fromJson(json.decode(str)); + +String assignedRoleToJson(AssignedRole data) => json.encode(data.toJson()); + +class AssignedRole { + final int? id; + final Role? role; + final CreatedBy? user; + final DateTime? createdAt; + final DateTime? updatedAt; + final CreatedBy? createdBy; + final CreatedBy? updatedBy; + + AssignedRole({ + required this.id, + required this.role, + required this.user, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory AssignedRole.fromJson(Map json) => AssignedRole( + id: json["id"], + role: json['role'] == null?null: Role.fromJson(json["role"]), + user: json['role'] == null?null: CreatedBy.fromJson(json["user"]), + createdAt:json["created_at"] == null?null: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"] == null?null: DateTime.parse(json["updated_at"]), + createdBy: json["created_by"] == null? null: CreatedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"] == null? null: CreatedBy.fromJson(json["updated_by"]), + ); + + Map toJson() => { + "id": id, + "role": role?.toJson(), + "user": user?.toJson(), + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt?.toIso8601String(), + "created_by": createdBy?.toJson(), + "updated_by": updatedBy?.toJson(), + }; +} + +class CreatedBy { + final int id; + final String username; + final String firstName; + final String lastName; + final String email; + final bool isActive; + + CreatedBy({ + required this.id, + required this.username, + required this.firstName, + required this.lastName, + required this.email, + required this.isActive, + }); + + factory CreatedBy.fromJson(Map json) => CreatedBy( + id: json["id"], + username: json["username"], + firstName: json["first_name"], + lastName: json["last_name"], + email: json["email"], + isActive: json["is_active"], + ); + + Map toJson() => { + "id": id, + "username": username, + "first_name": firstName, + "last_name": lastName, + "email": email, + "is_active": isActive, + }; +} + +class Role { + final int id; + final String name; + final String slug; + final String shorthand; + final DateTime createdAt; + final DateTime updatedAt; + final CreatedBy createdBy; + final CreatedBy updatedBy; + + Role({ + required this.id, + required this.name, + required this.slug, + required this.shorthand, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory Role.fromJson(Map json) => Role( + id: json["id"], + name: json["name"], + slug: json["slug"], + shorthand: json["shorthand"], + createdAt: DateTime.parse(json["created_at"]), + updatedAt: DateTime.parse(json["updated_at"]), + createdBy: CreatedBy.fromJson(json["created_by"]), + updatedBy: CreatedBy.fromJson(json["updated_by"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "shorthand": shorthand, + "created_at": createdAt.toIso8601String(), + "updated_at": updatedAt.toIso8601String(), + "created_by": createdBy.toJson(), + "updated_by": updatedBy.toJson(), + }; +} diff --git a/lib/model/rbac/new_permission.dart b/lib/model/rbac/new_permission.dart new file mode 100644 index 0000000..8c84b49 --- /dev/null +++ b/lib/model/rbac/new_permission.dart @@ -0,0 +1,70 @@ +// To parse this JSON data, do +// +// final newPermission = newPermissionFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +NewPermission newPermissionFromJson(String str) => NewPermission.fromJson(json.decode(str)); + +String newPermissionToJson(NewPermission data) => json.encode(data.toJson()); + +class NewPermission { + final int? newPermissionObjectId; + final String? newObjectName; + final String? newObjectSlug; + final String? newObjectShorthand; + final List newPermissionOperationIds; + final List newOperations; + + NewPermission({ + required this.newPermissionObjectId, + required this.newObjectName, + required this.newObjectSlug, + required this.newObjectShorthand, + required this.newPermissionOperationIds, + required this.newOperations, + }); + + factory NewPermission.fromJson(Map json) => NewPermission( + newPermissionObjectId: json["_new_permission_object_id"], + newObjectName: json["_new_object_name"], + newObjectSlug: json["_new_object_slug"], + newObjectShorthand: json["_new_object_shorthand"], + newPermissionOperationIds: List.from(json["_new_permission_operation_ids"].map((x) => x)), + newOperations: List.from(json["_new_operations"].map((x) => NewOperation.fromJson(x))), + ); + + Map toJson() => { + "_new_permission_object_id": newPermissionObjectId, + "_new_object_name": newObjectName, + "_new_object_slug": newObjectSlug, + "_new_object_shorthand": newObjectShorthand, + "_new_permission_operation_ids": List.from(newPermissionOperationIds.map((x) => x)), + "_new_operations": List.from(newOperations.map((x) => x.toJson())), + }; +} + +class NewOperation { + final String newOperationName; + final String newOperationSlug; + final String newOperationShorthand; + + NewOperation({ + required this.newOperationName, + required this.newOperationSlug, + required this.newOperationShorthand, + }); + + factory NewOperation.fromJson(Map json) => NewOperation( + newOperationName: json["_new_operation_name"], + newOperationSlug: json["_new_operation_slug"], + newOperationShorthand: json["_new_operation_shorthand"], + ); + + Map toJson() => { + "_new_operation_name": newOperationName, + "_new_operation_slug": newOperationSlug, + "_new_operation_shorthand": newOperationShorthand, + }; +} diff --git a/lib/model/rbac/permission.dart b/lib/model/rbac/permission.dart new file mode 100644 index 0000000..dd2c2e3 --- /dev/null +++ b/lib/model/rbac/permission.dart @@ -0,0 +1,79 @@ +import 'package:unit2/model/rbac/rbac.dart'; + +class RBACPermission { + final int? id; + final RBAC? object; + final RBAC? operation; + final DateTime? createdAt; + final dynamic updatedAt; + final CreatedBy? createdBy; + final dynamic updatedBy; + + RBACPermission({ + required this.id, + required this.object, + required this.operation, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory RBACPermission.fromJson(Map json) => RBACPermission( + id: json["id"], + object: json['object'] == null?null:RBAC.fromJson(json["object"]), + operation: json['operation'] == null?null: RBAC.fromJson(json["operation"]), + createdAt: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"], + createdBy: CreatedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"], + ); + + Map toJson() => { + "id": id, + "object": object?.toJson(), + "operation": operation?.toJson(), + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt, + "created_by": createdBy?.toJson(), + "updated_by": updatedBy, + }; +} + +class CreatedBy { + final int id; + final String username; + final String firstName; + final String lastName; + final String email; + final bool isActive; + + CreatedBy({ + required this.id, + required this.username, + required this.firstName, + required this.lastName, + required this.email, + required this.isActive, + }); + + factory CreatedBy.fromJson(Map json) => CreatedBy( + id: json["id"], + username: json["username"], + firstName: json["first_name"], + lastName: json["last_name"], + email: json["email"], + isActive: json["is_active"], + ); + + Map toJson() => { + "id": id, + "username": username, + "first_name": firstName, + "last_name": lastName, + "email": email, + "is_active": isActive, + }; +} + + diff --git a/lib/model/rbac/rbac.dart b/lib/model/rbac/rbac.dart new file mode 100644 index 0000000..5f83962 --- /dev/null +++ b/lib/model/rbac/rbac.dart @@ -0,0 +1,94 @@ +// To parse this JSON data, do +// +// final rbac = rbacFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +RBAC rbacFromJson(String str) => RBAC.fromJson(json.decode(str)); + +String rbacToJson(RBAC data) => json.encode(data.toJson()); + +class RBAC { + int? id; + final String? name; + final String? slug; + final String? shorthand; + final String? fontawesomeIcon; + final DateTime? createdAt; + final dynamic updatedAt; + final CreatedBy? createdBy; + final dynamic updatedBy; + + RBAC({ + required this.id, + required this.name, + required this.slug, + required this.shorthand, + required this.fontawesomeIcon, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory RBAC.fromJson(Map json) => RBAC( + id: json["id"], + name: json["name"], + slug: json["slug"], + shorthand: json["shorthand"], + fontawesomeIcon: json["fontawesome_icon"], + createdAt: json['created_at'] == null?null: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"], + createdBy: json['created_by']==null?null: CreatedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"], + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "shorthand": shorthand, + "fontawesome_icon": fontawesomeIcon, + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt, + "created_by": createdBy?.toJson(), + "updated_by": updatedBy, + }; +} + +class CreatedBy { + final int id; + final String username; + final String firstName; + final String lastName; + final String email; + final bool isActive; + + CreatedBy({ + required this.id, + required this.username, + required this.firstName, + required this.lastName, + required this.email, + required this.isActive, + }); + + factory CreatedBy.fromJson(Map json) => CreatedBy( + id: json["id"], + username: json["username"], + firstName: json["first_name"], + lastName: json["last_name"], + email: json["email"], + isActive: json["is_active"], + ); + + Map toJson() => { + "id": id, + "username": username, + "first_name": firstName, + "last_name": lastName, + "email": email, + "is_active": isActive, + }; +} diff --git a/lib/model/rbac/rbac_rbac.dart b/lib/model/rbac/rbac_rbac.dart new file mode 100644 index 0000000..ec5bc5f --- /dev/null +++ b/lib/model/rbac/rbac_rbac.dart @@ -0,0 +1,122 @@ +class ModuleObjects { + final int id; + final Module object; + final Module module; + final DateTime? createdAt; + final dynamic updatedAt; + final AtedBy createdBy; + final dynamic updatedBy; + + ModuleObjects({ + required this.id, + required this.object, + required this.module, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory ModuleObjects.fromJson(Map json) => ModuleObjects( + id:json['id'], + object: Module.fromJson(json["object"]), + module: Module.fromJson(json["module"]), + createdAt: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"], + createdBy: AtedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"], + ); + + Map toJson() => { + "object": object.toJson(), + "module": module.toJson(), + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt, + "created_by": createdBy.toJson(), + "updated_by": updatedBy, + }; +} + +class AtedBy { + final int id; + final String username; + final String firstName; + final String lastName; + final String email; + final bool isActive; + + AtedBy({ + required this.id, + required this.username, + required this.firstName, + required this.lastName, + required this.email, + required this.isActive, + }); + + factory AtedBy.fromJson(Map json) => AtedBy( + id: json["id"], + username: json["username"], + firstName: json["first_name"], + lastName: json["last_name"], + email: json["email"], + isActive: json["is_active"], + ); + + Map toJson() => { + "id": id, + "username": username, + "first_name": firstName, + "last_name": lastName, + "email": email, + "is_active": isActive, + }; +} + +class Module { + final int id; + final String? name; + final String? slug; + final String? shorthand; + final String? fontawesomeIcon; + final DateTime? createdAt; + final DateTime? updatedAt; + final AtedBy? createdBy; + final AtedBy? updatedBy; + + Module({ + required this.id, + required this.name, + required this.slug, + required this.shorthand, + required this.fontawesomeIcon, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory Module.fromJson(Map json) => Module( + id: json["id"], + name: json["name"], + slug: json["slug"], + shorthand: json["shorthand"], + fontawesomeIcon: json['fontawesome_icon'] == null?null: json["fontawesome_icon"], + createdAt:json["created_at"] == null? null: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"] == null? null: DateTime.parse(json["updated_at"]), + createdBy: json["created_by"] == null? null:AtedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"] == null? null:AtedBy.fromJson(json["updated_by"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "shorthand": shorthand, + "fontawesome_icon": fontawesomeIcon, + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt?.toIso8601String(), + "created_by": createdBy?.toJson(), + "updated_by": updatedBy?.toJson(), + }; +} diff --git a/lib/model/rbac/rbac_station.dart b/lib/model/rbac/rbac_station.dart new file mode 100644 index 0000000..9fa9272 --- /dev/null +++ b/lib/model/rbac/rbac_station.dart @@ -0,0 +1,149 @@ +// To parse this JSON data, do +// +// final assignArea = assignAreaFromJson(jsonString); + + + +import 'package:unit2/model/rbac/station_type.dart'; +import 'package:unit2/model/roles/pass_check/station_assign_area.dart'; + +class RbacStation { + final int? id; + final String? stationName; + final StationType? stationType; + final int? hierarchyOrderNo; + final String? headPosition; + final GovernmentAgency? governmentAgency; + final String? acronym; + final int? parentStation; + final String? code; + final String? fullcode; + final List? childStationInfo; + final bool? islocationUnderParent; + final int? mainParentStation; + final String? description; + final bool? ishospital; + final bool? isactive; + final bool? sellingStation; + + RbacStation({ + required this.id, + required this.stationName, + required this.stationType, + required this.hierarchyOrderNo, + required this.headPosition, + required this.governmentAgency, + required this.acronym, + required this.parentStation, + required this.code, + required this.fullcode, + required this.childStationInfo, + required this.islocationUnderParent, + required this.mainParentStation, + required this.description, + required this.ishospital, + required this.isactive, + required this.sellingStation, + }); + + factory RbacStation.fromJson(Map json) => RbacStation( + id: json["id"], + stationName: json["station_name"], + stationType:json["station_type"] ==null?null: StationType.fromJson(json["station_type"]), + hierarchyOrderNo: json["hierarchy_order_no"], + headPosition: json["head_position"], + governmentAgency: json["government_agency"] == null?null:GovernmentAgency.fromJson(json["government_agency"]), + acronym: json["acronym"], + parentStation: json["parent_station"], + code: json["code"], + fullcode: json["fullcode"], + childStationInfo: null, + islocationUnderParent: json["islocation_under_parent"], + mainParentStation: json["main_parent_station"], + description: json["description"], + ishospital: json["ishospital"], + isactive: json["isactive"], + sellingStation: json["selling_station"], + ); + + Map toJson() => { + "id": id, + "station_name": stationName, + "station_type": stationType?.toJson(), + "hierarchy_order_no": hierarchyOrderNo, + "head_position": headPosition, + "government_agency": governmentAgency?.toJson(), + "acronym": acronym, + "parent_station": parentStation, + "code": code, + "fullcode": fullcode, + "child_station_info": List.from(childStationInfo!.map((x) => x.toJson())), + "islocation_under_parent": islocationUnderParent, + "main_parent_station": mainParentStation, + "description": description, + "ishospital": ishospital, + "isactive": isactive, + "selling_station": sellingStation, + }; +} + +class ChildStationInfo { + final int? id; + final String? stationName; + final String? acroym; + bool? motherStation; + + ChildStationInfo({ + required this.id, + required this.stationName, + required this.acroym, + this.motherStation + }); + + factory ChildStationInfo.fromJson(Map json) => ChildStationInfo( + id: json["id"], + stationName: json["station_name"], + acroym: json["acroym"], + + ); + + Map toJson() => { + "id": id, + "station_name": stationName, + "acroym": acroym, + }; +} + +class GovernmentAgency { + final int? agencyid; + final String? agencyname; + final int? agencycatid; + final bool? privateEntity; + final int? contactinfoid; + + GovernmentAgency({ + required this.agencyid, + required this.agencyname, + required this.agencycatid, + required this.privateEntity, + required this.contactinfoid, + }); + + factory GovernmentAgency.fromJson(Map json) => GovernmentAgency( + agencyid: json["agencyid"], + agencyname: json["agencyname"], + agencycatid: json["agencycatid"], + privateEntity: json["private_entity"], + contactinfoid: json["contactinfoid"], + ); + + Map toJson() => { + "agencyid": agencyid, + "agencyname": agencyname, + "agencycatid": agencycatid, + "private_entity": privateEntity, + "contactinfoid": contactinfoid, + }; +} + + diff --git a/lib/model/rbac/role_extend.dart b/lib/model/rbac/role_extend.dart new file mode 100644 index 0000000..acd95fb --- /dev/null +++ b/lib/model/rbac/role_extend.dart @@ -0,0 +1,37 @@ +// To parse this JSON data, do +// +// final rolesExtend = rolesExtendFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; + +RolesExtend rolesExtendFromJson(String str) => RolesExtend.fromJson(json.decode(str)); + +String rolesExtendToJson(RolesExtend data) => json.encode(data.toJson()); + +class RolesExtend { + final int id; + final RBAC roleExtendMain; + final RBAC roleExtendChild; + + RolesExtend({ + required this.id, + required this.roleExtendMain, + required this.roleExtendChild, + }); + + factory RolesExtend.fromJson(Map json) => RolesExtend( + id: json["id"], + roleExtendMain: RBAC.fromJson(json["role_extend_main"]), + roleExtendChild: RBAC.fromJson(json["role_extend_child"]), + ); + + Map toJson() => { + "id": id, + "role_extend_main": roleExtendMain.toJson(), + "role_extend_child": roleExtendChild.toJson(), + }; +} + diff --git a/lib/model/rbac/role_module.dart b/lib/model/rbac/role_module.dart new file mode 100644 index 0000000..295f1cf --- /dev/null +++ b/lib/model/rbac/role_module.dart @@ -0,0 +1,124 @@ + +class RoleModules { + final int? id; + final Module? role; + final Module? module; + final DateTime? createdAt; + final dynamic updatedAt; + final AtedBy? createdBy; + final dynamic updatedBy; + + RoleModules({ + required this.id, + required this.role, + required this.module, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory RoleModules.fromJson(Map json) => RoleModules( + id: json["id"], + role:json['role'] == null?null: Module.fromJson(json["role"]), + module: json['module'] == null?null:Module.fromJson(json["module"]), + createdAt: json["created_at"] == null? null: DateTime.parse(json["created_at"]), + updatedAt: json["updated_at"], + createdBy: json["created_by"]==null? null: AtedBy.fromJson(json["created_by"]), + updatedBy: json["updated_by"], + ); + + Map toJson() => { + "id": id, + "role": role?.toJson(), + "module": module?.toJson(), + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt, + "created_by": createdBy?.toJson(), + "updated_by": updatedBy, + }; +} + +class AtedBy { + final int id; + final String username; + final String firstName; + final String lastName; + final String email; + final bool isActive; + + AtedBy({ + required this.id, + required this.username, + required this.firstName, + required this.lastName, + required this.email, + required this.isActive, + }); + + factory AtedBy.fromJson(Map json) => AtedBy( + id: json["id"], + username: json["username"], + firstName: json["first_name"], + lastName: json["last_name"], + email: json["email"], + isActive: json["is_active"], + ); + + Map toJson() => { + "id": id, + "username": username, + "first_name": firstName, + "last_name": lastName, + "email": email, + "is_active": isActive, + }; +} + +class Module { + final int? id; + final String? name; + final String? slug; + final String? shorthand; + final String? fontawesomeIcon; + final DateTime? createdAt; + final DateTime? updatedAt; + final AtedBy? createdBy; + final AtedBy? updatedBy; + + Module({ + required this.id, + required this.name, + required this.slug, + required this.shorthand, + required this.fontawesomeIcon, + required this.createdAt, + required this.updatedAt, + required this.createdBy, + required this.updatedBy, + }); + + factory Module.fromJson(Map json) => Module( + id: json["id"], + name: json["name"], + slug: json["slug"], + shorthand: json["shorthand"], + fontawesomeIcon: null, + createdAt:json['created_at'] == null?null: DateTime.parse(json["created_at"]), + updatedAt:json["updated_at"] == null?null: DateTime.parse(json["updated_at"]), + createdBy:json["created_by"] ==null?null: AtedBy.fromJson(json["created_by"]), + updatedBy:json["updated_by"] == null?null: AtedBy.fromJson(json["updated_by"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "slug": slug, + "shorthand": shorthand, + "fontawesome_icon": fontawesomeIcon, + "created_at": createdAt?.toIso8601String(), + "updated_at": updatedAt?.toIso8601String(), + "created_by": createdBy?.toJson(), + "updated_by": updatedBy?.toJson(), + }; +} diff --git a/lib/model/rbac/role_under.dart b/lib/model/rbac/role_under.dart new file mode 100644 index 0000000..dedc7c2 --- /dev/null +++ b/lib/model/rbac/role_under.dart @@ -0,0 +1,37 @@ +// To parse this JSON data, do +// +// final rolesUnder = rolesUnderFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; + +RolesUnder rolesUnderFromJson(String str) => RolesUnder.fromJson(json.decode(str)); + +String rolesUnderToJson(RolesUnder data) => json.encode(data.toJson()); + +class RolesUnder { + final int id; + final RBAC roleUnderMain; + final RBAC roleUnderChild; + + RolesUnder({ + required this.id, + required this.roleUnderMain, + required this.roleUnderChild, + }); + + factory RolesUnder.fromJson(Map json) => RolesUnder( + id: json["id"], + roleUnderMain: RBAC.fromJson(json["role_under_main"]), + roleUnderChild: RBAC.fromJson(json["role_under_child"]), + ); + + Map toJson() => { + "id": id, + "role_under_main": roleUnderMain.toJson(), + "role_under_child": roleUnderChild.toJson(), + }; +} + diff --git a/lib/model/rbac/station_type.dart b/lib/model/rbac/station_type.dart new file mode 100644 index 0000000..6254bd8 --- /dev/null +++ b/lib/model/rbac/station_type.dart @@ -0,0 +1,40 @@ +// To parse this JSON data, do +// +// final rbacStationType = rbacStationTypeFromJson(jsonString); + + +class StationType { + final int? id; + final String? typeName; + final String? color; + final int? order; + final bool? isActive; + final String? group; + + StationType({ + required this.id, + required this.typeName, + required this.color, + required this.order, + required this.isActive, + required this.group, + }); + + factory StationType.fromJson(Map json) => StationType( + id: json["id"], + typeName: json["type_name"], + color: json["color"], + order: json["order"], + isActive: json["is_active"], + group: json["group"], + ); + + Map toJson() => { + "id": id, + "type_name": typeName, + "color": color, + "order": order, + "is_active": isActive, + "group": group, + }; +} diff --git a/lib/model/roles/pass_check/agency_area_type.dart b/lib/model/roles/pass_check/agency_area_type.dart new file mode 100644 index 0000000..cb595cc --- /dev/null +++ b/lib/model/roles/pass_check/agency_area_type.dart @@ -0,0 +1,79 @@ + +import '../../utils/category.dart'; + +class AgencyAssignedArea { + final bool? isactive; + final Area? area; + + AgencyAssignedArea({ + required this.isactive, + required this.area, + }); + + factory AgencyAssignedArea.fromJson(Map json) => AgencyAssignedArea( + isactive: json["isactive"], + area: json["area"] == null? null:Area.fromJson(json["area"]), + ); + + Map toJson() => { + "isactive": isactive, + "area": area?.toJson(), + }; +} + +class Area { + final int? id; + final String? name; + final Category? category; + final bool? privateEntity; + final String? contactInfo; + + Area({ + required this.id, + required this.name, + required this.category, + required this.privateEntity, + required this.contactInfo, + }); + + factory Area.fromJson(Map json) => Area( + id: json["id"], + name: json["name"], + category: json["category"]==null?null:Category.fromJson(json["category"]), + privateEntity: json["private_entity"], + contactInfo: json["contact_info"], + ); + + Map toJson() => { + "id": id, + "name": name, + "category": category?.toJson(), + "private_entity": privateEntity, + "contact_info": contactInfo, + }; +} + + +class IndustryClass { + final int? id; + final String? name; + final String? description; + + IndustryClass({ + required this.id, + required this.name, + required this.description, + }); + + factory IndustryClass.fromJson(Map json) => IndustryClass( + id: json["id"], + name: json["name"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "name": name, + "description": description, + }; +} diff --git a/lib/model/roles/pass_check/assign_role_area_type.dart b/lib/model/roles/pass_check/assign_role_area_type.dart new file mode 100644 index 0000000..3b2df3e --- /dev/null +++ b/lib/model/roles/pass_check/assign_role_area_type.dart @@ -0,0 +1,52 @@ +// To parse this JSON data, do +// +// final assignRoleAreaType = assignRoleAreaTypeFromJson(jsonString); + + +class AssignRoleAreaType { + final String areaTypeName; + final Details details; + + AssignRoleAreaType({ + required this.areaTypeName, + required this.details, + }); + + factory AssignRoleAreaType.fromJson(Map json) => AssignRoleAreaType( + areaTypeName: json["area_type_name"], + details: Details.fromJson(json["details"]), + ); + + Map toJson() => { + "area_type_name": areaTypeName, + "details": details.toJson(), + }; +} + +class Details { + final String? table; + final String? schema; + final String? dataType; + final String? idColumn; + + Details({ + required this.table, + required this.schema, + required this.dataType, + required this.idColumn, + }); + + factory Details.fromJson(Map json) => Details( + table: json["table"], + schema: json["schema"], + dataType: json["data_type"], + idColumn: json["id_column"], + ); + + Map toJson() => { + "table": table, + "schema": schema, + "data_type": dataType, + "id_column": idColumn, + }; +} diff --git a/lib/model/roles/pass_check/barangay_assign_area.dart b/lib/model/roles/pass_check/barangay_assign_area.dart new file mode 100644 index 0000000..f86ddd5 --- /dev/null +++ b/lib/model/roles/pass_check/barangay_assign_area.dart @@ -0,0 +1,24 @@ + +class BaragayAssignArea { + final String? brgycode; + final String? brgydesc; + final String? citymuncode; + + BaragayAssignArea({ + required this.brgycode, + required this.brgydesc, + required this.citymuncode, + }); + + factory BaragayAssignArea.fromJson(Map json) => BaragayAssignArea( + brgycode: json["brgycode"], + brgydesc: json["brgydesc"], + citymuncode: json["citymuncode"], + ); + + Map toJson() => { + "brgycode": brgycode, + "brgydesc": brgydesc, + "citymuncode": citymuncode, + }; +} diff --git a/lib/model/roles/pass_check/passer_info.dart b/lib/model/roles/pass_check/passer_info.dart new file mode 100644 index 0000000..b841783 --- /dev/null +++ b/lib/model/roles/pass_check/passer_info.dart @@ -0,0 +1,120 @@ + +class PasserInfo { + final int personid; + final String familyname; + final String givenname; + final String? middlename; + final String sex; + final DateTime? birthdate; + final String? extension; + final String? civilstatus; + final double? heightM; + final double weightKg; + final String? bloodtype; + final String? photoPath; + final String? uuid; + final String? encryptionKey; + final bool? deceased; + final dynamic encryptedProfile; + final String? addedby; + final DateTime? addedat; + final String? updateby; + final DateTime? updatedat; + final String? deletedby; + final DateTime? deletedat; + final String? encryptSignature; + final String? esigPath; + final String? titlePrefix; + final String? titleSuffix; + final bool? showTitleId; + + PasserInfo({ + required this.personid, + required this.familyname, + required this.givenname, + required this.middlename, + required this.sex, + required this.birthdate, + required this.extension, + required this.civilstatus, + required this.heightM, + required this.weightKg, + required this.bloodtype, + required this.photoPath, + required this.uuid, + required this.encryptionKey, + required this.deceased, + required this.encryptedProfile, + required this.addedby, + required this.addedat, + required this.updateby, + required this.updatedat, + required this.deletedby, + required this.deletedat, + required this.encryptSignature, + required this.esigPath, + required this.titlePrefix, + required this.titleSuffix, + required this.showTitleId, + }); + + factory PasserInfo.fromJson(Map json) => PasserInfo( + personid: json["personid"], + familyname: json["familyname"], + givenname: json["givenname"], + middlename: json["middlename"], + sex: json["sex"], + birthdate: json['birthdate'] == null?null: DateTime.parse(json["birthdate"]), + extension: json["extension"], + civilstatus: json["civilstatus"], + heightM: json["height_m"]?.toDouble(), + weightKg: json["weight_kg"]?.toDouble(), + bloodtype: json["bloodtype"], + photoPath: json["photo_path"], + uuid: json["uuid"], + encryptionKey: json["encryption_key"], + deceased: json["deceased"], + encryptedProfile: json["encrypted_profile"], + addedby: json["addedby"], + addedat: json["addedat"] == null? null:DateTime.tryParse(json["addedat"]), + updateby:json["updateby"], + updatedat:json["updatedat"]==null?null: DateTime.tryParse(json["updatedat"]), + deletedby: json["deletedby"], + deletedat: json['deletedat'] == null?null:DateTime.tryParse(json["deletedat"]), + encryptSignature: json["encrypt_signature"], + esigPath: json["esig_path"], + titlePrefix: json["title_prefix"], + titleSuffix: json["title_suffix"], + showTitleId: json["show_title_id"], + ); + + Map toJson() => { + "personid": personid, + "familyname": familyname, + "givenname": givenname, + "middlename": middlename, + "sex": sex, + "birthdate": "${birthdate?.year.toString().padLeft(4, '0')}-${birthdate?.month.toString().padLeft(2, '0')}-${birthdate?.day.toString().padLeft(2, '0')}", + "extension": extension, + "civilstatus": civilstatus, + "height_m": heightM, + "weight_kg": weightKg, + "bloodtype": bloodtype, + "photo_path": photoPath, + "uuid": uuid, + "encryption_key": encryptionKey, + "deceased": deceased, + "encrypted_profile": encryptedProfile, + "addedby": addedby, + "addedat": addedat?.toIso8601String(), + "updateby": updateby, + "updatedat": updatedat?.toIso8601String(), + "deletedby": deletedby, + "deletedat": deletedat, + "encrypt_signature": encryptSignature, + "esig_path": esigPath, + "title_prefix": titlePrefix, + "title_suffix": titleSuffix, + "show_title_id": showTitleId, + }; +} diff --git a/lib/model/roles/pass_check/purok_assign_area.dart b/lib/model/roles/pass_check/purok_assign_area.dart new file mode 100644 index 0000000..883086f --- /dev/null +++ b/lib/model/roles/pass_check/purok_assign_area.dart @@ -0,0 +1,42 @@ + + +import 'barangay_assign_area.dart'; + +class Purok { + final String? purokid; + final String? purokdesc; + final BaragayAssignArea? brgy; + final dynamic purokLeader; + final bool? writelock; + final dynamic recordsignature; + + Purok({ + required this.purokid, + required this.purokdesc, + required this.brgy, + required this.purokLeader, + required this.writelock, + required this.recordsignature, + }); + + factory Purok.fromJson(Map json) => Purok( + purokid: json["purokid"], + purokdesc: json["purokdesc"], + brgy: json["brgy"]==null?null:BaragayAssignArea.fromJson(json["brgy"]), + purokLeader: json["purok_leader"], + writelock: json["writelock"], + recordsignature: json["recordsignature"], + ); + + Map toJson() => { + "purokid": purokid, + "purokdesc": purokdesc, + "brgy": brgy?.toJson(), + "purok_leader": purokLeader, + "writelock": writelock, + "recordsignature": recordsignature, + }; +} + + + diff --git a/lib/model/roles/pass_check/station_assign_area.dart b/lib/model/roles/pass_check/station_assign_area.dart new file mode 100644 index 0000000..5b2c099 --- /dev/null +++ b/lib/model/roles/pass_check/station_assign_area.dart @@ -0,0 +1,136 @@ +// To parse this JSON data, do +// +// final assignArea = assignAreaFromJson(jsonString); + +import '../../rbac/rbac_station.dart'; +import '../../rbac/station_type.dart'; + +class StationAssignArea { + final bool? isactive; + final Station? area; + + StationAssignArea({ + required this.isactive, + required this.area, + }); + + factory StationAssignArea.fromJson(Map json) => StationAssignArea( + isactive: json["isactive"], + area: json["area"] == null?null: Station.fromJson(json["area"]), + ); + + Map toJson() => { + "isactive": isactive, + "area": area?.toJson(), + }; +} + +class Station { + final int? id; + final String? stationName; + final StationType? stationType; + final int? hierarchyOrderNo; + final String? headPosition; + final GovernmentAgency? governmentAgency; + final String? acronym; + final int? parentStation; + final String? code; + final String? fullcode; + final List? childStationInfo; + final bool? islocationUnderParent; + final int? mainParentStation; + final String? description; + final bool? ishospital; + final bool? isactive; + final bool? sellingStation; + + Station({ + required this.id, + required this.stationName, + required this.stationType, + required this.hierarchyOrderNo, + required this.headPosition, + required this.governmentAgency, + required this.acronym, + required this.parentStation, + required this.code, + required this.fullcode, + required this.childStationInfo, + required this.islocationUnderParent, + required this.mainParentStation, + required this.description, + required this.ishospital, + required this.isactive, + required this.sellingStation, + }); + + factory Station.fromJson(Map json) => Station( + id: json["id"], + stationName: json["station_name"], + stationType:json["station_type"] ==null?null: StationType.fromJson(json["station_type"]), + hierarchyOrderNo: json["hierarchy_order_no"], + headPosition: json["head_position"], + governmentAgency: json["government_agency"] == null?null:GovernmentAgency.fromJson(json["government_agency"]), + acronym: json["acronym"], + parentStation: json["parent_station"], + code: json["code"], + fullcode: json["fullcode"], + childStationInfo: json['child_station_info']==null || json['child_station_info'].isEmpty ?[]:List.from(json["child_station_info"].map((x) => ChildStationInfo.fromJson(x))), + islocationUnderParent: json["islocation_under_parent"], + mainParentStation: json["main_parent_station"], + description: json["description"], + ishospital: json["ishospital"], + isactive: json["isactive"], + sellingStation: json["selling_station"], + ); + + Map toJson() => { + "id": id, + "station_name": stationName, + "station_type": stationType?.toJson(), + "hierarchy_order_no": hierarchyOrderNo, + "head_position": headPosition, + "government_agency": governmentAgency?.toJson(), + "acronym": acronym, + "parent_station": parentStation, + "code": code, + "fullcode": fullcode, + "child_station_info": List.from(childStationInfo!.map((x) => x.toJson())), + "islocation_under_parent": islocationUnderParent, + "main_parent_station": mainParentStation, + "description": description, + "ishospital": ishospital, + "isactive": isactive, + "selling_station": sellingStation, + }; +} + +class ChildStationInfo { + final int? id; + final String? stationName; + final String? acroym; + bool? motherStation; + + ChildStationInfo({ + required this.id, + required this.stationName, + required this.acroym, + this.motherStation + }); + + factory ChildStationInfo.fromJson(Map json) => ChildStationInfo( + id: json["id"], + stationName: json["station_name"], + acroym: json["acroym"], + + ); + + Map toJson() => { + "id": id, + "station_name": stationName, + "acroym": acroym, + }; +} + + + diff --git a/lib/model/sos/session.dart b/lib/model/sos/session.dart new file mode 100644 index 0000000..2fa398a --- /dev/null +++ b/lib/model/sos/session.dart @@ -0,0 +1,69 @@ +// To parse this JSON data, do +// +// final sessionData = sessionDataFromJson(jsonString); + +import 'dart:convert'; + +SessionData sessionDataFromJson(String str) => SessionData.fromJson(json.decode(str)); + +String sessionDataToJson(SessionData data) => json.encode(data.toJson()); + +class SessionData { + SessionData({ + this.id, + this.receivedDate, + this.responseDate, + this.statusid, + this.acknowledgeDate, + this.acknowledgedBy, + this.remarks, + this.respondentid, + this.respondentMessage, + this.pushedbuttonDate, + this.sosLevel, + this.sessionToken, + }); + + final int? id; + final String? receivedDate; + final String? responseDate; + final int? statusid; + final String? acknowledgeDate; + final String? acknowledgedBy; + final String? remarks; + final int? respondentid; + final String? respondentMessage; + final String? pushedbuttonDate; + final String? sosLevel; + final String? sessionToken; + + factory SessionData.fromJson(Map json) => SessionData( + id: json["id"] = json["id"], + receivedDate: json["received_date"], + responseDate: json["response_date"], + statusid: json["statusid"], + acknowledgeDate: json["acknowledge_date"], + acknowledgedBy: json["acknowledged_by"], + remarks: json["remarks"], + respondentid: json["respondentid"], + respondentMessage: json["respondent_message"], + pushedbuttonDate: json["pushedbutton_date"], + sosLevel: json["sos_level"], + sessionToken: json["session_token"], + ); + + Map toJson() => { + "id": id, + "received_date": receivedDate, + "response_date": responseDate, + "statusid": statusid, + "acknowledge_date": acknowledgeDate, + "acknowledged_by": acknowledgedBy, + "remarks": remarks, + "respondentid": respondentid, + "respondent_message": respondentMessage, + "pushedbutton_date": pushedbuttonDate , + "sos_level": sosLevel, + "session_token": sessionToken, + }; +} diff --git a/lib/model/utils/agency.dart b/lib/model/utils/agency.dart new file mode 100644 index 0000000..b8def65 --- /dev/null +++ b/lib/model/utils/agency.dart @@ -0,0 +1,28 @@ +import 'package:unit2/model/utils/category.dart'; + +class Agency { + Agency({ + this.id, + this.name, + this.category, + this.privateEntity, + }); + + final int? id; + final String? name; + final Category? category; + final bool? privateEntity; + + factory Agency.fromJson(Map json) => Agency( + id: json["id"], + name: json["name"], + category: json["category"] == null ? null : Category.fromJson(json["category"]), + privateEntity: json["private_entity"], + ); + Map toJson() => { + "id": id, + "name": name, + "category": category?.toJson(), + "private_entity": privateEntity, + }; +} \ No newline at end of file diff --git a/lib/model/utils/agency_position.dart b/lib/model/utils/agency_position.dart new file mode 100644 index 0000000..f2d4f01 --- /dev/null +++ b/lib/model/utils/agency_position.dart @@ -0,0 +1,31 @@ + +import 'dart:convert'; + + +// To parse this JSON data, do +// +// final appoinemtStatus = appoinemtStatusFromJson(jsonString); +AppoinemtStatus appoinemtStatusFromJson(String str) => AppoinemtStatus.fromJson(json.decode(str)); + +String appoinemtStatusToJson(AppoinemtStatus data) => json.encode(data.toJson()); + +class AppoinemtStatus { + AppoinemtStatus({ + required this.value, + required this.label, + }); + + final String value; + final String label; + + factory AppoinemtStatus.fromJson(Map json) => AppoinemtStatus( + value: json["value"], + label: json["label"], + ); + + Map toJson() => { + "value": value, + "label": label, + }; +} + diff --git a/lib/model/utils/category.dart b/lib/model/utils/category.dart new file mode 100644 index 0000000..8319067 --- /dev/null +++ b/lib/model/utils/category.dart @@ -0,0 +1,25 @@ +import 'package:unit2/model/utils/industry_class.dart'; + +class Category { + Category({ + this.id, + this.name, + this.industryClass, + }); + + final int? id; + final String? name; + final IndustryClass? industryClass; + + factory Category.fromJson(Map json) => Category( + id: json["id"], + name: json["name"], + industryClass: json["industry_class"] == null ? null : IndustryClass.fromJson(json["industry_class"]), + ); + + Map toJson() => { + "id": id, + "name": name, + "industry_class": industryClass?.toJson(), + }; +} \ No newline at end of file diff --git a/lib/model/utils/eligibility.dart b/lib/model/utils/eligibility.dart new file mode 100644 index 0000000..b2ec606 --- /dev/null +++ b/lib/model/utils/eligibility.dart @@ -0,0 +1,39 @@ +// To parse this JSON data, do +// +// final eligibilities = eligibilitiesFromJson(jsonString); + +import 'package:meta/meta.dart'; +import 'dart:convert'; + +Eligibility eligibilitiesFromJson(String str) => Eligibility.fromJson(json.decode(str)); + +String eligibilitiesToJson(Eligibility data) => json.encode(data.toJson()); + +class Eligibility { + Eligibility({ + required this.id, + required this.title, + required this.type, + }); + + final int id; + final String title; + final String type; + + factory Eligibility.fromJson(Map json) => Eligibility( + id: json["id"], + title: json["title"], + type: json["type"], + ); + + Map toJson() => { + "id": id, + "title": title, + "type": type, + }; + @override + String toString() { +return title; + + } +} diff --git a/lib/model/utils/industry_class.dart b/lib/model/utils/industry_class.dart new file mode 100644 index 0000000..c6bb4bf --- /dev/null +++ b/lib/model/utils/industry_class.dart @@ -0,0 +1,23 @@ +class IndustryClass { + IndustryClass({ + this.id, + this.name, + this.description, + }); + + final int? id; + final String? name; + final String? description; + + factory IndustryClass.fromJson(Map json) => IndustryClass( + id: json["id"], + name: json["name"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "name": name, + "description": description, + }; +} \ No newline at end of file diff --git a/lib/model/utils/position.dart b/lib/model/utils/position.dart new file mode 100644 index 0000000..7051fae --- /dev/null +++ b/lib/model/utils/position.dart @@ -0,0 +1,19 @@ +class PositionTitle { + PositionTitle({ + this.id, + this.title, + }); + + final int? id; + final String? title; + + factory PositionTitle.fromJson(Map json) => PositionTitle( + id: json["id"], + title: json["title"], + ); + + Map toJson() => { + "id": id, + "title": title, + }; +} \ No newline at end of file diff --git a/lib/screens/docsms/components/doc_info_tile.dart b/lib/screens/docsms/components/doc_info_tile.dart new file mode 100644 index 0000000..f34f219 --- /dev/null +++ b/lib/screens/docsms/components/doc_info_tile.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import '../../../theme-data.dart/text-styles.dart'; +import '../../../utils/global.dart'; + +class DocInfo extends StatelessWidget { + final String title; + final String subTitle; + const DocInfo({super.key, required this.title, required this.subTitle}); + + @override + Widget build(BuildContext context) { + return ListTile( + dense: true, + title: Text( + title, + style: titleTextStyle() + .copyWith(color: Colors.black87, fontSize: blockSizeVertical * 2), + ), + subtitle: Text(subTitle), + ); + } +} diff --git a/lib/screens/docsms/components/request_receipt.dart b/lib/screens/docsms/components/request_receipt.dart new file mode 100644 index 0000000..d2e2491 --- /dev/null +++ b/lib/screens/docsms/components/request_receipt.dart @@ -0,0 +1,152 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/screens/docsms/components/doc_info_tile.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/costum_divider.dart'; +import 'package:unit2/widgets/text_icon.dart'; + +import '../../../test_data.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/global.dart'; + +class RequetAutoReceipt extends StatefulWidget { + RequetAutoReceipt({super.key}); + + @override + State createState() => _RequetAutoReceiptState(); +} + +class _RequetAutoReceiptState extends State { + final _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + backgroundColor: primary, + ), + body: SingleChildScrollView( + // ignore: avoid_unnecessary_containers + child: Container( + padding: const EdgeInsets.symmetric(vertical: 8), + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + const DocInfo(title: "4427", subTitle: documentId), + const CostumDivider(), + const DocInfo(title: "Purchase of Diesel", subTitle: documentTitle), + const CostumDivider(), + const DocInfo(title: "N/A", subTitle: documentSubject), + const CostumDivider(), + const DocInfo(title: "Request for Quotation", subTitle: documentType), + const CostumDivider(), + Form( + child: Column(children: [ + FormBuilder( + key: _formKey, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 25), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextIcon(title: "Source", icon: Entypo.reply), + const SizedBox( + height: 8, + ), + Text( + sourceRemarks, + style: Theme.of(context).textTheme.caption, + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + name: "remarks", + validator: FormBuilderValidators.required( + errorText: remarksRequired), + autovalidateMode: + AutovalidateMode.onUserInteraction, + maxLines: 5, + decoration: normalTextFieldStyle( + enterRemarks, "..."), + ), + const SizedBox( + height: 8, + ), + const TextIcon( + title: "Destination", icon: Entypo.forward), + const SizedBox( + height: 8, + ), + FormBuilderDropdown( + name: 'department', + autofocus: false, + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required( + errorText: departmentRequired) + ]), + decoration: + normalTextFieldStyle("Department", ""), + items: puroks + .map((purok) => DropdownMenuItem( + value: purok, + child: Text(purok), + )) + .toList()), + const SizedBox( + height: 12, + ), + FormBuilderDropdown( + name: 'substation', + autofocus: false, + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required( + errorText: substationRequired) + ]), + decoration: + normalTextFieldStyle("Substation", ""), + items: puroks + .map((purok) => DropdownMenuItem( + value: purok, + child: Text(purok), + )) + .toList()), + const SizedBox( + height: 24, + ), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle( + primary, Colors.transparent, Colors.white54), + child: const Text( + requestAutoReceipt, + style: TextStyle(color: Colors.white), + ), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + debugPrint(_formKey + .currentState!.value['remarks']); + } + }, + ), + ), + ], + ), + )), + ]), + ) + ]), + ), + ), + ), + ); + } +} diff --git a/lib/screens/docsms/index.dart b/lib/screens/docsms/index.dart new file mode 100644 index 0000000..d1730f0 --- /dev/null +++ b/lib/screens/docsms/index.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/docsms/docsms_bloc.dart'; +import 'package:unit2/screens/docsms/components/request_receipt.dart'; +import 'package:unit2/widgets/error_state.dart'; + +class AutoReceiveDocument extends StatefulWidget { + const AutoReceiveDocument({super.key}); + + @override + State createState() => _AutoReceiveDocumentState(); +} + +class _AutoReceiveDocumentState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + + ), + child: BlocConsumer( + listener: (context, state) { + if (state is DocSmsLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is DocSmsErrorState || state is DocumentLoaded) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + if (state is DocumentLoaded) { + return RequetAutoReceipt(); + }if(state is DocSmsErrorState){ + return SomethingWentWrong(message: state.message.toString(), onpressed: (){}); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/passo/Building/add_building.dart b/lib/screens/passo/Building/add_building.dart new file mode 100644 index 0000000..d2d94a8 --- /dev/null +++ b/lib/screens/passo/Building/add_building.dart @@ -0,0 +1,281 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/class_components/class_components_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart'; +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/additional_items.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/bldg_location_landref.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/general_description.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/property_appraisal.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/property_assessment.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/property_info.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/structural_materials.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:im_stepper/stepper.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; + +GlobalKey formKey = GlobalKey(); + +class AddBuilding extends StatefulWidget { + @override + _AddBuilding createState() => _AddBuilding(); +} + +class _AddBuilding extends State { + int activeStep = 0; // Initial step set to 5. + int upperBound = 6; + + bool saveStep1 = false; + bool saveStep2 = false; + bool saveStep3 = false; + bool saveStep4 = false; + bool saveStep5 = false; + bool saveStep6 = false; + bool saveStep7 = false; + int tempId = 0; + + Future _loadTempId() async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + tempId = (prefs.getInt('tempid') ?? 0); + }); + } + + void PrevBtn() { + setState(() { + activeStep--; + }); + } + + void NextBtn() { + setState(() { + activeStep++; + }); + } + + void onPutStructuralMaterials() { + if (activeStep < upperBound) { + setState(() { + activeStep++; + }); + } + // var strucMaterials = StructureMaterialsII( + // foundation: _foundations.getSelectedAsString().split(","), + // columns: _coumns.getSelectedAsString().split(","), + // beams: _beams.getSelectedAsString().split(","), + // trussFraming: + // _trussframing.getSelectedAsString().split(","), + // roof: _roof.getSelectedAsString().split(","), + // flooring: _flooring.getSelectedAsString().split(","), + // walls: _walls.getSelectedAsString().split(",")); + } + + void onPutPropertyAppraisal() {} + void bldgPrevBtn() { + if (activeStep > 0) { + setState(() { + activeStep--; + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + centerTitle: true, + title: const Text("Building FAAS"), + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer(listener: ( + context, + state, + ) { + if (state is PropertyInfoLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is PropertyInfoLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is PropertyInfoErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + Fluttertoast.showToast( + msg: onError, + fontSize: 24, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.black, + textColor: Colors.white); + } + }, builder: (context, state) { + if (state is PropertyInfoLoaded || + state is PropertyInfoErrorState) { + return BlocConsumer( + listener: ( + context, + state, + ) { + if (state is UnitConstructLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is UnitConstructLoaded || + state is UnitConstructErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + }, + builder: (context, state) { + if (state is UnitConstructLoaded) { + final unit = state.unit; + return BlocConsumer( + listener: ( + context, + state, + ) { + if (state is ClassComponentLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ClassComponentLoaded || + state is ClassComponentErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + }, + builder: (context, state) { + if (state is ClassComponentLoaded) { + final classes = state.classes; + + return Column( + children: [ + NumberStepper( + numbers: [1, 2, 3, 4, 5, 6, 7], + stepPadding: 5, + activeStepColor: primary, + numberStyle: TextStyle(color: Colors.white), + lineColor: primary, + // activeStep property set to activeStep variable defined above. + activeStep: activeStep, + activeStepBorderColor: Colors.white, + activeStepBorderWidth: 1, + // This ensures step-tapping updates the activeStep. + onStepReached: (index) { + setState(() { + activeStep = index; + }); + }, + enableStepTapping: false, + ), + Expanded( + child: StatefulBuilder(builder: + (BuildContext context, + StateSetter setState) { + return FormBuilder( + key: formKey, + onChanged: () { + formKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Container( + child: content( + unit, + classes, + PrevBtn, + NextBtn, + ), + ), + ); + }), + ), + ], + ); + } + if (state is ClassComponentErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadClassComponents()); + }, + ); + } + return Container(); + }, + ); + } + if (state is UnitConstructErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadUnitConstruct()); + }, + ); + } + return Container(); + }, + ); + } + + return Container(); + })), + ); + } + + Widget content(unit, List classes, PrevBtn, NextBtn) { + switch (activeStep) { + case 0: + return PropertyInfoPage(NextBtn); + + case 1: + return BldgLocationLandrefPage(PrevBtn, NextBtn); + + case 2: + return GeneralDescriptionPage(unit, NextBtn, PrevBtn); + + case 3: + return StructuralMaterialsPage(PrevBtn, NextBtn); + + case 4: + return AdditionalItemPage(unit, classes, PrevBtn, NextBtn); + + case 5: + return PropertyAppraisalPage(NextBtn, PrevBtn); + + case 6: + return PropertyAssessmentPage(onSAveAll); + + default: + return Text("Property Info"); + } + } + + void onSAveAll() { + return Navigator.of(context).pop(); + } +} diff --git a/lib/screens/passo/Building/add_building_components/AddExtraItems.dart b/lib/screens/passo/Building/add_building_components/AddExtraItems.dart new file mode 100644 index 0000000..eb3a9a7 --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/AddExtraItems.dart @@ -0,0 +1,579 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +class AddExtraItems extends StatefulWidget { + final List unit; + final List options; + + AddExtraItems(this.unit, this.options); + + @override + _AddExtraItems createState() => _AddExtraItems(); +} + +class _AddExtraItems extends State { + GlobalKey formKey = GlobalKey(); + final focus = FocusNode(); + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + final double _depValue = 0; + double _unitValue = 0; + String _className = ""; + int _classId = 0; + String _structureType = ""; + bool _withoutBUCC = false; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + double _amountofDepreciation(unitVal, unitBase, area, depreciation) { + return ((unitVal * unitBase) * area) * depreciation; + } + + double _totalMarketValue(unitVal, unitBase, area, depreciation, withBUCC, + className, painted, secondHand, paintedUnitVal, secondhandUntVal) { + if (withBUCC == false) { + if (painted == true || secondHand == true) { + final deductions = (paintedUnitVal + secondhandUntVal) / 100; + + print(deductions); + return (((unitVal - deductions) * unitBase) * area); + } else { + return ((unitVal * unitBase) * area); + } + } else { + return (unitVal * area); + } + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddItemsScreen) { + return FormBuilder( + key: formKey, + onChanged: () { + formKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: 800, + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDropdown( + name: 'extra_item', + autofocus: false, + decoration: + normalTextFieldStyle("Additional Item", ""), + items: widget.options + .map((e) => DropdownMenuItem( + value: e, + child: Text(e.componentName), + )) + .toList(), + onChanged: (value) { + if (value!.minBaseUnitvalPercent != '0.00') { + setState(() { + _unitValue = + double.parse(value.minBaseUnitvalPercent); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minBaseUnitvalPercent}); + } + if (value.maxBaseUnitvalPercent != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxBaseUnitvalPercent); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxBaseUnitvalPercent}); + } + if (value.minUnitvalSqrmtr != '0.00') { + setState(() { + _unitValue = + double.parse(value.minUnitvalSqrmtr); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minUnitvalSqrmtr}); + } + if (value.maxUnitvalSqrmtr != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxUnitvalSqrmtr); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxUnitvalSqrmtr}); + } + if (value.minAddBaseunitval != '0.00') { + setState(() { + _unitValue = + double.parse(value.minAddBaseunitval); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minAddBaseunitval}); + } + if (value.maxAddBaseunitval != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxAddBaseunitval); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxAddBaseunitval}); + } + if (value.minDeductBaserate != '0.00') { + setState(() { + _unitValue = + double.parse(value.minDeductBaserate); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minDeductBaserate}); + } + if (value.maxDeductBaserate != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxDeductBaserate); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxDeductBaserate}); + } + }, + ), + ), + const SizedBox(height: 10), + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: SizedBox( + height: 45, + child: SearchField( + itemHeight: 70, + suggestions: widget.unit + .map((UnitConstruct unit) => + SearchFieldListItem( + '${unit.bldgType} - ${unit.building}', + item: unit, + child: ListTile( + title: Text( + '${unit.bldgType} - ${unit.building!.toUpperCase()}', + overflow: TextOverflow.ellipsis, + ), + ))) + .toList(), + + validator: FormBuilderValidators.required( + errorText: "This field is required"), + + searchInputDecoration: normalTextFieldStyle( + "Structure Type", "") + .copyWith( + suffixIcon: + const Icon(Icons.arrow_drop_down)), + ////agency suggestion tap + focusNode: focus, + suggestionState: Suggestion.expand, + onSuggestionTap: (unit) { + setState(() { + _unitBase = + double.parse(unit.item!.unitValue); + _structureType = + '${unit.item!.bldgType} - ${unit.item!.building}'; + }); + focus.unfocus(); + }, + ), + ), + ), + // const SizedBox(height: 10), + // Container( + // margin: const EdgeInsets.only( + // left: 0, top: 10, right: 0, bottom: 0), + // child: FormBuilderDropdown( + // name: 'struc_type', + // autofocus: false, + // decoration: + // normalTextFieldStyle("Structure Type", ""), + // items: widget.unit + // .map((e) => DropdownMenuItem( + // value: e, + // child: + // Text(e.bldgType + " - " + e.building), + // )) + // .toList(), + // onChanged: (val) { + // setState(() { + // _unitBase = double.parse(val!.unitValue); + // _structureType = val.bldgType; + // }); + // }, + // ), + // ), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 1, + child: FormBuilderTextField( + name: 'unitValue', + decoration: + normalTextFieldStyle("Unit Value", ""), + validator: FormBuilderValidators.compose([]), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: FormBuilderTextField( + name: 'areaValue', + decoration: normalTextFieldStyle("Area", ""), + validator: FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + _areaValue = int.parse(value!); + }); + }, + ), + ), + ], + ), + // const SizedBox(height: 10), + // FormBuilderTextField( + // name: 'depRate', + // decoration: + // normalTextFieldStyle("Depreciation Rate", ""), + // validator: FormBuilderValidators.compose([]), + // onChanged: (value) { + // setState(() { + // _depValue = double.parse(value!); + // }); + // }, + // ), + // const SizedBox(height: 10), + // FormBuilderTextField( + // name: 'marketValue', + // decoration: normalTextFieldStyle( + // NumberFormat.currency( + // locale: 'en-PH', symbol: "₱") + // .format(_totalMarketValue(_unitValue, + // _unitBase, _areaValue, _depValue)), + // ""), + // validator: FormBuilderValidators.compose([]), + // onChanged: (value) { + // setState(() { + // _marketValue = double.parse(value!); + // }); + // }, + // ), + // const SizedBox(height: 10), + // Text('Amount of Depreciation'), + // const SizedBox(height: 5), + // Container( + // height: 45.0, + // width: double.infinity, + // decoration: BoxDecoration( + // color: Colors.white, + // border: Border.all( + // color: Colors.grey, + // width: 1.0, + // ), + // borderRadius: BorderRadius.circular(5.0), + // ), + // child: Align( + // alignment: Alignment.center, + // child: Text(NumberFormat.currency( + // locale: 'en-PH', symbol: "₱") + // .format(_amountofDepreciation(_unitValue, + // _unitBase, _areaValue, _depValue)))), + // ), + + Visibility( + visible: !_withoutBUCC, + child: Column( + children: [ + const SizedBox(height: 10), + const Text('Building is not painted?'), + const SizedBox(height: 5), + Container( + child: Row( + children: [ + Checkbox( + value: isPainted, + onChanged: (bool? value) { + setState(() { + isPainted = value!; + if (value == false) { + _notPaintedUnitVal = 0; + } else { + _notPaintedUnitVal = 10; + } + }); + }, + ), + const SizedBox(width: 10), + Container( + height: 40.0, + width: 100, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(' - ' + + _notPaintedUnitVal.toString() + + '%')), + ), + ], + ), + ), + const SizedBox(height: 10), + const Text('Uses second hand materials?'), + const SizedBox(height: 5), + Container( + child: Row( + children: [ + Checkbox( + value: isSecondHand, + onChanged: (bool? value) { + setState(() { + isSecondHand = value!; + if (isSecondHand == false) { + _secondHandUnitVal = 0; + formKey.currentState!.patchValue( + {'secondHandMat': '0'}); + } else { + _secondHandUnitVal = 5; + formKey.currentState!.patchValue( + {'secondHandMat': '5'}); + } + }); + }, + ), + const SizedBox(width: 10), + Row( + children: [ + SizedBox( + height: 40, + width: 100, + child: FormBuilderTextField( + enabled: isSecondHand, + name: 'secondHandMat', + textAlign: TextAlign.center, + decoration: normalTextFieldStyle( + "Unit Value", ""), + validator: + FormBuilderValidators.compose( + []), + onChanged: (value) { + // Check if the value is not null before parsing to double + if (value != null && + value.isNotEmpty) { + setState(() { + _secondHandUnitVal = + int.parse(value); + }); + } else { + // Handle the case when the value is empty or null + // For example, set _secondHandUnitVal to a default value or show an error message. + } + }, + ), + ), + const SizedBox( + height: 40, + width: 40, + child: Center( + child: Text( + '%', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold), + ), + ), + ) + ], + ), + ], + ), + ), + ], + ), + ), + + const SizedBox(height: 10), + const Text('Market Value'), + const SizedBox(height: 5), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', symbol: "₱") + .format(_totalMarketValue( + _unitValue, + _unitBase, + _areaValue, + _depValue, + _withoutBUCC, + _className, + isPainted, + isSecondHand, + _notPaintedUnitVal, + _secondHandUnitVal)))), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences.getInstance(); + var itemss = AdditionalItems( + id: 1, + bldgapprDetailsId: + tempID.getInt('tempid')! - 1, + classId: _classId, + className: _className, + structType: _structureType, + unitValue: + _withoutBUCC == true ? 0 : _unitValue, + baseUnitValue: _unitBase, + area: _areaValue, + marketValue: + (_unitValue * _unitBase) * _areaValue, + depreciationRate: _depValue, + adjustedMarketVal: _totalMarketValue( + _unitValue, + _unitBase, + _areaValue, + _depValue, + _withoutBUCC, + _className, + isPainted, + isSecondHand, + _notPaintedUnitVal, + _secondHandUnitVal), + actualUse: 'Test', + amtDepreciation: _amountofDepreciation( + _unitValue, + _unitBase, + _areaValue, + _depValue, + ), + painted: true, + secondhand: true, + paintedUnitval: '1', + secondhandUnitval: '1'); + + context + .read() + .add(AddAdditionalItems(items: itemss)); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + const SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read() + .add(const LoadAdditionalItems()); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ))); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Building/add_building_components/additional_items.dart b/lib/screens/passo/Building/add_building_components/additional_items.dart new file mode 100644 index 0000000..f087534 --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/additional_items.dart @@ -0,0 +1,296 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Building/add_building_components/AddExtraItems.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class AdditionalItemPage extends StatefulWidget { + final List unit; + final List options; + + final VoidCallback additionalItemsPrevBtn; + final VoidCallback additionalItemsNextBtn; + + const AdditionalItemPage(this.unit, this.options, this.additionalItemsPrevBtn, + this.additionalItemsNextBtn); + + @override + _AdditionalItemPage createState() => _AdditionalItemPage(); +} + +class _AdditionalItemPage extends State { + void deleteItem(int itemId) { + context.read().add(DeleteAdditionalItems(id: itemId)); + } + + double _totalMarketValue(items) { + double total = 0; + items.forEach((row) { + total += double.parse(row.adjustedMarketVal); + }); + return total; + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + final state = context.watch().state; + if (state is AdditionalItemsLoaded) { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('ADDITIONAL ITEMS', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowAdditionalItems()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: const [ + Text('ADD ITEM'), // <-- Text + SizedBox( + width: 5, + ), + Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Items'), + ), + const DataColumn( + label: Text('Unit Value'), + ), + const DataColumn( + label: Text('% of BUCC'), + ), + const DataColumn( + label: Text('Market Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.items.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.className)), + DataCell(Text(dataRow.baseUnitValue)), + DataCell(Text(dataRow.unitValue)), + DataCell(Text(((double.parse( + dataRow.adjustedMarketVal))) + .toString())), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: const Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id); + }, + ), + const SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: const Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList(), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Total', + style: + TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + ), + Text( + NumberFormat.currency(locale: 'en-PH', symbol: "₱") + .format(_totalMarketValue(state.items)), + style: + TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + ) + ], + ), + ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.additionalItemsPrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.additionalItemsNextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is AdditionalItemsDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadAdditionalItems()); + }); + }); + } + } + if (state is ShowAddItemsScreen) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: const EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: const Text( + 'ADD EXTRA ITEMS', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: AddExtraItems(widget.unit, widget.options)) + ], + ), + ), + ); + } + return Container( + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('ADDITIONAL MATERIALS', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + onPressed: () { + context + .read() + .add(ShowAdditionalItems()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: const [ + Text('ADD ITEM'), // <-- Text + SizedBox( + width: 5, + ), + Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/screens/passo/Building/add_building_components/bldg_location_landref.dart b/lib/screens/passo/Building/add_building_components/bldg_location_landref.dart new file mode 100644 index 0000000..0ecfe0a --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/bldg_location_landref.dart @@ -0,0 +1,336 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/barangay/barangay_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; + +import 'package:unit2/bloc/passo/municipality/municipality_bloc.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/passo/bldg_loc.dart'; + +import 'package:unit2/model/passo/city.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +import '../../../../model/passo/barangay.dart'; + +class BldgLocationLandrefPage extends StatefulWidget { + final VoidCallback PrevBtn; + final VoidCallback NextBtn; + BldgLocationLandrefPage(this.PrevBtn, this.NextBtn); + + @override + _BldgLocationLandrefPage createState() => _BldgLocationLandrefPage(); +} + +class _BldgLocationLandrefPage extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is MunicipalityLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is MunicipalityLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is MunicipalityErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is MunicipalityLoaded) { + List cityList = state.municipality; + + return BlocConsumer( + listener: (context, state) { + if (state is BarangayLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is BarangayLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is BarangayErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is BarangayLoaded) { + List brgyList = state.brgy; + List brgyNAmes = brgyList + .map((brgy) => brgy.barangayDescription) + .toList() + .cast(); + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('BUILDING LOCATION', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Province / City", "", 'province')), + const SizedBox(width: 10.0), + Expanded( + flex: 1, + child: FormBuilderDropdown( + name: 'municipality', + autofocus: false, + decoration: normalTextFieldStyle( + "Municipality", ""), + items: cityList + .map((city) => + DropdownMenuItem( + value: city, + child: Text(city + .cityDescription!), // Use cityDescription instead of cityName + )) + .toList(), + onChanged: (selectedCity) { + if (selectedCity != null) { + final selectedCityCode = + selectedCity.cityCode; + final barangayBloc = + context.read(); + barangayBloc.add(LoadBarangay( + id: selectedCityCode!)); // Use selectedCityCode directly + } + }, + )), + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "No. / Street", "", 'street'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDropDownField( + "Brgy. / District", + "", + 'brgy', + brgyNAmes)) + ]), + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('LAND REFERENCE', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + customTextField("Land Owner", "", 'l_owner'), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "OCT/TCT/CLOA No.", "", 'oct_tct_cloa'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Survey No.", "", 'survey_no')) + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Lot No.", "", 'lot_no'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Blk No.", "", 'blk_no')) + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "TD / ARP No.", "", 'l_td_arp'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: + customTextField("Area", "", 'area')) + ]), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () async { + { + final tempID = + await SharedPreferences.getInstance(); + var bldgLocData = BldgLoc( + id: tempID.getInt('tempid')! - 1, + street: formKey + .currentState?.value['street'], + barangay: + formKey.currentState?.value['brgy'], + municipality: formKey + .currentState + ?.value['municipality'] + .cityDescription, + province: formKey + .currentState?.value['province'], + ); + var landRefData = LandRef( + id: tempID.getInt('tempid')! - 1, + owner: formKey + .currentState?.value['l_owner'], + cloaNo: formKey.currentState + ?.value['oct_tct_cloa'], + lotNo: formKey + .currentState?.value['lot_no'], + tdn: formKey + .currentState?.value['l_td_arp'], + area: + formKey.currentState?.value['area'], + surveyNo: formKey + .currentState?.value['survey_no'], + blkNo: formKey + .currentState?.value['blk_no'], + ); + context.read() + ..add(UpdateBldgLoc( + bldg_loc: bldgLocData)) + ..add(UpdateLandRef( + land_ref: landRefData)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ) + ], + ), + ), + ); + } + if (state is BarangayErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add(LoadBarangay(id: '1')); + }, + ); + } + return Container(); + }, + ); + } + if (state is MunicipalityErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add(LoadMunicipality()); + }, + ); + } + return Container(); + }, + ), + ), + ); + } + + Future _waitForAddPropertyInfoToComplete() async { + // Wait for the state change indicating completion + final propertyInfoState = context.read().state; + + if (propertyInfoState is PropertyInfoErrorState) { + // Check if the add operation was successful + return true; // You'll need to define this in your state class + } + + // Return false if the state didn't change as expected + return false; + } +} diff --git a/lib/screens/passo/Building/add_building_components/general_description.dart b/lib/screens/passo/Building/add_building_components/general_description.dart new file mode 100644 index 0000000..78bbbe2 --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/general_description.dart @@ -0,0 +1,226 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class GeneralDescriptionPage extends StatefulWidget { + final List unit; + final VoidCallback onPutGeneralDescription; + final VoidCallback gendescPrevBtn; + + GeneralDescriptionPage( + this.unit, this.onPutGeneralDescription, this.gendescPrevBtn); + + @override + _GeneralDescriptionPage createState() => _GeneralDescriptionPage(); +} + +class _GeneralDescriptionPage extends State { + final actual_use = [ + "Residential", + "Agricultural", + "Commercial", + "Industrial", + "Mineral", + "Timberland", + ]; + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Container( + margin: + const EdgeInsets.only(left: 0, top: 20, right: 0, bottom: 10), + child: const Text('GENERAL DESCRIPTION', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Container( + margin: + const EdgeInsets.only(left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDropdown( + name: 'bldg_type', + autofocus: false, + decoration: normalTextFieldStyle("Kind of Building", ""), + items: widget.unit + .map((e) => DropdownMenuItem( + value: e, + child: Text('${e.bldgType}-${e.building}'), + )) + .toList(), + ), + ), + customDropDownField("Actual Use", "", 'actual_use', actual_use), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: + customTextField("Bldg. Permit No.", "", 'bldg_permit'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Certificate of Occupancy Issued ON", + "", + 'date_issued')) + ]), + customTextField( + "Condominium Certificate of Title (CCT)", "", 'cct'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customDatTimePicker( + "Certificate of Completion Issued ON", + "", + 'coc_issued'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Certificate of Occupancy Issued ON", + "", + 'coo_issued')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customDatTimePicker( + "Date Constructed /Completed", "", 'date_cnstructed'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Date Occupied", "", 'date_occupied')) + ]), + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: < + Widget>[ + Expanded( + flex: 1, + child: customTextField("Bldg. Age", "", 'bldg_age'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("No. of storeys", "", 'no_of_storeys')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Area of 1st Floor", "", 'area_of_1stFl'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Area of 2nd Floor", "", 'area_of_2ndFl')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Area of 3rd Floor", "", 'area_of_3rdFl')), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Area of 4th Floor", "", 'area_of_4thFl')) + ]), + customTextField("Total Area", "", 'total_area'), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.gendescPrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () async { + { + final tempID = await SharedPreferences.getInstance(); + widget.onPutGeneralDescription(); + var genDescData = GeneralDesc( + id: tempID.getInt('tempid')! - 1, + bldgKind: + formKey.currentState?.value['bldg_type'].building, + strucType: + formKey.currentState?.value['bldg_type'].bldgType, + bldgPermit: + formKey.currentState?.value['bldg_permit'], + dateIssued: formKey.currentState?.value['coc_issued'], + cct: formKey.currentState?.value['cct'], + certCompletionIssued: + formKey.currentState?.value['coc_issued'], + certOccupancyIssued: + formKey.currentState?.value['coo_issued'], + dateCompleted: + formKey.currentState?.value['date_cnstructed'], + dateOccupied: + formKey.currentState?.value['date_occupied'], + bldgAge: int.tryParse( + formKey.currentState?.value['bldg_age']), + noStoreys: int.tryParse( + formKey.currentState?.value['no_of_storeys']), + area1Stfloor: '0', + area2Ndfloor: '0', + area3Rdfloor: '0', + area4Thfloor: '0', + totalFloorArea: + formKey.currentState?.value['total_area'], + floorSketch: null, + actualUse: formKey.currentState?.value['actual_use']); + + context.read() + ..add(UpdateGeneralDesc(gen_desc: genDescData)); + } + ; + }, + ) + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/passo/Building/add_building_components/property_appraisal.dart b/lib/screens/passo/Building/add_building_components/property_appraisal.dart new file mode 100644 index 0000000..e746860 --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/property_appraisal.dart @@ -0,0 +1,1032 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class PropertyAppraisalPage extends StatefulWidget { + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + PropertyAppraisalPage(this.NextBtn, this.PrevBtn); + + @override + _PropertyAppraisalPage createState() => _PropertyAppraisalPage(); +} + +class _PropertyAppraisalPage extends State { + double depRate = 0; + + double _depRate = 0; + + double assessment_level = 0; + bool isTaxable = false; + bool isExempt = false; + String _memoranda = ''; + final focus = FocusNode(); + + String assessmentLevel(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return '0 '; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return '10 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return '20 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return '25 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return '80 '; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + default: + } + return ''; + } + + double assessmentValue(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return marketValue * 0; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return marketValue * 0.10; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return marketValue * 0.20; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return marketValue * 0.25; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return marketValue * 0.80; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + default: + } + return 0; + } + + calculateAdditionalItems(List items) { + double sum = 0; + double product = 1; + + for (AdditionalItems value in items) { + sum += double.parse(value.adjustedMarketVal); + } + + return sum; + } + + calculateTotalConstructionCost(buildingCost, additionalItems) { + double sum = 0; + double product = 1; + + sum = buildingCost + calculateAdditionalItems(additionalItems); + + return sum; + } + + calculateMarketValue(buildingCost, additionalItems, dep) { + double sum = 0; + double depreciation = 0; + double total = 0; + + sum = buildingCost + calculateAdditionalItems(additionalItems); + + depreciation = sum * dep; + + total = sum - depreciation; + + return total; + } + + calculateDepCost(buildingCost, additionalItems, dep) { + double sum = 0; + double depreciation = 0; + double total = 0; + + sum = buildingCost + calculateAdditionalItems(additionalItems); + + depreciation = sum * dep; + + total = sum - depreciation; + + return depreciation; + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) {}, + builder: (context, state) { + if (state is AdditionalItemsLoaded) { + return SingleChildScrollView( + child: Container( + margin: const EdgeInsets.only(left: 20.0, right: 20.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 20), + child: const Text('PROPERTY APPRAISAL', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Unit Construction Cost", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + formKey.currentState!.value['bldg_type'].unitValue + + ' sq.m', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Building Core", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Sub-total", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + (double.parse(formKey + .currentState!.value['total_area']) * + double.parse(formKey.currentState! + .value['bldg_type'].unitValue)) + .toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Cost of Additional Items", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Sub-total", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateAdditionalItems(state.items).toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Total Construction Cost", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateTotalConstructionCost( + (double.parse(formKey + .currentState!.value['total_area']) * + double.parse(formKey.currentState! + .value['bldg_type'].unitValue)), + state.items) + .toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Depreciation Rate", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + SizedBox( + width: 90, + height: 25, + child: FormBuilderTextField( + name: 'depRate', + decoration: normalTextFieldStyle("", ""), + validator: FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + depRate = double.parse(value!); + }); + }, + ), + ), + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Depreciation Cost", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateDepCost( + (double.parse(formKey + .currentState!.value['total_area']) * + double.parse(formKey.currentState! + .value['bldg_type'].unitValue)), + state.items, + depRate) + .toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Total % Depreciation", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '${(depRate * 100).toStringAsFixed(2)}%', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Market Value", + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateMarketValue( + (double.parse(formKey + .currentState!.value['total_area']) * + double.parse(formKey.currentState! + .value['bldg_type'].unitValue)), + state.items, + depRate) + .toString(), + textAlign: TextAlign.right, + ), + ), + ], + ), + Row( + children: [ + Expanded( + flex: 1, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Container( + margin: const EdgeInsets.only( + left: 20.0, right: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, + top: 20, + right: 0, + bottom: 20), + child: const Text('PROPERTY ASSESSMENT', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + Column( + children: [ + Row( + children: [ + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: const Text( + 'Actual Use', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: const Text( + 'Market Value', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: const Text( + 'Ass. Level', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: const Text( + 'Ass. Value', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + SizedBox( + height: 59, + child: Row( + children: [ + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: Text( + formKey.currentState + ?.value['actual_use']!, + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: Text( + calculateMarketValue( + (double.parse(formKey + .currentState! + .value[ + 'total_area']) * + double.parse(formKey + .currentState! + .value[ + 'bldg_type'] + .unitValue)), + state.items, + depRate) + .toString(), + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: Text( + assessmentLevel( + calculateMarketValue( + (double.parse(formKey + .currentState! + .value[ + 'total_area']) * + double.parse(formKey + .currentState! + .value[ + 'bldg_type'] + .unitValue)), + state.items, + depRate) + .toString(), + formKey.currentState + ?.value[ + 'actual_use']), + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + Container( + width: 100, + margin: const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all(5.0), + child: Text( + assessmentValue( + calculateMarketValue( + (double.parse(formKey.currentState!.value[ + 'total_area']) * + double.parse(formKey + .currentState! + .value[ + 'bldg_type'] + .unitValue)), + state.items, + depRate) + .toString(), + formKey.currentState + ?.value[ + 'actual_use']) + .toString(), + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + ) + ], + ), + ]))), + ), + ], + ), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () async { + { + final tempID = + await SharedPreferences.getInstance(); + print(tempID.getInt('tempid')); + var appraisals = PropertyAppraisal( + id: 1, + bldgapprDetailsId: tempID.getInt('tempid')!, + unitconstructCost: formKey + .currentState!.value['bldg_type'].unitValue, + buildingCore: 'test', + unitconstructSubtotal: + (double.parse(formKey.currentState!.value['total_area']) * + double.parse(formKey.currentState! + .value['bldg_type'].unitValue)) + .toString(), + depreciationRate: depRate.toString(), + depreciationCost: calculateDepCost( + (double.parse(formKey.currentState!.value['total_area']) * + double.parse( + formKey.currentState!.value['bldg_type'].unitValue)), + state.items, + depRate) + .toString(), + costAddItems: calculateAdditionalItems(state.items).toString(), + addItemsSubtotal: calculateAdditionalItems(state.items).toString(), + totalpercentDepreciation: (depRate * 100).toStringAsFixed(2), + marketValue: calculateMarketValue((double.parse(formKey.currentState!.value['total_area']) * double.parse(formKey.currentState!.value['bldg_type'].unitValue)), state.items, depRate).toString(), + totalArea: formKey.currentState!.value['total_area']); + context.read() + ..add( + AddPropertyAppraisal(appraisal: appraisals)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ], + ), + ), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/passo/Building/add_building_components/property_assessment.dart b/lib/screens/passo/Building/add_building_components/property_assessment.dart new file mode 100644 index 0000000..ff0d03c --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/property_assessment.dart @@ -0,0 +1,1168 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/memoranda/memoranda_bloc.dart'; + +import 'package:unit2/bloc/passo/signatories/signatories_bloc.dart'; +import 'package:unit2/model/passo/memoranda.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_assessment.dart'; +import 'package:unit2/model/passo/signatories.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class PropertyAssessmentPage extends StatefulWidget { + Function function; + + PropertyAssessmentPage(this.function); + + @override + _PropertyAssessmentPage createState() => _PropertyAssessmentPage(); +} + +class _PropertyAssessmentPage extends State { + double assessment_level = 0; + bool isTaxable = false; + bool isExempt = false; + String _memoranda = ''; + final focus = FocusNode(); + + String assessmentLevel(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return '0 '; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return '10 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return '20 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return '25 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return '80 '; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + default: + } + return ''; + } + + double assessmentValue(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return marketValue * 0; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return marketValue * 0.10; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return marketValue * 0.20; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return marketValue * 0.25; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return marketValue * 0.80; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + default: + } + return 0; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: true, + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is PropertyAssessmentLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is PropertyAssessmentLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is PropertyAssessmentErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is PropertyAssessmentLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is SignatoriesLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is SignatoriesLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is SignatoriesErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is SignatoriesLoaded) { + final signatories = state.signatories; + return BlocConsumer( + listener: (context, state) { + if (state is MemorandaLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is MemorandaLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is MemorandaErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is MemorandaLoaded) { + final memoranda = state.memorada; + return BlocConsumer( + listener: (context, state) { + if (state is PropertyAppraisalLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is PropertyAppraisalLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is PropertyAppraisalErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, builder: (context, state) { + if (state is PropertyAppraisalLoaded) { + return ListView( + children: [ + Align( + alignment: Alignment.center, + child: Container( + margin: const EdgeInsets.fromLTRB( + 0, 20, 0, 20), + child: const Text( + 'PROPERTY ASSESSMENT cont..', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + textAlign: TextAlign.left, + ), + ), + ), + Expanded( + flex: 3, + child: SingleChildScrollView( + padding: EdgeInsets.only( + left: 20.0, right: 20.0), + scrollDirection: Axis.vertical, + child: Column(children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + const Text('Taxable'), + Checkbox( + checkColor: Colors.white, + value: isTaxable, + onChanged: (bool? value) { + setState(() { + isTaxable = value!; + }); + }, + ) + ], + ), + Row( + children: [ + const Text('Exempt'), + Checkbox( + checkColor: Colors.white, + value: isExempt, + onChanged: (bool? value) { + setState(() { + isExempt = value!; + }); + }, + ) + ], + ), + ], + ), + Column( + children: [ + const SizedBox( + height: 20, + ), + const Text( + 'EFFECTIVITY OF ASSESSMENT / REASSESSMENT :', + style: TextStyle( + fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + const Text('Qtr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'qtr', + validator: + FormBuilderValidators + .compose([]), + ), + ), + const SizedBox( + width: 20, + ), + const Text('Yr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'yr', + validator: + FormBuilderValidators + .compose([]), + ), + ), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPRAISED/ASSESSED BY:', + style: TextStyle( + fontWeight: FontWeight.bold), + textAlign: TextAlign.start, + ), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'appraised_by', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: + FormBuilderDateTimePicker( + name: 'app_date', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: + DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'RECOMMENDING APPROVAL:', + style: TextStyle( + fontWeight: FontWeight.bold), + )), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'rec_approval', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: + FormBuilderDateTimePicker( + name: 'rec_date', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: + DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPROVED BY:', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'apprvd_by', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + ], + ), + const SizedBox( + height: 50, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'MEMORANDA: ', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + SizedBox( + height: 30, + ), + SizedBox( + width: 500, + height: 100, + child: SearchField( + itemHeight: 70, + suggestions: memoranda + .map((Memoranda memoranda) => + SearchFieldListItem( + '${memoranda.memoranda}', + item: + memoranda, // Change: Use individual Memoranda object + child: ListTile( + title: Text( + '${memoranda.memoranda}', + overflow: + TextOverflow + .ellipsis, + ), + ), + )) + .toList(), + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + // searchInputDecoration: + // normalTextFieldStyle( + // "Memoranda", "") + // .copyWith( + // suffixIcon: const Icon( + // Icons.arrow_drop_down), + // ), + // focusNode: focus, + suggestionState: + Suggestion.expand, + onSuggestionTap: (memoranda) { + setState(() { + _memoranda = memoranda + .item!.memoranda!; + }); + focus.unfocus(); + }, + )), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('Sworn Statement No. :'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'sworn_statement', + decoration: InputDecoration(), + validator: FormBuilderValidators + .compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('Date Received:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_received', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Date of Entry in the Rec. of Ass. :'), + SizedBox( + width: 100, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_of_entry', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('By:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'by', + decoration: InputDecoration(), + validator: FormBuilderValidators + .compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences + .getInstance(); + print(tempID.getInt('tempid')! - 1); + final List + propertyAssessments = []; + + PropertyAssessment ass = + PropertyAssessment( + id: 1, + bldgapprDetailsId: + tempID.getInt('tempid')! - 1, + actualUse: formKey.currentState! + .value['actual_use'], + marketValue: '0.00', + assessmentLevel: '0.00', + assessedValue: '0.00', + taxable: isTaxable, + exempt: isExempt, + qtr: int.parse(formKey + .currentState!.value['qtr']), + yr: int.parse(formKey + .currentState!.value['yr']), + appraisedbyName: formKey + .currentState! + .value['appraised_by'] + .firstname + + ' ' + + formKey + .currentState! + .value['appraised_by'] + .middlename + + ' ' + + formKey + .currentState! + .value['appraised_by'] + .lastname, + appraisedbyDate: formKey + .currentState! + .value['app_date'], + recommendapprName: formKey + .currentState! + .value['rec_approval'] + .firstname + + ' ' + + formKey + .currentState! + .value['rec_approval'] + .middlename + + ' ' + + formKey + .currentState! + .value['rec_approval'] + .lastname, + recommendapprDate: formKey + .currentState! + .value['rec_date'], + approvedbyName: formKey + .currentState! + .value['apprvd_by'] + .firstname + + ' ' + + formKey + .currentState! + .value['apprvd_by'] + .middlename + + ' ' + + formKey + .currentState! + .value['apprvd_by'] + .lastname, + memoranda: _memoranda, + swornstatementNo: formKey + .currentState! + .value['sworn_statement'], + dateReceived: formKey + .currentState! + .value['date_received'], + entryDateAssessment: formKey + .currentState! + .value['date_of_entry'], + entryDateBy: formKey + .currentState!.value['by'], + ); + + propertyAssessments.add(ass); + + context + .read() + ..add(UpdatePropertyAssessment( + assessment: + propertyAssessments[0])); + widget.function(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: primary, + foregroundColor: Colors.red), + child: SizedBox( + width: 200, + height: 50, + child: Align( + alignment: Alignment.center, + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + SizedBox( + height: 30, + ), + ]), + ), + ) + ], + ); + } + if (state is PropertyAppraisalErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add( + LoadPropertyAppraisal( + appraisal: PropertyAppraisal())); + }, + ); + } + return Container(); + }); + } + if (state is MemorandaErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadMemoranda()); + }, + ); + } + return Container(); + }, + ); + } + if (state is SignatoriesErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add(LoadSignatories()); + }, + ); + } + return Container(); + }, + ); + } + if (state is PropertyAssessmentErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadPropertyAssessment()); + }, + ); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/passo/Building/add_building_components/property_info.dart b/lib/screens/passo/Building/add_building_components/property_info.dart new file mode 100644 index 0000000..6cad1fc --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/property_info.dart @@ -0,0 +1,156 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +GlobalKey ownerKey = GlobalKey(); + +class PropertyInfoPage extends StatefulWidget { + final VoidCallback handleButtonPress; + const PropertyInfoPage(this.handleButtonPress, {super.key}); + + @override + _PropertyInfoPage createState() => _PropertyInfoPage(); +} + +class _PropertyInfoPage extends State { + int tempId = 0; + final transaction_codes = ['New', 'Revision']; + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY OWNER INFO', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + const SizedBox(height: 15), + customDropDownField("Transaction Code", "", "transaction_code", + transaction_codes), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("ARP No. / TD No.", "", 'arp_td')), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Pin", "", 'pin')), + ], + ), + customTextField("Owner", "", 'owner'), + customTextField("Address", "", 'address'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("Tel No.", "", 'tel_no'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("TIN", "", 'tin')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Administrator / Benificial User", "", 'benificiary'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("TIN", "", 'benificiary_tin')) + ]), + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: < + Widget>[ + Expanded( + flex: 1, + child: customTextField("Address", "", 'benificiary_address'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Tel No.", "", 'benificiary_telno')) + ]), + const SizedBox(height: 25), + CustomButton( + icon: const Icon(Icons.chevron_right, color: Colors.white), + onPressed: () async { + var property_info = PropertyInfo( + id: 1, + transCode: formKey.currentState!.value['transaction_code'] + .toString(), + tdn: formKey.currentState!.value['arp_td'], + pin: formKey.currentState!.value['pin'], + owner: formKey.currentState!.value['owner'], + address: formKey.currentState!.value['address'], + telno: formKey.currentState!.value['tel_no'], + tin: formKey.currentState!.value['tin'], + adminUser: formKey.currentState!.value['benificiary'], + adminAddress: + formKey.currentState!.value['benificiary_address'], + adminTin: formKey.currentState!.value['benificiary_tin'], + adminTelno: + formKey.currentState!.value['benificiary_telno'], + assessedById: '1', + assessedByName: 'Cyril', + faasType: "BUILDING", + dateModified: DateTime.now(), + dateCreated: DateTime.now()); + + // Dispatch the event to add the property_info + context.read().add( + AddPropertyInfo(property_info: property_info), + ); + + // Wait for the event to complete and get the result + bool success = await _waitForAddPropertyInfoToComplete(); + + if (success) { + // Proceed to the next step or perform an action + widget.handleButtonPress(); + } else { + // Stay or show an error message + } + }, + ) + ]), + ), + ); + } + + Future _waitForAddPropertyInfoToComplete() async { + // Wait for the state change indicating completion + final propertyInfoState = context.read().state; + + if (propertyInfoState is PropertyInfoLoaded) { + // Check if the add operation was successful + return true; // You'll need to define this in your state class + } + + // Return false if the state didn't change as expected + return false; + } +} diff --git a/lib/screens/passo/Building/add_building_components/structural_materials.dart b/lib/screens/passo/Building/add_building_components/structural_materials.dart new file mode 100644 index 0000000..67f6edd --- /dev/null +++ b/lib/screens/passo/Building/add_building_components/structural_materials.dart @@ -0,0 +1,421 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:multiselect/multiselect.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class MaterialOption { + final String id; + final String label; + + MaterialOption(this.id, this.label); +} + +class StructuralMaterialsPage extends StatefulWidget { + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + StructuralMaterialsPage(this.NextBtn, this.PrevBtn); + + @override + _StructuralMaterialsPage createState() => _StructuralMaterialsPage(); +} + +class _StructuralMaterialsPage extends State { + List foundation = []; + List column = []; + List beam = []; + List truss_framing = []; + List roof = []; + List flooring = []; + List walls = []; + bool foundationOthers = false; + bool columOthers = false; + bool beamsOthers = false; + bool tfOthers = false; + bool roofOthers = false; + bool flooringOthers = false; + bool wpOthers = false; + + List columnOptions = [ + MaterialOption('steel', 'Steel'), + MaterialOption('concrete', 'Reinforced Concrete'), + MaterialOption('wood', 'Wood'), + ]; + + List selectedColumnValues = []; + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + padding: const EdgeInsets.all(30.0), + child: Column( + children: [ + Container( + margin: + const EdgeInsets.only(left: 0, top: 20, right: 0, bottom: 10), + child: const Text('STRUCTURAL MATERIALS', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'FOUNDATION', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: foundationOthers, + onChanged: (bool? value) { + setState(() { + foundationOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: foundationOthers, + child: customTextField( + "Enter other foundation", "", "other_foundation"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + foundation = x; + }); + }, + options: const ['Reinforced Concrete', 'Plain Concrete'], + selectedValues: foundation, + whenEmpty: 'Select Foundations', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'COLUMNS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: columOthers, + onChanged: (bool? value) { + setState(() { + columOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: columOthers, + child: customTextField("Enter other columns", "", "other_column"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + column = x; + }); + }, + options: const ['Steel', 'Reinforced Concrete', 'Wood'], + selectedValues: column, + whenEmpty: 'Select Column/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'BEAMS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: beamsOthers, + onChanged: (bool? value) { + setState(() { + beamsOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: beamsOthers, + child: customTextField("Enter other beam/s", "", "other_beam"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + beam = x; + }); + }, + options: const ['Steel', 'Reinforced Concrete', 'Wood'], + selectedValues: beam, + whenEmpty: 'Select Beam/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'TRUSS FRAMING', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: tfOthers, + onChanged: (bool? value) { + setState(() { + tfOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: tfOthers, + child: customTextField( + "Enter other truss framing/s", "", "other_tf"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + truss_framing = x; + }); + }, + options: const ['Steel', 'Wood'], + selectedValues: truss_framing, + whenEmpty: 'Select Truss Framing/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'ROOF', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: roofOthers, + onChanged: (bool? value) { + setState(() { + roofOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: roofOthers, + child: customTextField("Enter other roof/s", "", "other_roof"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + roof = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Tiles', + 'G.I Sheet', + 'Aluminum', + 'Asbestos', + 'Long Span', + 'Concrete Desk', + 'Nipa/Anahaw/Cogon' + ], + selectedValues: roof, + whenEmpty: 'Select Roof/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'FLOORING', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: flooringOthers, + onChanged: (bool? value) { + setState(() { + flooringOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: flooringOthers, + child: customTextField( + "Enter other flooring/s", "", "other_flooring"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + flooring = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Plain Cement', + 'Marble', + 'Wood', + 'Tiles' + ], + selectedValues: flooring, + whenEmpty: 'Select Flooring/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'WALLS & PARTITIONS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: wpOthers, + onChanged: (bool? value) { + setState(() { + wpOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: wpOthers, + child: customTextField( + "Enter other walls & partition/s", "", "other_wp"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + walls = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Plain Concrete', + 'Wood', + 'CHIB', + 'G.I Sheet', + 'Build-a-wall', + 'Sawali', + 'Bamboo' + ], + selectedValues: walls, + whenEmpty: 'Select Walls & Partition/s', + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: + const Icon(Icons.chevron_left_rounded, color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () async { + { + final tempID = await SharedPreferences.getInstance(); + var strucMaterials = StructureMaterialsII( + id: tempID.getInt('tempid')! - 1, + foundation: foundationOthers + ? formKey.currentState!.value['other_foundation'] + .split(',') + : foundation, + columns: columOthers + ? formKey.currentState!.value['other_column'] + .split(',') + : column, + beams: beamsOthers + ? formKey.currentState!.value['other_beam'] + .split(',') + : beam, + trussFraming: tfOthers + ? formKey.currentState!.value['other_tf'].split(',') + : truss_framing, + roof: roofOthers + ? formKey.currentState!.value['other_roof'] + .split(',') + : roof, + flooring: flooringOthers + ? formKey.currentState!.value['other_flooring'] + .split(',') + : flooring, + walls: wpOthers + ? formKey.currentState!.value['other_wp'].split(',') + : walls, + others: ["Others"]); + context.read() + ..add(UpdateStrucMaterials(data: strucMaterials)); + + widget.PrevBtn(); + } + ; + }, + ) + ], + ) + ], + ), + ); + } +} diff --git a/lib/screens/passo/Building/edit_building.dart b/lib/screens/passo/Building/edit_building.dart new file mode 100644 index 0000000..6a1dde5 --- /dev/null +++ b/lib/screens/passo/Building/edit_building.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import 'package:im_stepper/stepper.dart'; +import 'package:unit2/bloc/passo/bulding/class_components/class_components_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Building/edit_building/additional_items.dart'; +import 'package:unit2/screens/passo/Building/edit_building/bldgloc_landref.dart'; +import 'package:unit2/screens/passo/Building/edit_building/general_description.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_appraisal.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_assessement_edit.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_owner_info.dart'; +import 'package:unit2/screens/passo/Building/edit_building/structural_materials.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; + +class EditBuilding extends StatefulWidget { + final int index; + final PropertyInfo faas; + final String title; + + const EditBuilding( + {super.key, + required this.title, + required this.index, + required this.faas}); + @override + _EditBuilding createState() => _EditBuilding(); +} + +class _EditBuilding extends State { + // THE FOLLOWING TWO VARIABLES ARE REQUIRED TO CONTROL THE STEPPER. + int activeStep = 0; // Initial step set to 5. + + int upperBound = 6; // upperBound MUST BE total number of icons minus 1. + + void PrevBtn() { + setState(() { + activeStep--; + }); + } + + void NextBtn() { + setState(() { + activeStep++; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + home: Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: Text('Building FAAS Edit'), + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is UnitConstructLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is UnitConstructLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is UnitConstructErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is UnitConstructLoaded) { + final unit = state.unit; + return BlocConsumer( + listener: (context, state) { + if (state is ClassComponentLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ClassComponentLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is ClassComponentErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is ClassComponentLoaded) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + NumberStepper( + numbers: [1, 2, 3, 4, 5, 6, 7], + activeStepColor: primary, + numberStyle: TextStyle(color: Colors.white), + lineColor: primary, + // activeStep property set to activeStep variable defined above. + activeStep: activeStep, + activeStepBorderColor: Colors.white, + activeStepBorderWidth: 1, + // This ensures step-tapping updates the activeStep. + onStepReached: (index) { + setState(() { + activeStep = index; + }); + }, + ), + content(unit, state.classes), + ], + ), + ); + } + if (state is ClassComponentErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadClassComponents()); + }, + ); + } + return Container(); + }, + ); + } + if (state is UnitConstructErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add(LoadUnitConstruct()); + }, + ); + } + return Container(); + }, + ), + ), + ), + ); + } + + // Returns the header text based on the activeStep. + Widget content(List unit, classes) { + switch (activeStep) { + case 0: + return PropertyOwnerInfoEdit( + widget.index, widget.faas, widget.title, NextBtn, PrevBtn); + + case 1: + return BldgLocLandRefEdit(widget.faas.id!, NextBtn, PrevBtn); + + case 2: + return GeneralDescriptionEdit(unit, widget.faas.id!, NextBtn, PrevBtn); + + case 3: + return StructuralMaterialsPageEdit(widget.faas.id!, NextBtn, PrevBtn); + + case 4: + return AdditionalItemEditPage( + unit, classes, widget.faas.id!, NextBtn, PrevBtn); + + case 5: + return PropertyAppraisalEditPage(widget.faas.id!, NextBtn, PrevBtn); + + case 6: + return PropertyAssessmentEditPage(widget.faas.id!); + + default: + return PropertyOwnerInfoEdit( + widget.index, widget.faas, widget.title, NextBtn, PrevBtn); + } + } +} diff --git a/lib/screens/passo/Building/edit_building/AddExtraItems.dart b/lib/screens/passo/Building/edit_building/AddExtraItems.dart new file mode 100644 index 0000000..374968d --- /dev/null +++ b/lib/screens/passo/Building/edit_building/AddExtraItems.dart @@ -0,0 +1,594 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +class AddExtraItemsEdit extends StatefulWidget { + final List unit; + final List options; + final int tempId; + + AddExtraItemsEdit(this.unit, this.options, this.tempId); + + @override + _AddExtraItemsEdit createState() => _AddExtraItemsEdit(); +} + +class _AddExtraItemsEdit extends State { + GlobalKey formKey = GlobalKey(); + final focus = FocusNode(); + double _computedValue = 0; + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + double _depValue = 0; + double _unitValue = 0; + double _marketValue = 0; + String _className = ""; + int _classId = 0; + String _structureType = ""; + bool _withoutBUCC = false; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + double _computeValue(double unitbase, double unitvalue, double area) { +// Compute some value based on the text here + return (unitbase * unitvalue) * area; + } + + double _amountofDepreciation(unitVal, unitBase, area, depreciation) { + return ((unitVal * unitBase) * area) * depreciation; + } + + double _adjustedMarketValue(unitVal, unitBase, area, depreciation) { + double depAmount = ((unitVal * unitBase) * area) * depreciation; + + return ((unitVal * unitBase) * area) - depAmount; + } + + double _totalMarketValue(unitVal, unitBase, area, depreciation, withBUCC, + className, painted, secondHand, paintedUnitVal, secondhandUntVal) { + if (withBUCC == false) { + if (painted == true || secondHand == true) { + final deductions = (paintedUnitVal + secondhandUntVal) / 100; + + print(deductions); + return (((unitVal - deductions) * unitBase) * area); + } else { + return ((unitVal * unitBase) * area); + } + } else { + return (unitVal * area); + } + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddItemsScreenEdit) { + return FormBuilder( + key: formKey, + onChanged: () { + formKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: 800, + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDropdown( + name: 'extra_item', + autofocus: false, + decoration: + normalTextFieldStyle("Additional Item", ""), + items: widget.options + .map((e) => DropdownMenuItem( + value: e, + child: Text(e.componentName), + )) + .toList(), + onChanged: (value) { + if (value!.minBaseUnitvalPercent != '0.00') { + setState(() { + _unitValue = + double.parse(value.minBaseUnitvalPercent); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minBaseUnitvalPercent}); + } + if (value.maxBaseUnitvalPercent != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxBaseUnitvalPercent); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxBaseUnitvalPercent}); + } + if (value.minUnitvalSqrmtr != '0.00') { + setState(() { + _unitValue = + double.parse(value.minUnitvalSqrmtr); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minUnitvalSqrmtr}); + } + if (value.maxUnitvalSqrmtr != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxUnitvalSqrmtr); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxUnitvalSqrmtr}); + } + if (value.minAddBaseunitval != '0.00') { + setState(() { + _unitValue = + double.parse(value.minAddBaseunitval); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minAddBaseunitval}); + } + if (value.maxAddBaseunitval != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxAddBaseunitval); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxAddBaseunitval}); + } + if (value.minDeductBaserate != '0.00') { + setState(() { + _unitValue = + double.parse(value.minDeductBaserate); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.minDeductBaserate}); + } + if (value.maxDeductBaserate != '0.00') { + setState(() { + _unitValue = + double.parse(value.maxDeductBaserate); + _className = value.componentName; + _classId = value.id; + _withoutBUCC = value.withoutBucc; + }); + formKey.currentState!.patchValue( + {'unitValue': value.maxDeductBaserate}); + } + }, + ), + ), + const SizedBox(height: 10), + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: SizedBox( + height: 45, + child: SearchField( + itemHeight: 70, + suggestions: widget.unit + .map((UnitConstruct unit) => + SearchFieldListItem( + unit.bldgType! + + ' - ' + + unit.building, + item: unit, + child: ListTile( + title: Text( + unit.bldgType + + ' - ' + + unit.building!.toUpperCase(), + overflow: TextOverflow.ellipsis, + ), + ))) + .toList(), + + validator: FormBuilderValidators.required( + errorText: "This field is required"), + + searchInputDecoration: normalTextFieldStyle( + "Structure Type", "") + .copyWith( + suffixIcon: + const Icon(Icons.arrow_drop_down)), + ////agency suggestion tap + focusNode: focus, + suggestionState: Suggestion.expand, + onSuggestionTap: (unit) { + setState(() { + _unitBase = + double.parse(unit.item!.unitValue); + _structureType = unit.item!.bldgType + + ' - ' + + unit.item!.building; + }); + focus.unfocus(); + }, + ), + ), + ), + // const SizedBox(height: 10), + // Container( + // margin: const EdgeInsets.only( + // left: 0, top: 10, right: 0, bottom: 0), + // child: FormBuilderDropdown( + // name: 'struc_type', + // autofocus: false, + // decoration: + // normalTextFieldStyle("Structure Type", ""), + // items: widget.unit + // .map((e) => DropdownMenuItem( + // value: e, + // child: + // Text(e.bldgType + " - " + e.building), + // )) + // .toList(), + // onChanged: (val) { + // setState(() { + // _unitBase = double.parse(val!.unitValue); + // _structureType = val.bldgType; + // }); + // }, + // ), + // ), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 1, + child: FormBuilderTextField( + name: 'unitValue', + decoration: + normalTextFieldStyle("Unit Value", ""), + validator: FormBuilderValidators.compose([]), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: FormBuilderTextField( + name: 'areaValue', + decoration: normalTextFieldStyle("Area", ""), + validator: FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + _areaValue = int.parse(value!); + }); + }, + ), + ), + ], + ), + // const SizedBox(height: 10), + // FormBuilderTextField( + // name: 'depRate', + // decoration: + // normalTextFieldStyle("Depreciation Rate", ""), + // validator: FormBuilderValidators.compose([]), + // onChanged: (value) { + // setState(() { + // _depValue = double.parse(value!); + // }); + // }, + // ), + // const SizedBox(height: 10), + // FormBuilderTextField( + // name: 'marketValue', + // decoration: normalTextFieldStyle( + // NumberFormat.currency( + // locale: 'en-PH', symbol: "₱") + // .format(_totalMarketValue(_unitValue, + // _unitBase, _areaValue, _depValue)), + // ""), + // validator: FormBuilderValidators.compose([]), + // onChanged: (value) { + // setState(() { + // _marketValue = double.parse(value!); + // }); + // }, + // ), + // const SizedBox(height: 10), + // Text('Amount of Depreciation'), + // const SizedBox(height: 5), + // Container( + // height: 45.0, + // width: double.infinity, + // decoration: BoxDecoration( + // color: Colors.white, + // border: Border.all( + // color: Colors.grey, + // width: 1.0, + // ), + // borderRadius: BorderRadius.circular(5.0), + // ), + // child: Align( + // alignment: Alignment.center, + // child: Text(NumberFormat.currency( + // locale: 'en-PH', symbol: "₱") + // .format(_amountofDepreciation(_unitValue, + // _unitBase, _areaValue, _depValue)))), + // ), + + Visibility( + visible: !_withoutBUCC, + child: Column( + children: [ + const SizedBox(height: 10), + Text('Building is not painted?'), + const SizedBox(height: 5), + Container( + child: Row( + children: [ + Checkbox( + value: isPainted, + onChanged: (bool? value) { + setState(() { + isPainted = value!; + if (value == false) { + _notPaintedUnitVal = 0; + } else { + _notPaintedUnitVal = 10; + } + }); + }, + ), + const SizedBox(width: 10), + Container( + height: 40.0, + width: 100, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(' - ' + + _notPaintedUnitVal.toString() + + '%')), + ), + ], + ), + ), + const SizedBox(height: 10), + Text('Uses second hand materials?'), + const SizedBox(height: 5), + Container( + child: Row( + children: [ + Checkbox( + value: isSecondHand, + onChanged: (bool? value) { + setState(() { + isSecondHand = value!; + if (isSecondHand == false) { + _secondHandUnitVal = 0; + formKey.currentState!.patchValue( + {'secondHandMat': '0'}); + } else { + _secondHandUnitVal = 5; + formKey.currentState!.patchValue( + {'secondHandMat': '5'}); + } + }); + }, + ), + const SizedBox(width: 10), + Row( + children: [ + SizedBox( + height: 40, + width: 100, + child: FormBuilderTextField( + enabled: isSecondHand, + name: 'secondHandMat', + textAlign: TextAlign.center, + decoration: normalTextFieldStyle( + "Unit Value", ""), + validator: + FormBuilderValidators.compose( + []), + onChanged: (value) { + // Check if the value is not null before parsing to double + if (value != null && + value.isNotEmpty) { + setState(() { + _secondHandUnitVal = + int.parse(value); + }); + } else { + // Handle the case when the value is empty or null + // For example, set _secondHandUnitVal to a default value or show an error message. + } + }, + ), + ), + SizedBox( + height: 40, + width: 40, + child: Center( + child: Text( + '%', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold), + ), + ), + ) + ], + ), + ], + ), + ), + ], + ), + ), + + const SizedBox(height: 10), + Text('Market Value'), + const SizedBox(height: 5), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', symbol: "₱") + .format(_totalMarketValue( + _unitValue, + _unitBase, + _areaValue, + _depValue, + _withoutBUCC, + _className, + isPainted, + isSecondHand, + _notPaintedUnitVal, + _secondHandUnitVal)))), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + var itemss = AdditionalItems( + id: 1, + bldgapprDetailsId: widget.tempId, + classId: _classId, + className: _className, + structType: _structureType, + unitValue: + _withoutBUCC == true ? 0 : _unitValue, + baseUnitValue: _unitBase, + area: _areaValue, + marketValue: + (_unitValue * _unitBase) * _areaValue, + depreciationRate: _depValue, + adjustedMarketVal: _totalMarketValue( + _unitValue, + _unitBase, + _areaValue, + _depValue, + _withoutBUCC, + _className, + isPainted, + isSecondHand, + _notPaintedUnitVal, + _secondHandUnitVal), + actualUse: 'Test', + amtDepreciation: _amountofDepreciation( + _unitValue, + _unitBase, + _areaValue, + _depValue, + ), + painted: true, + secondhand: true, + paintedUnitval: '1', + secondhandUnitval: '1'); + + context.read().add( + AddAdditionalItemsEdit(items: itemss)); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read() + .add(LoadAdditionalItems()); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ))); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Building/edit_building/additional_items.dart b/lib/screens/passo/Building/edit_building/additional_items.dart new file mode 100644 index 0000000..b5b9872 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/additional_items.dart @@ -0,0 +1,305 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Building/edit_building/AddExtraItems.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class AdditionalItemEditPage extends StatefulWidget { + final List unit; + final List options; + final int tempId; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + AdditionalItemEditPage( + this.unit, this.options, this.tempId, this.NextBtn, this.PrevBtn); + + @override + _AdditionalItemEditPage createState() => _AdditionalItemEditPage(); +} + +class _AdditionalItemEditPage extends State { + void deleteItem(int itemId) { + context + .read() + .add(DeleteAdditionalItemsEdit(id: itemId)); + } + + // double _totalMarketValue(items) { + // double total = 0; + // items.forEach((row) { + // total += double.parse(row.adjustedMarketVal); + // }); + // return total; + // } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + final state = context.watch().state; + if (state is AdditionalItemsEditLoaded) { + return Column( + children: [ + Container( + height: 500, + child: Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('ADDITIONAL ITEMS', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowAdditionalItemsEdit()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Items'), + ), + const DataColumn( + label: Text('Unit Value'), + ), + const DataColumn( + label: Text('% of BUCC'), + ), + const DataColumn( + label: Text('Market Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.items.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.className)), + DataCell(Text(dataRow.baseUnitValue)), + DataCell(Text(dataRow.unitValue)), + DataCell(Text(((double.parse( + dataRow.adjustedMarketVal))) + .toString())), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id); + }, + ), + SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList(), + ), + ), + ], + ), + ), + ), + ), + ), + // Padding( + // padding: const EdgeInsets.only(left: 20.0, right: 20.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // 'Total', + // style: + // TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ), + // Text( + // NumberFormat.currency(locale: 'en-PH', symbol: "₱") + // .format(_totalMarketValue(state.items)), + // style: + // TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ) + // ], + // ), + // ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is AdditionalItemsEditDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context.read().add( + LoadAdditionalItemsEdit( + items: const [], id: widget.tempId)); + }); + }); + } + } + if (state is ShowAddItemsScreenEdit) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: Text( + 'ADD EXTRA ITEMS', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: AddExtraItemsEdit( + widget.unit, widget.options, widget.tempId)) + ], + ), + ), + ); + } + return Container( + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('ADDITIONAL MATERIALS', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + onPressed: () { + context + .read() + .add(ShowAdditionalItems()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/screens/passo/Building/edit_building/bldgloc_landref.dart b/lib/screens/passo/Building/edit_building/bldgloc_landref.dart new file mode 100644 index 0000000..2b6ced8 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/bldgloc_landref.dart @@ -0,0 +1,453 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/passo/barangay/barangay_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/landref/landref_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/location/location_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; + +import 'package:unit2/bloc/passo/municipality/municipality_bloc.dart'; + +import 'package:unit2/model/passo/barangay.dart'; +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/model/passo/city.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_owner_info.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class BldgLocLandRefEdit extends StatefulWidget { + final int tempId; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + BldgLocLandRefEdit(this.tempId, this.NextBtn, this.PrevBtn); + @override + _BldgLocLandRefEdit createState() => _BldgLocLandRefEdit(); +} + +class _BldgLocLandRefEdit extends State { + Set seenCityCodes = Set(); + @override + Widget build(BuildContext context) { + return ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is LocationLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is LocationLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is LocationErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is LocationLoaded) { + final bldgloc = state.bldgloc; + return BlocConsumer( + listener: (context, state) { + if (state is LandrefLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is LandrefLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is LandrefErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, + builder: (context, state) { + if (state is LandrefLoaded) { + final landRef = state.landRef; + return BlocConsumer( + listener: (context, state) { + if (state is MunicipalityLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is MunicipalityLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is MunicipalityErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, builder: (context, state) { + if (state is MunicipalityLoaded) { + final cityList = state.municipality; + Set uniqueItems = {}; + + // Iterate through the dropdownItems list to filter out duplicates + for (var item in cityList) { + uniqueItems.add(item); + } + return BlocConsumer( + listener: (context, state) { + if (state is BarangayLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is BarangayLoaded) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + if (state is BarangayErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + // Fluttertoast.showToast( + // msg: onError, + // fontSize: 24, + // toastLength: Toast.LENGTH_LONG, + // gravity: ToastGravity.CENTER, + // backgroundColor: Colors.black, + // textColor: Colors.white); + } + }, builder: (context, state) { + if (state is BarangayLoaded) { + List brgyList = state.brgy; + List brgyNAmes = brgyList + .map((brgy) => brgy.barangayDescription) + .toList() + .cast(); + return FormBuilder( + key: keys, + initialValue: { + 'street': bldgloc.street, + // 'brgy': bldgloc.barangay, + // 'municipality': bldgloc.municipality, + 'province': bldgloc.province, + 'l_owner': landRef.owner, + 'oct_tct_cloa': landRef.cloaNo, + 'survey_no': landRef.surveyNo, + 'lot_no': landRef.lotNo, + 'blk_no': landRef.blkNo, + 'l_td_arp': landRef.tdn, + 'area': landRef.area + }, + enabled: true, + onChanged: () { + keys.currentState!.save(); + debugPrint(keys.currentState!.value.toString()); + }, + autovalidateMode: AutovalidateMode.disabled, + skipDisabled: true, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: ListView( + shrinkWrap: true, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, + top: 20, + right: 0, + bottom: 10), + child: const Text('BUILDING LOCATION', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: FormBuilderDropdown( + name: 'municipality', + autofocus: false, + decoration: normalTextFieldStyle( + bldgloc.municipality ?? + "Municipality", + "", + ), + items: uniqueItems + .map( + (city) => + DropdownMenuItem( + value: city, + child: Text( + city.cityDescription ?? + ''), + ), + ) + .toList(), + onChanged: (selectedCityCode) { + // Find the corresponding City object using selectedCityCode + final selectedCity = cityList + .firstWhere((city) => + city.cityCode == + selectedCityCode); + + final barangayBloc = context + .read(); + barangayBloc.add(LoadBarangay( + id: selectedCityCode! + .cityCode!)); + }, + ), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Province / City", + "", + 'province')) + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "No. / Street", "", 'street'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDropDownField( + bldgloc.barangay, + "", + 'brgy', + brgyNAmes)) + ]), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 20, + right: 0, + bottom: 10), + child: const Text('LAND REFERENCE', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + customTextField( + "Land Owner", "", 'l_owner'), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "OCT/TCT/CLOA No.", + "", + 'oct_tct_cloa'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Survey No.", + "", + 'survey_no')) + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Lot No.", "", 'lot_no'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Blk No.", "", 'blk_no')) + ]), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "TD / ARP No.", "", 'l_td_arp'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Area", "", 'area')) + ]), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon( + Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon( + Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + var bldgLocData = BldgLoc( + id: widget.tempId, + street: keys.currentState + ?.value['street'], + barangay: keys.currentState + ?.value['brgy'], + municipality: keys + .currentState + ?.value['municipality'] + ?.cityDescription ?? + bldgloc.municipality, + province: keys.currentState + ?.value['province'], + ); + var landRefData = LandRef( + id: widget.tempId, + owner: keys.currentState + ?.value['l_owner'], + cloaNo: keys.currentState + ?.value['oct_tct_cloa'], + lotNo: keys.currentState + ?.value['lot_no'], + tdn: keys.currentState + ?.value['l_td_arp'], + area: keys.currentState + ?.value['area'], + surveyNo: keys.currentState + ?.value['survey_no'], + blkNo: keys.currentState + ?.value['blk_no'], + ); + context.read() + ..add(UpdateBldgLoc( + bldg_loc: bldgLocData)) + ..add(UpdateLandRef( + land_ref: landRefData)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ) + ], + ), + ), + ), + ); + } + if (state is BarangayErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadBarangay(id: '01')); + }, + ); + } + return Container(); + }); + } + if (state is MunicipalityErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadMunicipality()); + }, + ); + } + return Container(); + }); + } + if (state is LandrefErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add( + LoadLandref(id: widget.tempId, landRef: LandRef())); + }, + ); + } + return Container(); + }, + ); + } + + if (state is LocationErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadLocation(id: widget.tempId, bldgloc: BldgLoc())); + }, + ); + } + return Container(); + }, + ), + ); + } +} diff --git a/lib/screens/passo/Building/edit_building/general_description.dart b/lib/screens/passo/Building/edit_building/general_description.dart new file mode 100644 index 0000000..201d6b7 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/general_description.dart @@ -0,0 +1,306 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/passo/bulding/general_description/general_description_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_owner_info.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +import '../add_building.dart'; + +class GeneralDescriptionEdit extends StatefulWidget { + final List unit; + final int tempId; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + GeneralDescriptionEdit(this.unit, this.tempId, this.NextBtn, this.PrevBtn); + @override + _GeneralDescriptionEdit createState() => _GeneralDescriptionEdit(); +} + +class _GeneralDescriptionEdit extends State { + final actual_use = [ + "Residential", + "Agricultural", + "Commercial", + "Industrial", + "Mineral", + "Timberland", + ]; + + @override + Widget build(BuildContext context) { + return Expanded( + child: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is GenDescLoaded) { + return FormBuilder( + key: keys, + initialValue: { + 'bldg_permit': state.gendesc.bldgPermit, + 'date_issued': state.gendesc.dateIssued.toString(), + 'cct': state.gendesc.cct.toString(), + 'coc_issued': state.gendesc.certCompletionIssued.toString(), + 'coo_issued': state.gendesc.certOccupancyIssued.toString(), + 'date_cnstructed': state.gendesc.dateIssued.toString(), + 'date_occupied': state.gendesc.dateOccupied.toString(), + 'bldg_age': state.gendesc.bldgAge.toString(), + 'no_of_storeys': state.gendesc.noStoreys.toString(), + 'area_of_1stFl': state.gendesc.area1Stfloor, + 'area_of_2ndFl': state.gendesc.area2Ndfloor, + 'area_of_3rdFl': state.gendesc.area3Rdfloor, + 'area_of_4thFl': state.gendesc.area4Thfloor, + 'total_area': state.gendesc.totalFloorArea.toString(), + 'actual_use': state.gendesc.actualUse + }, + enabled: true, + onChanged: () { + keys.currentState!.save(); + debugPrint(keys.currentState!.value.toString()); + }, + autovalidateMode: AutovalidateMode.disabled, + skipDisabled: true, + child: Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('GENERAL DESCRIPTION', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDropdown( + name: 'bldg_type', + autofocus: false, + decoration: normalTextFieldStyle( + state.gendesc.bldgKind ?? "Kind of Building", + "Kind of Building"), + items: widget.unit + .map((e) => DropdownMenuItem( + value: e, + child: + Text(e.bldgType + '-' + e.building), + )) + .toList(), + ), + ), + customDropDownField( + "Actual Use", "", 'actual_use', actual_use), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Bldg. Permit No.", "", 'bldg_permit'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Certificate of Occupancy Issued ON", + "", + 'date_issued')) + ]), + customTextField( + "Condominium Certificate of Title (CCT)", + "", + 'cct'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customDatTimePicker( + "Certificate of Completion Issued ON", + "", + 'coc_issued'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Certificate of Occupancy Issued ON", + "", + 'coo_issued')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customDatTimePicker( + "Date Constructed /Completed", + "", + 'date_cnstructed'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker( + "Date Occupied", "", 'date_occupied')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Bldg. Age", "", 'bldg_age'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "No. of storeys", "", 'no_of_storeys')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Area of 1st Floor", "", 'area_of_1stFl'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Area of 2nd Floor", + "", 'area_of_2ndFl')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("Area of 3rd Floor", + "", 'area_of_3rdFl')), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Area of 4th Floor", + "", 'area_of_4thFl')) + ]), + customTextField("Total Area", "", 'total_area'), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + keys.currentState!.save(); + var genDescData = GeneralDesc( + id: widget.tempId, + bldgKind: keys + .currentState + ?.value['bldg_type'] + ?.building ?? + state.gendesc.bldgKind, + strucType: keys + .currentState + ?.value['bldg_type'] + ?.bldgType ?? + state.gendesc.strucType, + bldgPermit: keys + .currentState?.value['bldg_permit'], + dateIssued: keys + .currentState?.value['coc_issued'], + cct: keys.currentState?.value['cct'], + certCompletionIssued: keys + .currentState?.value['coc_issued'], + certOccupancyIssued: keys + .currentState?.value['coo_issued'], + dateCompleted: keys.currentState + ?.value['date_cnstructed'], + dateOccupied: keys.currentState + ?.value['date_occupied'], + bldgAge: int.tryParse(keys.currentState?.value['bldg_age']), + noStoreys: int.tryParse(keys.currentState?.value['no_of_storeys']), + area1Stfloor: keys.currentState?.value['area_of_1stFl'], + area2Ndfloor: keys.currentState?.value['area_of_2ndFl'], + area3Rdfloor: keys.currentState?.value['area_of_3rdFl'], + area4Thfloor: keys.currentState?.value['area_of_4thFl'], + totalFloorArea: keys.currentState?.value['total_area'], + floorSketch: null, + actualUse: keys.currentState?.value['actual_use']); + + context.read() + ..add(UpdateGeneralDesc( + gen_desc: genDescData)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ) + ], + ), + ), + ), + ), + ); + } + if (state is GenDescErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add( + LoadGenDesc(id: widget.tempId, gendesc: GeneralDesc())); + }, + ); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/passo/Building/edit_building/property_appraisal.dart b/lib/screens/passo/Building/edit_building/property_appraisal.dart new file mode 100644 index 0000000..535eb1f --- /dev/null +++ b/lib/screens/passo/Building/edit_building/property_appraisal.dart @@ -0,0 +1,1135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'package:unit2/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/general_description/general_description_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart'; + +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_appraisal_edit.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_owner_info.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class PropertyAppraisalEditPage extends StatefulWidget { + final int tempId; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + PropertyAppraisalEditPage(this.tempId, this.NextBtn, this.PrevBtn); + + @override + _PropertyAppraisalEditPage createState() => _PropertyAppraisalEditPage(); +} + +class _PropertyAppraisalEditPage extends State { + double depRate = 0; + + calculateAdditionalItems(List items) { + double sum = 0; + double product = 1; + + for (AdditionalItems value in items) { + sum += double.parse(value.adjustedMarketVal); + } + + return sum; + } + + calculateMarketValue(buildingCost, additionalItems, dep) { + double sum = 0; + double depreciation = 0; + double total = 0; + + sum = buildingCost + calculateAdditionalItems(additionalItems); + + depreciation = sum * dep; + + total = sum - depreciation; + + return total; + } + + calculateDepCost(buildingCost, additionalItems, dep) { + double sum = 0; + double depreciation = 0; + double total = 0; + + sum = buildingCost + calculateAdditionalItems(additionalItems); + + depreciation = sum * dep; + + total = sum - depreciation; + + return depreciation; + } + + calculateConstructionCost(constructioncost, addtionalCost) { + double sum = 0; + sum = constructioncost + addtionalCost; + + return sum; + } + + String assessmentLevel(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return '0 '; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return '10 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return '20 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return '25 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return '80 '; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + default: + } + return ''; + } + + double assessmentValue(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return marketValue * 0; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return marketValue * 0.10; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return marketValue * 0.20; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return marketValue * 0.25; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return marketValue * 0.80; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + default: + } + return 0; + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is PropertyAppraisalEditLoaded) { + final appraisal = state.appraisalEdit; + return BlocConsumer(listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is AdditionalItemsEditLoaded) { + final item = state.items; + return BlocConsumer(listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is GenDescLoaded) { + double totalArea = double.tryParse( + state.gendesc.totalFloorArea ?? + appraisal.totalArea.toString()) ?? + 0.0; + + double bldgUnitValue = double.tryParse( + keys.currentState?.value['bldg_type']?.unitValue ?? + appraisal.unitconstructCost) ?? + 0.0; + return Expanded( + child: SingleChildScrollView( + child: Container( + margin: const EdgeInsets.only(left: 20.0, right: 20.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 20), + child: const Text('PROPERTY APPRAISAL', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Unit Construction Cost", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + bldgUnitValue.toString() + ' sq.m', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Building Core", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Sub-total", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + bldgUnitValue.toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Cost of Additional Items", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Sub-total", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + appraisal.addItemsSubtotal!, + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Total Construction Cost", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateConstructionCost( + double.parse(appraisal + .unitconstructSubtotal!), + double.parse( + appraisal.addItemsSubtotal!)) + .toString()!, + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Depreciation Rate", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + SizedBox( + width: 90, + height: 25, + child: FormBuilderTextField( + name: 'depRate', + decoration: + normalTextFieldStyle("0.00", ""), + validator: + FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + depRate = double.parse(value!); + }); + }, + ), + ), + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Depreciation Cost", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateDepCost( + (totalArea * bldgUnitValue), + item, + double.parse(keys.currentState + ?.value['depRate'] ?? + appraisal.depreciationRate)) + .toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Total % Depreciation", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + '${(double.parse(keys.currentState?.value['depRate'] ?? appraisal.depreciationRate) * 100).toStringAsFixed(2)}%', + textAlign: TextAlign.right, + ), + ) + ], + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + "Market Value", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13), + textAlign: TextAlign.left, + ), + ), + Container( + child: Text( + calculateMarketValue( + (totalArea * bldgUnitValue), + item, + double.parse(keys.currentState + ?.value['depRate'] ?? + appraisal.depreciationRate)) + .toString(), + textAlign: TextAlign.right, + ), + ) + ], + ), + Row( + children: [ + Expanded( + flex: 1, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 20.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.fromLTRB( + 0, 20, 0, 20), + child: const Text( + 'PROPERTY ASSESSMENT', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + textAlign: TextAlign.left, + ), + ), + Column( + children: [ + Row( + children: [ + Container( + width: 100, + margin: + const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all( + 5.0), + child: const Text( + 'Actual Use', + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: + TextAlign.center, + ), + ), + Container( + width: 150, + margin: + const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all( + 5.0), + child: const Text( + 'Market Value', + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: + TextAlign.center, + ), + ), + Container( + width: 100, + margin: + const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all( + 5.0), + child: const Text( + 'Ass. Level', + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: + TextAlign.center, + ), + ), + Container( + width: 150, + margin: + const EdgeInsets.only( + top: 15, left: 15), + padding: + const EdgeInsets.all( + 5.0), + child: const Text( + 'Ass. Value', + style: TextStyle( + fontWeight: + FontWeight.bold, + fontSize: 13, + ), + textAlign: + TextAlign.center, + ), + ), + ], + ), + SizedBox( + height: 50, + child: SingleChildScrollView( + scrollDirection: + Axis.horizontal, + child: Row(children: [ + Container( + height: 100, + child: Row( + children: [ + Container( + width: 100, + margin: + const EdgeInsets + .only( + top: 15, + left: 15), + padding: + const EdgeInsets + .all(5.0), + child: Text( + state.gendesc + .actualUse ?? + "", + style: TextStyle( + fontWeight: + FontWeight + .bold, + fontSize: 13, + ), + textAlign: + TextAlign + .center, + ), + ), + Container( + width: 150, + margin: + const EdgeInsets + .only( + top: 15, + left: 15), + padding: + const EdgeInsets + .all(5.0), + child: Text( + NumberFormat + .currency( + locale: 'en-PH', + symbol: "₱", + ).format( + calculateMarketValue( + (totalArea * + bldgUnitValue), + item, + double.parse(keys + .currentState + ?.value['depRate'] ?? + appraisal.depreciationRate)), + ), + style: TextStyle( + fontWeight: + FontWeight + .bold, + fontSize: 13, + ), + textAlign: + TextAlign + .center, + ), + ), + Container( + width: 100, + margin: + const EdgeInsets + .only( + top: 15, + left: 15), + padding: + const EdgeInsets + .all(5.0), + child: Text( + assessmentLevel( + calculateMarketValue( + (totalArea * bldgUnitValue), + item, + double.parse(keys.currentState?.value['depRate'] ?? appraisal.depreciationRate)) + .toString(), + state.gendesc.actualUse) + + '%', + style: TextStyle( + fontWeight: + FontWeight + .bold, + fontSize: 13, + ), + textAlign: + TextAlign + .center, + ), + ), + Container( + width: 150, + margin: + const EdgeInsets + .only( + top: 15, + left: 15), + padding: + const EdgeInsets + .all(5.0), + child: Text( + NumberFormat + .currency( + locale: 'en-PH', + symbol: "₱", + ).format(assessmentValue( + calculateMarketValue( + (totalArea * + bldgUnitValue), + item, + double.parse(keys.currentState?.value['depRate'] ?? + appraisal + .depreciationRate)) + .toString(), + state.gendesc + .actualUse)), + style: TextStyle( + fontWeight: + FontWeight + .bold, + fontSize: 13, + ), + textAlign: + TextAlign + .center, + ), + ), + const SizedBox( + height: 80, + ), + ], + ), + ) + ]), + ), + ) + ], + ) + ], + ), + ), + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () async { + final tempID = + await SharedPreferences.getInstance(); + + final id = tempID.getInt('tempid')! - 1; + { + var appraisals = PropertyAppraisalEdit( + id: 1, + bldgapprDetailsId: id, + unitconstructCost: + bldgUnitValue.toString(), + buildingCore: 'test', + unitconstructSubtotal: + (totalArea * bldgUnitValue) + .toString(), + depreciationRate: depRate.toString(), + depreciationCost: calculateDepCost( + (totalArea * bldgUnitValue), + item, + depRate) + .toString(), + costAddItems: + calculateAdditionalItems(item) + .toString(), + addItemsSubtotal: + calculateAdditionalItems(item) + .toString(), + totalpercentDepreciation: + (depRate * 100) + .toStringAsFixed(2), + marketValue: calculateMarketValue( + (totalArea * bldgUnitValue), + item, + depRate) + .toString(), + totalArea: totalArea.toString()); + context.read() + ..add(UpdatePropertyAppraisalEdit( + appraisalEdit: appraisals, + id: widget.tempId)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ) + ], + ), + ), + ), + ); + } + return Container(); + }); + } + return Container(); + }); + } + if (state is PropertyAppraisalEditErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadPropertyAppraisalEdit( + appraisalEdit: PropertyAppraisalEdit(), + id: widget.tempId, + )); + }, + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/passo/Building/edit_building/property_assessement_edit.dart b/lib/screens/passo/Building/edit_building/property_assessement_edit.dart new file mode 100644 index 0000000..e2b20e3 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/property_assessement_edit.dart @@ -0,0 +1,1093 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart'; +import 'package:unit2/bloc/passo/memoranda/memoranda_bloc.dart'; +import 'package:unit2/bloc/passo/signatories/signatories_bloc.dart'; +import 'package:unit2/model/passo/memoranda.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_appraisal_edit.dart'; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:unit2/model/passo/signatories.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/screens/passo/Building/edit_building/property_owner_info.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../model/passo/general_description.dart'; + +class PropertyAssessmentEditPage extends StatefulWidget { + int tempId; + PropertyAssessmentEditPage(this.tempId); + @override + _PropertyAssessmentEditPage createState() => _PropertyAssessmentEditPage(); +} + +class _PropertyAssessmentEditPage extends State { + double assessment_level = 0; + bool isTaxable = false; + bool isExempt = false; + String _memoranda = ''; + final focus = FocusNode(); + + String assessmentLevel(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return '0 '; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return '10 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return '20 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return '25 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return '30 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return '35 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return '40 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return '75 '; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return '80 '; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return '45 '; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return '50 '; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return '55 '; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return '60 '; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return '65 '; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return '70 '; + } + break; + default: + } + return ''; + } + + double assessmentValue(marketValues, property_class) { + final marketValue = double.parse(marketValues); + switch (property_class) { + case 'Residential': + if (marketValue < 175000) { + // setState(() { + // assessment_level = 0; + // }); + return marketValue * 0; + } else if (marketValue < 300000 && marketValue > 175000) { + // setState(() { + // assessment_level = 0.10; + // }); + return marketValue * 0.10; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.20; + // }); + return marketValue * 0.20; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.25; + // }); + return marketValue * 0.25; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } + break; + case 'Agricultural': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + case 'Commercial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + } + break; + case 'Industrial': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.30; + // }); + return marketValue * 0.30; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.35; + // }); + return marketValue * 0.35; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.40; + // }); + return marketValue * 0.40; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 5000000 && marketValue > 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } else if (marketValue < 10000000 && marketValue > 5000000) { + // setState(() { + // assessment_level = 0.75; + // }); + return marketValue * 0.75; + } else if (marketValue > 10000000) { + // setState(() { + // assessment_level = 0.80; + // }); + return marketValue * 0.80; + } + break; + case 'Mineral': + break; + case 'Timberland': + if (marketValue < 300000) { + // setState(() { + // assessment_level = 0.45; + // }); + return marketValue * 0.45; + } else if (marketValue < 500000 && marketValue > 300000) { + // setState(() { + // assessment_level = 0.50; + // }); + return marketValue * 0.50; + } else if (marketValue < 750000 && marketValue > 500000) { + // setState(() { + // assessment_level = 0.55; + // }); + return marketValue * 0.55; + } else if (marketValue < 1000000 && marketValue > 750000) { + // setState(() { + // assessment_level = 0.60; + // }); + return marketValue * 0.60; + } else if (marketValue < 2000000 && marketValue > 1000000) { + // setState(() { + // assessment_level = 0.65; + // }); + return marketValue * 0.65; + } else if (marketValue < 2000000) { + // setState(() { + // assessment_level = 0.70; + // }); + return marketValue * 0.70; + } + break; + default: + } + return 0; + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is PropertyAssessmentEditLoaded) { + final assessment = state.assessmentsEdit; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is SignatoriesLoaded) { + final signatories = state.signatories; + + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is MemorandaLoaded) { + return FormBuilder( + key: keys, + initialValue: { + 'qtr': assessment.qtr.toString(), + 'yr': assessment.qtr.toString(), + // 'appraised_by': assessment.appraisedbyName, + 'app_date': assessment.appraisedbyDate.toString(), + // 'rec_approval': assessment.recommendapprName, + 'rec_date': assessment.recommendapprDate.toString(), + // 'apprvd_by': assessment.approvedbyName, + 'memoranda': assessment.memoranda, + 'sworn_statement': assessment.swornstatementNo, + 'date_received': assessment.dateReceived.toString(), + 'date_of_entry': + assessment.entryDateAssessment.toString(), + 'by': assessment.entryDateBy + }, + enabled: true, + onChanged: () { + keys.currentState!.save(); + debugPrint(keys.currentState!.value.toString()); + }, + autovalidateMode: AutovalidateMode.disabled, + skipDisabled: true, + child: Expanded( + child: Column( + children: [ + Container( + margin: const EdgeInsets.fromLTRB(0, 20, 0, 20), + child: const Text( + 'PROPERTY ASSESSMENT cont..', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + textAlign: TextAlign.left, + ), + ), + Expanded( + flex: 3, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + const Text('Taxable'), + Checkbox( + checkColor: Colors.white, + value: isTaxable, + onChanged: (bool? value) { + setState(() { + isTaxable = value!; + }); + }, + ) + ], + ), + Row( + children: [ + const Text('Exempt'), + Checkbox( + checkColor: Colors.white, + value: isExempt, + onChanged: (bool? value) { + setState(() { + isExempt = value!; + }); + }, + ) + ], + ), + ], + ), + Column( + children: [ + const SizedBox( + height: 20, + ), + const Text( + 'EFFECTIVITY OF ASSESSMENT / REASSESSMENT :', + style: TextStyle( + fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + const Text('Qtr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'qtr', + validator: + FormBuilderValidators + .compose([]), + ), + ), + const SizedBox( + width: 20, + ), + const Text('Yr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'yr', + validator: + FormBuilderValidators + .compose([]), + ), + ), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPRAISED/ASSESSED BY:', + style: TextStyle( + fontWeight: FontWeight.bold), + textAlign: TextAlign.start, + ), + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'appraised_by', + decoration: + InputDecoration( + labelText: assessment + .appraisedbyName!, + labelStyle: + const TextStyle( + color: Colors + .black), + ), + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: + FormBuilderDateTimePicker( + name: 'app_date', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: + DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'RECOMMENDING APPROVAL:', + style: TextStyle( + fontWeight: FontWeight.bold), + )), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'rec_approval', + decoration: + InputDecoration( + labelText: assessment + .recommendapprName!, + labelStyle: + const TextStyle( + color: Colors + .black), + ), + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: + FormBuilderDateTimePicker( + name: 'rec_date', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: + DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPROVED BY:', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown< + Signatories>( + name: 'apprvd_by', + autofocus: false, + decoration: + InputDecoration( + labelText: assessment + .approvedbyName!, + labelStyle: + const TextStyle( + color: Colors + .black), + ), + items: signatories + .map((signatories) => + DropdownMenuItem( + value: + signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + ], + ), + const SizedBox( + height: 50, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'MEMORANDA: ', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + SizedBox( + height: 30, + ), + SizedBox( + width: 500, + height: 100, + child: SearchField( + itemHeight: 70, + + suggestions: state.memorada + .map((Memoranda memoranda) => + SearchFieldListItem( + '${memoranda.memoranda}', + item: + memoranda, // Change: Use individual Memoranda object + child: ListTile( + title: Text( + '${memoranda.memoranda}', + overflow: + TextOverflow + .ellipsis, + ), + ), + )) + .toList(), + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + // searchInputDecoration: + // normalTextFieldStyle( + // "Memoranda", "") + // .copyWith( + // suffixIcon: const Icon( + // Icons.arrow_drop_down), + // ), + // focusNode: focus, + suggestionState: + Suggestion.expand, + onSuggestionTap: (memoranda) { + setState(() { + _memoranda = memoranda + .item!.memoranda!; + }); + focus.unfocus(); + }, + )), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('Sworn Statement No. :'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'sworn_statement', + decoration: InputDecoration(), + validator: FormBuilderValidators + .compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('Date Received:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_received', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Date of Entry in the Rec. of Ass. :'), + SizedBox( + width: 100, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_of_entry', + initialEntryMode: + DatePickerEntryMode + .calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: const TimeOfDay( + hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('By:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'by', + decoration: InputDecoration(), + validator: FormBuilderValidators + .compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + SizedBox( + width: + MediaQuery.of(context).size.width, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: primary, + foregroundColor: Colors.red), + child: SizedBox( + width: 200, + height: 50, + child: Align( + alignment: Alignment.center, + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ), + ), + onPressed: () { + final List + propertyAssessments = []; + + PropertyAssessmentEdit ass = + PropertyAssessmentEdit( + id: 1, + bldgapprDetailsId: 440, + actualUse: assessment.actualUse, + marketValue: '0.0', + assessmentLevel: '0.0', + assessedValue: "1.0", + taxable: isTaxable, + exempt: isExempt, + qtr: int.parse(keys + .currentState! + .value['qtr']), + yr: int.parse(keys + .currentState!.value['yr']), + appraisedbyName: keys + .currentState! + .value['appraised_by'] + .firstname + + ' ' + + keys + .currentState! + .value['appraised_by'] + .middlename + + ' ' + + keys + .currentState! + .value['appraised_by'] + .lastname, + appraisedbyDate: keys + .currentState! + .value['app_date'], + recommendapprName: keys + .currentState! + .value['rec_approval'] + .firstname + + ' ' + + keys + .currentState! + .value['rec_approval'] + .middlename + + ' ' + + keys + .currentState! + .value['rec_approval'] + .lastname, + recommendapprDate: keys + .currentState! + .value['rec_date'], + approvedbyName: keys + .currentState! + .value['apprvd_by'] + .firstname + + ' ' + + keys + .currentState! + .value['apprvd_by'] + .middlename + + ' ' + + keys + .currentState! + .value['apprvd_by'] + .lastname, + memoranda: _memoranda, + swornstatementNo: keys + .currentState! + .value['sworn_statement'], + dateReceived: keys.currentState! + .value['date_received'], + entryDateAssessment: keys + .currentState! + .value['date_of_entry'], + entryDateBy: keys + .currentState!.value['by'], + ); + + propertyAssessments.add(ass); + + context.read< + PropertyAssessmentEditBloc>() + ..add( + UpdatePropertyAssessmentEdit( + assessmentsEdit: + propertyAssessments[ + 0])); + }, + ), + ), + ], + ), + )) + ], + ), + ), + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + if (state is PropertyAssessmentEditErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add( + LoadPropertyAssessmentEdit( + assessmentsEdit: PropertyAssessmentEdit(), + id: widget.tempId)); + }, + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/passo/Building/edit_building/property_owner_info.dart b/lib/screens/passo/Building/edit_building/property_owner_info.dart new file mode 100644 index 0000000..7e81231 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/property_owner_info.dart @@ -0,0 +1,229 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:multiselect/multiselect.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +GlobalKey keys = GlobalKey(); + +class PropertyOwnerInfoEdit extends StatefulWidget { + final int index; + final PropertyInfo faas; + final String title; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + const PropertyOwnerInfoEdit( + this.index, this.faas, this.title, this.NextBtn, this.PrevBtn); + + @override + State createState() => _PropertyOwnerInfoEdit(); +} + +ButtonStyle secondaryBtnStyle( + Color background, Color borderColor, Color overlay) { + return ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(background), + overlayColor: MaterialStateProperty.all(overlay), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + side: BorderSide( + width: 2, + color: borderColor, + )))); +} + +class _PropertyOwnerInfoEdit extends State { + // late List selectedFoundation = widget.faas.foundations; + // late List selectedColumns = widget.faas.columns; + // late List selectedBeams = widget.faas.beams; + // late List selectedTFraming = widget.faas.truss_framing; + // late List selectedRoof = widget.faas.roof; + // late List selectedFlooring = widget.faas.flooring; + // late List selectedWallPartition = widget.faas.walls_and_partition; + + Map myMap = {'zero': 0, 'one': 1, 'two': 2}; + + final transaction_codes = ['New', 'Revision']; + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is PropertyInfoLoaded) { + return SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Expanded( + child: Column( + children: [ + FormBuilder( + key: keys, + initialValue: { + 'transaction_code': widget.faas.transCode, + 'arp_td': widget.faas.tdn, + 'pin': widget.faas.pin, + 'owner': widget.faas.owner, + 'address': widget.faas.address, + 'tel_no': widget.faas.telno, + 'tin': widget.faas.tin, + 'benificiary': widget.faas.adminUser, + 'benificiary_telno': widget.faas.adminTelno, + 'benificiary_address': widget.faas.adminAddress, + 'benificaiary_tin': widget.faas.adminTin, + }, + enabled: true, + onChanged: () { + keys.currentState!.save(); + debugPrint(keys.currentState!.value.toString()); + }, + autovalidateMode: AutovalidateMode.disabled, + skipDisabled: true, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY OWNER INFO', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + const SizedBox(height: 15), + customDropDownField("Transaction Code", "", + "transaction_code", transaction_codes), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "ARP No. / TD No.", "", 'arp_td')), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Pin", "", 'pin')), + ], + ), + customTextField("Owner", "", 'owner'), + customTextField("Address", "", 'address'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: + customTextField("Tel No.", "", 'tel_no'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("TIN", "", 'tin')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Administrator / Benificial User", + "", + 'benificiary'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "TIN", "", 'benificiary_tin')) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Address", "", 'benificiary_address'), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField( + "Tel No.", "", 'benificiary_telno')) + ]), + const SizedBox(height: 25), + SizedBox( + width: MediaQuery.of(context).size.width, + child: CustomButton( + icon: const Icon(Icons.chevron_right, + color: Colors.white), + onPressed: () { + var property_info = PropertyInfo( + id: widget.faas.id, + transCode: keys + .currentState!.value['transaction_code'] + .toString(), + tdn: keys.currentState!.value['arp_td'], + pin: keys.currentState!.value['pin'], + owner: keys.currentState!.value['owner'], + address: + keys.currentState!.value['address'], + telno: keys.currentState!.value['tel_no'], + tin: keys.currentState!.value['tin'], + adminUser: + keys.currentState!.value['benificiary'], + adminAddress: keys.currentState! + .value['benificiary_address'], + adminTin: keys + .currentState!.value['benificiary_tin'], + adminTelno: keys.currentState! + .value['benificiary_telno'], + assessedById: '1', + assessedByName: 'Cyril', + dateModified: DateTime.now(), + dateCreated: DateTime.now()); + + context.read().add( + UpdatPropertyInfo( + property_info: property_info)); + + widget.NextBtn(); + }, + ), + ), + ])), + ], + ), + ), + ); + } + if (state is PropertyInfoErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context.read().add(LoadPropertyInfo()); + }, + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Building/edit_building/structural_materials.dart b/lib/screens/passo/Building/edit_building/structural_materials.dart new file mode 100644 index 0000000..5d37368 --- /dev/null +++ b/lib/screens/passo/Building/edit_building/structural_materials.dart @@ -0,0 +1,416 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:multiselect/multiselect.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/structural_material/structural_material_bloc.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class StructuralMaterialsPageEdit extends StatefulWidget { + // final VoidCallback onPutStructuralMaterials; + final int tempId; + final VoidCallback NextBtn; + final VoidCallback PrevBtn; + + StructuralMaterialsPageEdit(this.tempId, this.NextBtn, this.PrevBtn); + + @override + _StructuralMaterialsPageEdit createState() => _StructuralMaterialsPageEdit(); +} + +class _StructuralMaterialsPageEdit extends State { + bool foundationOthers = false; + bool columOthers = false; + bool beamsOthers = false; + bool tfOthers = false; + bool roofOthers = false; + bool flooringOthers = false; + bool wpOthers = false; + List foundation = []; + List column = []; + List beam = []; + List truss_framing = []; + List roof = []; + List flooring = []; + List walls = []; + + List selectedColumnValues = []; + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + if (state is StructuralMaterialsLoaded) { + setState(() { + foundation = state.structure.foundation!.split(','); + column = state.structure.columns!.split(','); + beam = state.structure.beams!.split(','); + truss_framing = state.structure.trussFraming!.split(','); + roof = state.structure.roof!.split(','); + flooring = state.structure.flooring!.split(','); + walls = state.structure.walls!.split(','); + // Update other local state variables here if needed + }); + } + // TODO: implement listener + }, builder: (context, state) { + if (state is StructuralMaterialsLoaded) { + return Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(30.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('STRUCTURAL MATERIALS', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'FOUNDATION', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: foundationOthers, + onChanged: (bool? value) { + setState(() { + foundationOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: foundationOthers, + child: customTextField( + "Enter other foundation", "", "other_foundation"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + foundation = x; + }); + }, + options: const ['Reinforced Concrete', 'Plain Concrete'], + selectedValues: foundation, + whenEmpty: 'Select Foundations', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'COLUMNS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: columOthers, + onChanged: (bool? value) { + setState(() { + columOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: columOthers, + child: customTextField( + "Enter other columns", "", "other_column"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + column = x; + }); + }, + options: const ['Steel', 'Reinforced Concrete', 'Wood'], + selectedValues: column, + whenEmpty: 'Select Column/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'BEAMS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: beamsOthers, + onChanged: (bool? value) { + setState(() { + beamsOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: beamsOthers, + child: + customTextField("Enter other beam/s", "", "other_beam"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + beam = x; + }); + }, + options: const ['Steel', 'Reinforced Concrete', 'Wood'], + selectedValues: beam, + whenEmpty: 'Select Beam/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'TRUSS FRAMING', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: tfOthers, + onChanged: (bool? value) { + setState(() { + tfOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: tfOthers, + child: customTextField( + "Enter other truss framing/s", "", "other_tf"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + truss_framing = x; + }); + }, + options: const ['Steel', 'Wood'], + selectedValues: truss_framing, + whenEmpty: 'Select Truss Framing/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'ROOF', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: roofOthers, + onChanged: (bool? value) { + setState(() { + roofOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: roofOthers, + child: + customTextField("Enter other roof/s", "", "other_roof"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + roof = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Tiles', + 'G.I Sheet', + 'Aluminum', + 'Asbestos', + 'Long Span', + 'Concrete Desk', + 'Nipa/Anahaw/Cogon' + ], + selectedValues: roof, + whenEmpty: 'Select Roof/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'FLOORING', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: flooringOthers, + onChanged: (bool? value) { + setState(() { + flooringOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: flooringOthers, + child: customTextField( + "Enter other flooring/s", "", "other_flooring"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + flooring = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Plain Cement', + 'Marble', + 'Wood', + 'Tiles' + ], + selectedValues: flooring, + whenEmpty: 'Select Flooring/s', + ), + ), + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + 'WALLS & PARTITIONS', + textAlign: TextAlign.start, + ), + Row( + children: [ + const Text('Others'), + Checkbox( + checkColor: Colors.white, + value: wpOthers, + onChanged: (bool? value) { + setState(() { + wpOthers = value!; + }); + }, + ) + ], + ), + ]), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Visibility( + visible: wpOthers, + child: customTextField( + "Enter other walls & partition/s", "", "other_wp"), + replacement: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.black), + onChanged: (List x) { + setState(() { + walls = x; + }); + }, + options: const [ + 'Reinforced Concrete', + 'Plain Concrete', + 'Wood', + 'CHIB', + 'G.I Sheet', + 'Build-a-wall', + 'Sawali', + 'Bamboo' + ], + selectedValues: walls, + whenEmpty: 'Select Walls & Partition/s', + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + var strucMaterials = StructureMaterialsII( + id: widget.tempId, + foundation: foundation, + columns: column, + beams: beam, + trussFraming: truss_framing, + roof: roof, + flooring: flooring, + walls: walls, + others: ["Others"]); + context.read() + ..add(UpdateStrucMaterials(data: strucMaterials)); + + widget.NextBtn(); + } + ; + }, + ) + ], + ) + ], + ), + )); + } + if (state is StructuralMaterialsErrorState) { + return Text(state.error); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Land/add_land.dart b/lib/screens/passo/Land/add_land.dart new file mode 100644 index 0000000..4b7e3aa --- /dev/null +++ b/lib/screens/passo/Land/add_land.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; + +import 'package:im_stepper/stepper.dart'; +import 'package:unit2/screens/passo/Land/add_land/land_appraisal.dart'; +import 'package:unit2/screens/passo/Land/add_land/location_and_boundaries.dart'; +import 'package:unit2/screens/passo/Land/add_land/other_improvements.dart'; +import 'package:unit2/screens/passo/Land/add_land/property_assessment.dart'; +import 'package:unit2/screens/passo/Land/add_land/property_assessment_cont.dart'; +import 'package:unit2/screens/passo/Land/add_land/property_owner_info.dart'; +import 'package:unit2/screens/passo/Land/add_land/value_adjustments.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +GlobalKey landKey = GlobalKey(); + +class AddLand extends StatefulWidget { + @override + _AddLand createState() => _AddLand(); +} + +class _AddLand extends State { + // THE FOLLOWING TWO VARIABLES ARE REQUIRED TO CONTROL THE STEPPER. + int activeStep = 0; // Initial step set to 5. + + int upperBound = 6; // upperBound MUST BE total number of icons minus 1. + + void PrevBtn() { + setState(() { + activeStep--; + }); + } + + void NextBtn() { + setState(() { + activeStep++; + }); + } + + void onSAveAll() { + return Navigator.of(context).pop(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: Text('Land FAAS'), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + NumberStepper( + numbers: [1, 2, 3, 4, 5, 6, 7], + activeStepColor: primary, + numberStyle: TextStyle(color: Colors.white), + lineColor: primary, + // activeStep property set to activeStep variable defined above. + activeStep: activeStep, + activeStepBorderColor: Colors.white, + activeStepBorderWidth: 1, + // This ensures step-tapping updates the activeStep. + onStepReached: (index) { + setState(() { + activeStep = index; + }); + }, + ), + Expanded( + child: FormBuilder( + key: landKey, + + // enabled: false, + onChanged: () { + landKey.currentState?.save(); + + print(landKey.currentState?.value.toString()); + }, + autovalidateMode: AutovalidateMode.disabled, + skipDisabled: true, + child: Container( + child: content(PrevBtn, NextBtn, onSAveAll), + ), + ), + ), + ], + ), + ), + ); + } + + /// Returns the next button. + + // Returns the content widget based on the activeStep. + Widget content(PrevBtn, NextBtn, onSAveAll) { + switch (activeStep) { + case 0: + return LandPropertyOwnerInfo(NextBtn); + case 1: + return LandLocationAndBoundaries(PrevBtn, NextBtn); + case 2: + return LandAppraisal(PrevBtn, NextBtn); + case 3: + return OtherImprovementPage(PrevBtn, NextBtn); + case 4: + return ValueAdjustmentPage(PrevBtn, NextBtn); + case 5: + return LandPropertyAssessmentPage(PrevBtn, NextBtn); + case 6: + return LandSignatories(onSAveAll); + + default: + return LandPropertyOwnerInfo(NextBtn); + } + } +} diff --git a/lib/screens/passo/Land/add_land/AddLandAppraisal.dart b/lib/screens/passo/Land/add_land/AddLandAppraisal.dart new file mode 100644 index 0000000..6e70768 --- /dev/null +++ b/lib/screens/passo/Land/add_land/AddLandAppraisal.dart @@ -0,0 +1,415 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_classification/land_classification_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart'; +import 'package:unit2/bloc/passo/municipality/municipality_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/city.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/model/passo/land_classification.dart'; +import 'package:unit2/model/passo/land_subclassification.dart'; +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class AddLandAppraisalModal extends StatefulWidget { + // final List unit; + // final List options; + // final int tempId; + + // AddLandAppraisalModal(this.unit, this.options, this.tempId); + + @override + _AddLandAppraisalModal createState() => _AddLandAppraisalModal(); +} + +class _AddLandAppraisalModal extends State { + final focus = FocusNode(); + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + final double _depValue = 0; + double _unitValue = 0; + String _subClassDesc = ""; + int _classId = 0; + String _structureType = ""; + bool _withoutBUCC = false; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + String cityCode = ''; + String cityDesc = ''; + int classCode = 1; + String _classDesc = ''; + + GlobalKey appraisalLandKey = GlobalKey(); + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + double _amountofDepreciation(unitVal, unitBase, area, depreciation) { + return ((unitVal * unitBase) * area) * depreciation; + } + + double _totalMarketValue(unitBase, area) { + return unitBase * area; + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddLandAppraisalScreen) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is LandClassificationLoaded) { + final classification = state.land_classification; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is LandSubClassificationLoaded) { + final subclassification = state.land_subclassification; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is MunicipalityLoaded) { + return FormBuilder( + key: appraisalLandKey, + onChanged: () { + appraisalLandKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: 800, + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: + FormBuilderDropdown( + name: + 'appraisal_municipality', + autofocus: false, + decoration: + normalTextFieldStyle( + cityDesc ?? + "Municipality", + ""), + items: state.municipality + .map((municipality) => + DropdownMenuItem< + City>( + value: municipality, + child: Text(municipality + .cityDescription!), // Use cityDescription instead of cityName + )) + .toList(), + onChanged: (selectedCity) { + if (selectedCity != null) { + final selectedCityCode = + selectedCity.cityCode; + setState(() { + cityCode = + selectedCityCode!; + cityDesc = selectedCity + .cityDescription!; + }); + final barangayBloc = + context.read< + LandSubClassificationBloc>(); + barangayBloc.add( + LoadLandSubClassification( + classCode: + classCode!, + cityCode: + selectedCityCode!)); // Use selectedCityCode directly + } + }, + )), + ), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown< + LandClassification>( + name: 'classification', + autofocus: false, + decoration: + normalTextFieldStyle( + _classDesc + .toString() ?? + "Classification", + ""), + items: classification + .map((classification) => + DropdownMenuItem< + LandClassification>( + value: + classification, + child: Text( + classification + .description!), // Use cityDescription instead of cityName + )) + .toList(), + onChanged: (selectedClass) { + if (selectedClass != null) { + final selectedClassCode = + selectedClass.id; + setState(() { + classCode = + selectedClassCode!; + _classDesc = + selectedClass + .description!; + }); + final barangayBloc = + context.read< + LandSubClassificationBloc>(); + barangayBloc.add( + LoadLandSubClassification( + classCode: + selectedClassCode!, + cityCode: + cityCode)); // Use selectedCityCode directly + } + }, + )), + ), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: SizedBox( + height: 45, + child: SearchField( + itemHeight: 70, + suggestions: subclassification + .map((LandSubClassification + subclass) => + SearchFieldListItem( + '${subclass.subclassCode} - ${subclass.subclassDescription}', + item: subclass, + child: ListTile( + title: Text( + '${subclass.subclassCode} - ${subclass.subclassDescription!.toUpperCase()}', + overflow: + TextOverflow + .ellipsis, + ), + ))) + .toList(), + + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + + searchInputDecoration: + normalTextFieldStyle( + "Structure Type", + "") + .copyWith( + suffixIcon: + const Icon(Icons + .arrow_drop_down)), + ////agency suggestion tap + focusNode: focus, + suggestionState: + Suggestion.expand, + onSuggestionTap: (subclass) { + setState(() { + _unitBase = double.parse( + subclass.item! + .baseUnitMarketval!); + _subClassDesc = + '${subclass.item!.subclassCode} - ${subclass.item!.subclassDescription}'; + }); + focus.unfocus(); + }, + ), + ), + ), + const SizedBox(height: 10), + FormBuilderTextField( + name: 'land_appraisal_area', + decoration: normalTextFieldStyle( + "Area", ""), + validator: + FormBuilderValidators.compose( + []), + onChanged: (value) { + setState(() { + _areaValue = int.parse(value!); + }); + }, + ), + const SizedBox(height: 10), + const Text('Market Value'), + const SizedBox(height: 5), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text( + NumberFormat.currency( + locale: 'en-PH', + symbol: "₱") + .format( + _totalMarketValue( + _unitBase, + _areaValue)))), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: + const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences + .getInstance(); + print(tempID + .getInt('landid')); + var land_appraisal = LandAppr( + landapprDetailsId: + tempID.getInt( + 'landid')! - + 1, + classification: + _classDesc, + subClass: _subClassDesc, + area: _areaValue + .toString(), + unitValue: _unitBase + .toString(), + baseMarketval: + _totalMarketValue( + _unitBase, + _areaValue) + .toString()); + + context + .read< + LandAppraisalBloc>() + .add(AddLandAppraisal( + land_appr: + land_appraisal)); + }, + style: + ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + const SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: + const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read< + LandAppraisalBloc>() + .add( + const LoadLandAppraisal()); + }, + style: + ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ))); + } + if (state is MunicipalityErrorState) { + return Text(state.error); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + if (state is LandAppraisalErrorState) { + return Text(state.error); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/AddLandValueAdjustmentModal.dart b/lib/screens/passo/Land/add_land/AddLandValueAdjustmentModal.dart new file mode 100644 index 0000000..64a53b6 --- /dev/null +++ b/lib/screens/passo/Land/add_land/AddLandValueAdjustmentModal.dart @@ -0,0 +1,467 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_location/type_of_location_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_road/type_of_road_bloc.dart'; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/model/passo/land_value_adjustment.dart'; +import 'package:unit2/model/passo/type_of_location.dart'; +import 'package:unit2/model/passo/type_of_road.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +class AddLandValueAdjustmentModal extends StatefulWidget { + // final List unit; + // final List options; + // final int tempId; + + // AddLandAppraisalModal(this.unit, this.options, this.tempId); + + @override + _AddLandValueAdjustmentModal createState() => _AddLandValueAdjustmentModal(); +} + +class _AddLandValueAdjustmentModal extends State { + final focus = FocusNode(); + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + final double _depValue = 0; + double _unitValue = 0; + String _subClassDesc = ""; + int _classId = 0; + String _structureType = ""; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + String cityCode = ''; + String cityDesc = ''; + int classCode = 1; + String _classDesc = ''; + String _treeType = ""; + bool _nonfruitBearing = false; + bool _fruitBearing = false; + int qty = 0; + int pr_qty = 0; + int nonpr_qty = 0; + double _roadTypeDeduction = 0; + double _locTypeRoad = 0; + double _locTypePob = 0; + String _roadType = ''; + String _distance = ''; + String _locRdDistance = ''; + String _locPobDistance = ''; + + GlobalKey otherImpKey = GlobalKey(); + + _calculateBaseMarketValue() { + double base = 0.00; + if (_fruitBearing) { + base = (pr_qty + nonpr_qty) * _unitValue; + } else { + base = qty * _unitValue; + } + return base; + } + + double calculateAdjustment() { + double adjustment = 0; + + if (_locPobDistance == '0 TO 1') { + adjustment = _locTypePob - (_roadTypeDeduction + _locTypeRoad); + } else { + adjustment = (_roadTypeDeduction + _locTypeRoad + _locTypePob) * -1; + } + + return adjustment; + } + + double calculateValueAdjustment() { + double adjustment = calculateAdjustment(); + double valueAdjustment = _unitValue * adjustment; + + return valueAdjustment; + } + + double calculateMarketValue() { + double marketValue = 0; + + marketValue = _unitValue + calculateValueAdjustment(); // Adding adjustment + + return marketValue; + } + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddLandValueAdjustmentsScreen) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is LandAppraisalLoaded) { + final land_appr = state.land_appr; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is TypeOfRoadLoaded) { + final roadType = state.road_type; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is TypeOfLocationLoaded) { + return FormBuilder( + key: otherImpKey, + onChanged: () { + otherImpKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: + FormBuilderDropdown( + name: 'land_appr_item', + autofocus: false, + decoration: normalTextFieldStyle( + "Land Appraisal Items", ""), + items: land_appr + .map((land_appr) => + DropdownMenuItem< + LandAppr?>( + value: land_appr, + child: Text((land_appr + .subClass ?? + "")), + )) + .toList(), + onChanged: (selectedLandAppr) { + if (selectedLandAppr != null) { + setState(() { + _unitValue = double.parse( + selectedLandAppr + .baseMarketval!); + }); + } + }, + )), + ), + SizedBox( + height: 10, + ), + Text("Adjustment Factors"), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown< + TypeOfRoad?>( + name: 'road_type', + autofocus: false, + decoration: normalTextFieldStyle( + "Type of Road", ""), + items: roadType + .map((roadType) => + DropdownMenuItem< + TypeOfRoad?>( + value: roadType, + child: Text((roadType + .roadType ?? + "")), + )) + .toList(), + onChanged: (selectedRoad) { + if (selectedRoad != null) { + setState(() { + _roadTypeDeduction = + double.parse( + selectedRoad + .deduction!); + _roadType = + selectedRoad.roadType!; + }); + } + }, + )), + ), + SizedBox( + height: 10, + ), + Text("Type of Location"), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown< + TypeOfLocation?>( + name: 'loc_type_road', + autofocus: false, + decoration: normalTextFieldStyle( + "Distance to Road", ""), + items: state.loc_type + .map((locTypeRoad) => + DropdownMenuItem< + TypeOfLocation?>( + value: locTypeRoad, + child: Text((locTypeRoad + .distanceKm ?? + "")), + )) + .toList(), + onChanged: (selectedLoadRoad) { + if (selectedLoadRoad != null) { + setState(() { + _locTypeRoad = double.parse( + selectedLoadRoad + .allRoadTypes!); + _locRdDistance = + selectedLoadRoad + .distanceKm!; + }); + } + }, + )), + ), + Container( + margin: const EdgeInsets.only( + left: 0, + top: 10, + right: 0, + bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown< + TypeOfLocation?>( + name: 'loc_type_pob', + autofocus: false, + decoration: normalTextFieldStyle( + "Distance to Poblacion", ""), + items: state.loc_type + .map((locTypePob) => + DropdownMenuItem< + TypeOfLocation?>( + value: locTypePob, + child: Text((locTypePob + .distanceKm ?? + "")), + )) + .toList(), + onChanged: (selectedLocPob) { + if (selectedLocPob != null) { + setState(() { + _locTypePob = double.parse( + selectedLocPob + .localTradingCenter!); + + _locPobDistance = + selectedLocPob + .distanceKm!; + }); + } + }, + )), + ), + const SizedBox(height: 10), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text( + (calculateAdjustment() * 100) + .toString() + + '%'), + ), + ), + const SizedBox(height: 10), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', + symbol: "₱", + ).format(calculateValueAdjustment())), + ), + ), + const SizedBox(height: 10), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', + symbol: "₱", + ).format(calculateMarketValue())), + ), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences + .getInstance(); + print(tempID.getInt('landid')); + var adjustments = ValueAdjustments( + landapprDetailsId: tempID + .getInt('landid')! - + 1, + baseMarketval: + _unitValue.toString(), + adjustmentFactors: + _roadType + + ' , ' + + _locPobDistance + + ' km from road , ' + + _locPobDistance + + ' km from poblacion', + adjustment: + calculateAdjustment() + .toString(), + valueAdjustment: + calculateValueAdjustment() + .toString(), + marketValue: + calculateMarketValue() + .toString()); + + context + .read< + LandValueAdjustmentsBloc>() + .add( + AddLandValueAdjustments( + val_adj: + adjustments)); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + const SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read< + LandValueAdjustmentsBloc>() + .add( + const LoadLandValueAdjustments()); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ), + )); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + + return Container(); + }); + } + if (state is LandValueAdjustmentsErrorState) { + return Text(state.error); + } + return Container( + child: Text("Land Value Adjustment"), + ); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/AddOtherImprovementModal.dart b/lib/screens/passo/Land/add_land/AddOtherImprovementModal.dart new file mode 100644 index 0000000..c89300d --- /dev/null +++ b/lib/screens/passo/Land/add_land/AddOtherImprovementModal.dart @@ -0,0 +1,344 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart'; +import 'package:unit2/bloc/passo/land/other_improvements/other_improvements_bloc.dart'; +import 'package:unit2/model/passo/other_improvements.dart'; +import 'package:unit2/model/passo/trees_improvements.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +class AddOtherImprovementModal extends StatefulWidget { + // final List unit; + // final List options; + // final int tempId; + + // AddLandAppraisalModal(this.unit, this.options, this.tempId); + + @override + _AddOtherImprovementModal createState() => _AddOtherImprovementModal(); +} + +class _AddOtherImprovementModal extends State { + final focus = FocusNode(); + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + final double _depValue = 0; + double _unitValue = 0; + String _subClassDesc = ""; + int _classId = 0; + String _structureType = ""; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + String cityCode = ''; + String cityDesc = ''; + int classCode = 1; + String _classDesc = ''; + String _treeType = ""; + bool _nonfruitBearing = false; + bool _fruitBearing = false; + int qty = 0; + int pr_qty = 0; + int nonpr_qty = 0; + + GlobalKey otherImpKey = GlobalKey(); + + final typeOfTree = [ + "Non-Fruit Bearing", + "Fruit Bearing", + ]; + + _calculateBaseMarketValue() { + double base = 0.00; + if (_fruitBearing) { + base = (pr_qty + nonpr_qty) * _unitValue; + } else { + base = qty * _unitValue; + } + return base; + } + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + double _amountofDepreciation(unitVal, unitBase, area, depreciation) { + return ((unitVal * unitBase) * area) * depreciation; + } + + double _totalMarketValue(unitBase, area) { + return unitBase * area; + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddOtherImprovementScreen) { + return BlocConsumer(listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is LandTreesImprovementsLoaded) { + final trees = state.trees_imp; + return FormBuilder( + key: otherImpKey, + onChanged: () { + otherImpKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown( + name: 'kinds_of_trees', + autofocus: false, + decoration: normalTextFieldStyle( + "Kinds of Trees", ""), + items: state.trees_imp + .map((trees) => + DropdownMenuItem( + value: trees, + child: Text( + (trees.improvement ?? "") + + " " + + (trees.subclassCode ?? ""), + ), + )) + .toList(), + onChanged: (selectedTree) { + if (selectedTree != null) { + setState(() { + _unitValue = double.parse( + selectedTree.pricePerTree!); + _treeType = selectedTree.improvement!; + }); + } + }, + )), + ), + Container( + child: Row( + children: [ + Row( + children: [ + Checkbox( + value: _fruitBearing, + onChanged: (bool? value) { + setState(() { + _fruitBearing = value!; + }); + }, + ), + Text('Fruit Bearing ?'), + ], + ), + ], + ), + ), + Visibility( + visible: !_fruitBearing, + child: Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'subClass', + decoration: normalTextFieldStyle( + "SubClass/Age", ""), + validator: + FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + _subClassDesc = value!; + }); + }, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: FormBuilderTextField( + name: 'qty', + decoration: normalTextFieldStyle("No.", ""), + validator: + FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + qty = int.parse(value!); + }); + }, + ), + ), + ], + ), + replacement: Column( + children: [ + FormBuilderTextField( + name: 'no_of_productive', + decoration: normalTextFieldStyle( + "No. of Productive", ""), + validator: FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + pr_qty = int.parse(value!); + }); + }, + ), + const SizedBox(height: 10), + FormBuilderTextField( + name: 'no_of_nonproductive', + decoration: normalTextFieldStyle( + "No. of Non-Productive", ""), + validator: FormBuilderValidators.compose([]), + onChanged: (value) { + setState(() { + nonpr_qty = int.parse(value!); + }); + }, + ), + ], + ), + ), + const SizedBox(height: 10), + const Text('Market Value'), + const SizedBox(height: 5), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', symbol: "₱") + .format(_unitValue))), + ), + const SizedBox(height: 10), + const Text('Base Market Value'), + const SizedBox(height: 5), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', + symbol: "₱", + ).format(_calculateBaseMarketValue().toString() == + "0.00" + ? "00.0" + : _calculateBaseMarketValue())), + ), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences.getInstance(); + print(tempID.getInt('landid')); + var improvement = OtherImprovements( + landapprDetailsId: + tempID.getInt('landid')! - 1, + kindsOfTrees: _treeType, + subclassAge: _subClassDesc, + quantity: qty, + unitValue: _unitValue.toString(), + baseMarketval: + _calculateBaseMarketValue() + .toString(), + noOfProductive: pr_qty, + noOfNonproductive: nonpr_qty, + fruitBearing: _fruitBearing); + + context.read().add( + AddOtherImprovement( + other_imp: improvement)); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + const SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read() + .add(const LoadOtherImprovement()); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ), + )); + } + + return Container(); + }); + } + if (state is OtherImprovementErrorState) { + return Text(state.error); + } + return Container( + child: Text("Other Improvement"), + ); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/AddPropertyAssessmentModal.dart b/lib/screens/passo/Land/add_land/AddPropertyAssessmentModal.dart new file mode 100644 index 0000000..35bf7f6 --- /dev/null +++ b/lib/screens/passo/Land/add_land/AddPropertyAssessmentModal.dart @@ -0,0 +1,342 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart'; +import 'package:unit2/model/passo/land_property_assessment.dart'; +import 'package:unit2/model/passo/land_value_adjustment.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +class AddPropertyAssessmentModal extends StatefulWidget { + // final List unit; + // final List options; + // final int tempId; + + // AddLandAppraisalModal(this.unit, this.options, this.tempId); + + @override + _AddPropertyAssessmentModal createState() => _AddPropertyAssessmentModal(); +} + +class _AddPropertyAssessmentModal extends State { + final focus = FocusNode(); + bool isPainted = false; + bool isSecondHand = false; + TextEditingController textEditingController = TextEditingController(); + double _unitBase = 0; + int _areaValue = 0; + final double _depValue = 0; + double _unitValue = 0; + String _subClassDesc = ""; + int _classId = 0; + String _structureType = ""; + int _notPaintedUnitVal = 0; + int _secondHandUnitVal = 0; + String cityCode = ''; + String cityDesc = ''; + int classCode = 1; + String _classDesc = ''; + String _treeType = ""; + bool _nonfruitBearing = false; + bool _fruitBearing = false; + int qty = 0; + int pr_qty = 0; + int nonpr_qty = 0; + String _actualUse = "Residential"; + String _assessmentLevel = ""; + + GlobalKey assessmentKey = GlobalKey(); + + final typeOfTree = [ + "Non-Fruit Bearing", + "Fruit Bearing", + ]; + + final actual_use = [ + "Residential", + "Agricultural", + "Commercial", + "Industrial", + "Mineral", + "Timberland", + ]; + + calculateAssessmentValue() { + switch (_actualUse) { + case "Residential": + return _unitValue * 0.20; + break; + case "Agricultural": + return _unitValue * 0.40; + break; + case "Commercial": + return _unitValue * 0.50; + break; + case "Industrial": + return _unitValue * 0.50; + break; + case "Mineral": + return _unitValue * 0.50; + break; + case "Timberland": + return _unitValue * 0.20; + break; + default: + } + } + + BoxDecoration box1() { + return const BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 5, blurRadius: 5) + ], color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(3))); + } + + double _amountofDepreciation(unitVal, unitBase, area, depreciation) { + return ((unitVal * unitBase) * area) * depreciation; + } + + double _totalMarketValue(unitBase, area) { + return unitBase * area; + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, builder: (context, state) { + if (state is ShowAddLandPropertyAssessmentScreen) { + return BlocConsumer(listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + if (state is LandValueAdjustmentsLoaded) { + final assessment = state.val_adj; + return FormBuilder( + key: assessmentKey, + onChanged: () { + assessmentKey.currentState?.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 10, right: 0, bottom: 0), + child: Expanded( + flex: 1, + child: FormBuilderDropdown( + name: 'value_adjustments', + autofocus: false, + decoration: normalTextFieldStyle( + "Value Adjustments", ""), + items: state.val_adj + .map((adj) => + DropdownMenuItem( + value: adj, + child: Text( + (adj.adjustmentFactors ?? ""), + ), + )) + .toList(), + onChanged: (selectedAdj) { + if (selectedAdj != null) { + setState(() { + _unitValue = double.parse( + selectedAdj.marketValue!); + }); + } + }, + )), + ), + SizedBox( + height: 10, + ), + FormBuilderDropdown( + name: "land_actual_use", + autofocus: false, + decoration: normalTextFieldStyle("Actual Use", ""), + items: actual_use + .map((item) => DropdownMenuItem( + value: item, + child: Text(item), + )) + .toList(), + onChanged: (value) { + setState(() { + _actualUse = value!; + + switch (value) { + case "Residential": + setState(() { + _assessmentLevel = '20'; + }); + + break; + case "Agricultural": + setState(() { + _assessmentLevel = '40'; + }); + + break; + case "Commercial": + setState(() { + _assessmentLevel = '50'; + }); + + break; + case "Industrial": + setState(() { + _assessmentLevel = '50'; + }); + + break; + case "Mineral": + setState(() { + _assessmentLevel = '50'; + }); + + break; + case "Timberland": + setState(() { + _assessmentLevel = '20'; + }); + + break; + default: + } + }); + }, + ), + SizedBox( + height: 10, + ), + Text('Assessment Level'), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(_assessmentLevel + '%'), + ), + ), + SizedBox( + height: 10, + ), + Text('Assessment Value'), + Container( + height: 45.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(5.0), + ), + child: Align( + alignment: Alignment.center, + child: Text(NumberFormat.currency( + locale: 'en-PH', + symbol: "₱", + ).format(calculateAssessmentValue().toString() == + "0.00" + ? "00.0" + : calculateAssessmentValue())), + ), + ), + const SizedBox(height: 10), + Row( + children: [ + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences.getInstance(); + print(tempID.getInt('landid')! - 1); + var assessment = LandPropertyAssessment( + landapprDetailsId: + tempID.getInt('landid')! - 1, + actualUse: _actualUse, + marketval: _unitValue.toString(), + assessmentLevel: _assessmentLevel, + assessedValue: + calculateAssessmentValue() + .toString(), + totalMarketval: '0', + totalAssessedval: '0'); + + context + .read() + .add(AddLandPropertyAssessment( + assessment: assessment)); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Submit"), + ), + ), + const SizedBox( + width: + 5), // Use SizedBox for horizontal spacing in a Row + Container( + width: 120, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + context + .read() + .add( + const LoadLandPropertyAssessment()); + }, + style: ElevatedButton.styleFrom( + primary: Colors.black, + ), + child: const Text("Cancel"), + ), + ), + ], + ) + ], + ), + ), + ), + )); + } + + return Container(); + }); + } + if (state is LandPropertyAssessmentErrorState) { + return Text(state.error); + } + return Container( + child: Text("Property Assessment"), + ); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/land_appraisal.dart b/lib/screens/passo/Land/add_land/land_appraisal.dart new file mode 100644 index 0000000..fa0ca77 --- /dev/null +++ b/lib/screens/passo/Land/add_land/land_appraisal.dart @@ -0,0 +1,248 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart'; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/screens/passo/Land/add_land/AddLandAppraisal.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class LandAppraisal extends StatefulWidget { + Function PrevBtn; + Function NextBtn; + LandAppraisal(this.PrevBtn, this.NextBtn); + @override + _LandAppraisal createState() => _LandAppraisal(); +} + +class _LandAppraisal extends State { + // double _totalMarketValue(items) { + // double total = 0; + // items.forEach((row) { + // total += double.parse(row); + // }); + // return total; + // } + + void deleteItem(int itemId) { + context.read().add(DeleteLandAppraisal(id: itemId)); + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + final state = context.watch().state; + if (state is LandAppraisalLoaded) { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('LAND APPRAISAL', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowLandAppraisal()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Classification'), + ), + const DataColumn( + label: Text('Sub-Classification'), + ), + const DataColumn( + label: Text('Area'), + ), + const DataColumn( + label: Text('Unit Value'), + ), + const DataColumn( + label: Text('Base MArket Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.land_appr.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.classification!)), + DataCell(Text(dataRow.subClass!)), + DataCell(Text(dataRow.area!)), + DataCell(Text( + ((double.parse(dataRow.unitValue!))) + .toString())), + DataCell(Text( + ((double.parse(dataRow.baseMarketval!))) + .toString())), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id!); + }, + ), + SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList())) + ], + ), + ), + )), + // Padding( + // padding: const EdgeInsets.only(left: 20.0, right: 20.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // 'Total', + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ), + // Text( + // NumberFormat.currency(locale: 'en-PH', symbol: "₱") + // .format('1.0'), + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ) + // ], + // ), + // ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is LandAppraisalDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context.read().add(const LoadLandAppraisal()); + }); + }); + } + } + if (state is ShowAddLandAppraisalScreen) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: Text( + 'ADD LAND APPRAISAL', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [Expanded(child: AddLandAppraisalModal())], + ), + ), + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/location_and_boundaries.dart b/lib/screens/passo/Land/add_land/location_and_boundaries.dart new file mode 100644 index 0000000..f27db38 --- /dev/null +++ b/lib/screens/passo/Land/add_land/location_and_boundaries.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart'; +import 'package:unit2/model/passo/land_property_boundaries.dart'; +import 'package:unit2/model/passo/land_property_loc.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class LandLocationAndBoundaries extends StatefulWidget { + Function PrevBtn; + Function NextBtn; + LandLocationAndBoundaries(this.PrevBtn, this.NextBtn); + @override + _LandLocationAndBoundaries createState() => _LandLocationAndBoundaries(); +} + +class _LandLocationAndBoundaries extends State { + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY LOCATION', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("No. / Street", "", "street")), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Brgy./District", "", "brgy")), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: + customTextField("Municipality", "", "municipality"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Province/City", "", "province")) + ]), + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY BOUNDARIES', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("North", "", "north"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("East", "", "east")) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("South", "", "south"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("West", "", "west")) + ]), + SizedBox( + height: 50, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left, color: Colors.white), + onPressed: () { + widget.PrevBtn(); + }), + CustomButton( + icon: + const Icon(Icons.chevron_right, color: Colors.white), + onPressed: () { + var boundaries = LandPropertyBoundaries( + id: 3, + north: landKey.currentState?.value['north'], + east: landKey.currentState?.value['east'], + west: landKey.currentState?.value['west'], + south: landKey.currentState?.value['south'], + ); + var location = LandPropertyLoc( + id: 3, + street: landKey.currentState?.value['street'], + barangay: landKey.currentState?.value['brgy'], + municipality: + landKey.currentState?.value['municipality'], + province: landKey.currentState?.value['province'], + ); + + context.read() + ..add( + UpdateLandBoundaries(land_boundaries: boundaries)) + ..add(UpdateLandLoc(land_loc: location)); + + widget.NextBtn(); + }) + ], + ) + ]), + ), + ); + } +} diff --git a/lib/screens/passo/Land/add_land/other_improvements.dart b/lib/screens/passo/Land/add_land/other_improvements.dart new file mode 100644 index 0000000..295e1b7 --- /dev/null +++ b/lib/screens/passo/Land/add_land/other_improvements.dart @@ -0,0 +1,263 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/land/other_improvements/other_improvements_bloc.dart'; +import 'package:unit2/screens/passo/Land/add_land/AddOtherImprovementModal.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class OtherImprovementPage extends StatefulWidget { + Function PrevBtn; + Function NextBtn; + OtherImprovementPage(this.PrevBtn, this.NextBtn); + @override + _OtherImprovementPage createState() => _OtherImprovementPage(); +} + +class _OtherImprovementPage extends State { + // double _totalMarketValue(items) { + // double total = 0; + // items.forEach((row) { + // total += double.parse(row); + // }); + // return total; + // } + + void deleteItem(int itemId) { + context + .read() + .add(DeleteOtherImprovement(id: itemId)); + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + final state = context.watch().state; + if (state is OtherImprovementLoaded) { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('OTHER IMPROVEMENTS', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowOtherImprovement()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Kinds of Tress'), + ), + const DataColumn( + label: Text('Sub-Class / Age'), + ), + const DataColumn( + label: Text('Type of Tree'), + ), + const DataColumn( + label: Text('No.'), + ), + const DataColumn( + label: Text('No. of Productive'), + ), + const DataColumn( + label: Text('No. of Non-Productive'), + ), + const DataColumn( + label: Text('Unit Value'), + ), + const DataColumn( + label: Text('Base Market Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.other_imp.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.kindsOfTrees!)), + DataCell(Text(dataRow.subclassAge!)), + DataCell(Text(dataRow.fruitBearing! + ? "Fruit Bearing" + : "Non-Fruit Bearing")), + DataCell(Text(dataRow.quantity.toString()!)), + DataCell( + Text(dataRow.noOfProductive.toString()!)), + DataCell(Text( + dataRow.noOfNonproductive.toString()!)), + DataCell(Text(dataRow.unitValue.toString()!)), + DataCell( + Text(dataRow.baseMarketval.toString()!)), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id!); + }, + ), + SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList())) + ], + ), + ), + )), + // Padding( + // padding: const EdgeInsets.only(left: 20.0, right: 20.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // 'Total', + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ), + // Text( + // NumberFormat.currency(locale: 'en-PH', symbol: "₱") + // .format('1.0'), + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ) + // ], + // ), + // ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is OtherImprovementDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadOtherImprovement()); + }); + }); + } + } + if (state is ShowAddOtherImprovementScreen) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: Text( + 'ADD OTHER IMPROVEMENTS', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [Expanded(child: AddOtherImprovementModal())], + ), + ), + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/property_assessment.dart b/lib/screens/passo/Land/add_land/property_assessment.dart new file mode 100644 index 0000000..19f43bf --- /dev/null +++ b/lib/screens/passo/Land/add_land/property_assessment.dart @@ -0,0 +1,243 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart'; +import 'package:unit2/screens/passo/Land/add_land/AddPropertyAssessmentModal.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class LandPropertyAssessmentPage extends StatefulWidget { + Function PrevBtn; + Function NextBtn; + LandPropertyAssessmentPage(this.PrevBtn, this.NextBtn); + @override + _LandPropertyAssessmentPage createState() => _LandPropertyAssessmentPage(); +} + +class _LandPropertyAssessmentPage extends State { + // double _totalMarketValue(items) { + // double total = 0; + // items.forEach((row) { + // total += double.parse(row); + // }); + // return total; + // } + + void deleteItem(int itemId) { + context + .read() + .add(DeleteLandPropertyAssessment(id: itemId)); + } + + @override + Widget build(BuildContext context) { + return BlocConsumer(listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + final state = context.watch().state; + if (state is LandPropertyAssessmentLoaded) { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY ASSESSMENT', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowLandPropertyAssessment()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Actual Use'), + ), + const DataColumn( + label: Text('Market Value'), + ), + const DataColumn( + label: Text('Assessment Level'), + ), + const DataColumn( + label: Text('Assessed Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.assessment.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.actualUse!)), + DataCell(Text(dataRow.marketval!)), + DataCell( + Text(dataRow.assessmentLevel! + '%')), + DataCell(Text(dataRow.assessedValue!)), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id!); + }, + ), + SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList())) + ], + ), + ), + )), + // Padding( + // padding: const EdgeInsets.only(left: 20.0, right: 20.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // 'Total', + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ), + // Text( + // NumberFormat.currency(locale: 'en-PH', symbol: "₱") + // .format('1.0'), + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ) + // ], + // ), + // ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is LandPropertyAssessmentDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadLandPropertyAssessment()); + }); + }); + } + } + if (state is ShowAddLandPropertyAssessmentScreen) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: Text( + 'ADD PROPERTY ASSESSMENT', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [Expanded(child: AddPropertyAssessmentModal())], + ), + ), + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Land/add_land/property_assessment_cont.dart b/lib/screens/passo/Land/add_land/property_assessment_cont.dart new file mode 100644 index 0000000..ad1f710 --- /dev/null +++ b/lib/screens/passo/Land/add_land/property_assessment_cont.dart @@ -0,0 +1,541 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/bloc/passo/land/land_ext/land_ext_bloc.dart'; +import 'package:unit2/bloc/passo/memoranda/memoranda_bloc.dart'; +import 'package:unit2/bloc/passo/signatories/signatories_bloc.dart'; +import 'package:unit2/model/passo/land_ext.dart'; +import 'package:unit2/model/passo/memoranda.dart'; +import 'package:unit2/model/passo/signatories.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class LandSignatories extends StatefulWidget { + Function onSAve; + LandSignatories(this.onSAve); + + @override + _LandSignatories createState() => _LandSignatories(); +} + +class _LandSignatories extends State { + bool isTaxable = false; + bool isExempt = false; + final focus = FocusNode(); + String _memoranda = ""; + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is LandExtLoaded) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is SignatoriesLoaded) { + final signatories = state.signatories; + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, + builder: (context, state) { + if (state is MemorandaLoaded) { + return SingleChildScrollView( + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY ASSESSMENT cont..', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + const Text('Taxable'), + Checkbox( + checkColor: Colors.white, + value: isTaxable, + onChanged: (bool? value) { + setState(() { + isTaxable = value!; + }); + }, + ) + ], + ), + Row( + children: [ + const Text('Exempt'), + Checkbox( + checkColor: Colors.white, + value: isExempt, + onChanged: (bool? value) { + setState(() { + isExempt = value!; + }); + }, + ) + ], + ), + ], + ), + Column( + children: [ + const SizedBox( + height: 20, + ), + const Text( + 'EFFECTIVITY OF ASSESSMENT / REASSESSMENT :', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + const Text('Qtr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'land_qtr', + validator: + FormBuilderValidators.compose([]), + ), + ), + const SizedBox( + width: 20, + ), + const Text('Yr.'), + SizedBox( + width: 70, + height: 25, + child: FormBuilderTextField( + name: 'land_yr', + validator: + FormBuilderValidators.compose([]), + ), + ), + ], + ), + ], + ), + Container( + margin: const EdgeInsets.only( + left: 0, top: 40, right: 0, bottom: 10), + child: const Text('SIGNATORIES', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + const SizedBox( + height: 30, + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPRAISED/ASSESSED BY:', + style: TextStyle(fontWeight: FontWeight.bold), + textAlign: TextAlign.start, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown( + name: 'appraised_by_land', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: FormBuilderDateTimePicker( + name: 'app_date_land', + initialEntryMode: + DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'RECOMMENDING APPROVAL:', + style: TextStyle(fontWeight: FontWeight.bold), + )), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown( + name: 'rec_approval_land', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: FormBuilderDateTimePicker( + name: 'rec_date_land', + initialEntryMode: + DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 30, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'APPROVED BY:', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + SizedBox( + width: 200, + child: FormBuilderDropdown( + name: 'apprvd_by_land', + autofocus: false, + items: signatories + .map((signatories) => + DropdownMenuItem( + value: signatories, + child: Text( + '${signatories.firstname} ${signatories.middlename} ${signatories.lastname}'), + )) + .toList()), + ), + Text('Name'), + ], + ), + const SizedBox( + width: 15, + ), + Column( + children: [ + SizedBox( + width: 100, + child: FormBuilderDateTimePicker( + name: 'apprvd_by_date_land', + initialEntryMode: + DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + Text('Date'), + ], + ), + ], + ), + const SizedBox( + height: 50, + ), + const Align( + alignment: Alignment.centerLeft, + child: Text( + 'MEMORANDA: ', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + )), + SizedBox( + height: 50, + ), + SizedBox( + width: 500, + height: 100, + child: SearchField( + suggestions: state.memorada + .map((Memoranda memoranda) => + SearchFieldListItem( + '${memoranda.memoranda}', + item: + memoranda, // Change: Use individual Memoranda object + child: ListTile( + title: Text( + '${memoranda.memoranda}', + overflow: TextOverflow.ellipsis, + ), + ), + )) + .toList(), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + // searchInputDecoration: + // normalTextFieldStyle( + // "Memoranda", "") + // .copyWith( + // suffixIcon: const Icon( + // Icons.arrow_drop_down), + // ), + // focusNode: focus, + suggestionState: Suggestion.expand, + onSuggestionTap: (memoranda) { + setState(() { + _memoranda = memoranda.item!.memoranda!; + }); + focus.unfocus(); + }, + )), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Sworn Statement No. :'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'sworn_statement_land', + decoration: InputDecoration(), + validator: FormBuilderValidators.compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Date Received:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_received_land', + initialEntryMode: + DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Date of Entry in the Rec. of Ass. :'), + SizedBox( + width: 100, + height: 20, + child: FormBuilderDateTimePicker( + name: 'date_of_entry_land', + initialEntryMode: + DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + + initialTime: + const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('By:'), + SizedBox( + width: 150, + height: 20, + child: FormBuilderTextField( + name: 'by_land', + decoration: InputDecoration(), + validator: FormBuilderValidators.compose([]), + ), + ), + ], + ), + SizedBox( + height: 30, + ), + ElevatedButton( + onPressed: () async { + final tempID = + await SharedPreferences.getInstance(); + var ext = LandExt( + landapprDetailsId: + tempID.getInt('landid')! - 1, + taxable: isTaxable, + exempt: isExempt, + qtr: int.parse( + landKey.currentState!.value['land_qtr']), + yr: int.parse( + landKey.currentState!.value['land_yr']), + appraisedbyName: landKey.currentState!.value['appraised_by_land'].firstname + + ' ' + + landKey + .currentState! + .value['appraised_by_land'] + .middlename + + ' ' + + landKey.currentState! + .value['appraised_by_land'].lastname, + appraisedbyDate: landKey + .currentState!.value['app_date_land'], + recommendapprName: landKey + .currentState! + .value['rec_approval_land'] + .firstname + + ' ' + + landKey + .currentState! + .value['rec_approval_land'] + .middlename + + ' ' + + landKey.currentState! + .value['rec_approval_land'].lastname, + recommendapprDate: landKey + .currentState!.value['rec_date_land'], + approvedbyName: landKey.currentState!.value['apprvd_by_land'].firstname + + ' ' + + landKey.currentState!.value['apprvd_by_land'].middlename + + ' ' + + landKey.currentState!.value['apprvd_by_land'].lastname, + approvedbyDate: landKey.currentState!.value['apprvd_by_date_land'], + memoranda: _memoranda, + swornstatementNo: landKey.currentState!.value['sworn_statement_land'], + dateReceived: landKey.currentState!.value['date_received_land'], + entryDateAssessment: landKey.currentState!.value['date_of_entry_land'], + entryDateBy: landKey.currentState!.value['by_land']); + + context.read() + ..add(UpdateLandExt(landext: ext)); + widget.onSAve(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: primary, + foregroundColor: Colors.red), + child: SizedBox( + width: 250, + height: 50, + child: Align( + alignment: Alignment.center, + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + SizedBox( + height: 30, + ), + ], + )); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/passo/Land/add_land/property_owner_info.dart b/lib/screens/passo/Land/add_land/property_owner_info.dart new file mode 100644 index 0000000..ec1391f --- /dev/null +++ b/lib/screens/passo/Land/add_land/property_owner_info.dart @@ -0,0 +1,210 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart'; +import 'package:unit2/model/passo/land_property_owner.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; +import 'package:unit2/widgets/passo/custom_formBuilder_fields.dart'; + +class LandPropertyOwnerInfo extends StatefulWidget { + Function NextBtn; + LandPropertyOwnerInfo(this.NextBtn); + @override + _LandPropertyOwnerInfo createState() => _LandPropertyOwnerInfo(); +} + +class _LandPropertyOwnerInfo extends State { + final transaction_codes = ['New', 'Revision']; + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: + const EdgeInsets.only(left: 0, top: 20, right: 0, bottom: 10), + child: const Text('PROPERTY OWNER INFO', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + const SizedBox(height: 15), + customDropDownField( + "Transaction Code", "", "transaction_code", transaction_codes), + customTextField("ARP No./ TD No.", "", "td_no"), + customTextField("Owner", "", "owner"), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded(flex: 1, child: customTextField("PIN", "", "pin")), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("TIN", "", "tin")) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("OCT/TCT CLOA No.", "", "cloa_no"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customDatTimePicker("Dated", "", "dated")) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("Survey No.", "", "survey_no"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Lot No.", "", "lot_no")), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Blk", "", "blk")), + ]), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("Address", "", "address"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Tel No.", "", "tel_no")) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField( + "Administrator/Beneficial User", "", "admin"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("TIN", "", "admin_tin")) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: customTextField("Address", "", "admin_address"), + ), + const SizedBox(width: 10.0), + Expanded( + // optional flex property if flex is 1 because the default flex is 1 + flex: 1, + child: customTextField("Tel No.", "", "admin_telno")) + ]), + + // SizedBox( + // width: double.infinity, + // height: 50, + // child: ElevatedButton( + // style: secondaryBtnStyle(const Color(0xffd92828), + // Color.fromARGB(0, 253, 252, 252), Colors.white54), + // child: const Text( + // "SUBMIT & PROCEED", + // style: TextStyle( + // color: Color.fromARGB(239, 255, 255, 255), + // fontWeight: FontWeight.w700), + // ), + // onPressed: () { + // // formKey.currentState?.save(); + // // // var faas = PropertyInfo( + // // // id: 1, + // // // transCode: formKey + // // // .currentState!.value['transaction_code'] + // // // .toString(), + // // // tdn: formKey.currentState!.value['arp_td'], + // // // pin: formKey.currentState!.value['pin'], + // // // owner: formKey.currentState!.value['owner'], + // // // address: formKey.currentState!.value['address'], + // // // telno: formKey.currentState!.value['tel_no'], + // // // tin: formKey.currentState!.value['tin'], + // // // adminUser: formKey.currentState!.value['benificiary'], + // // // adminAddress: formKey + // // // .currentState!.value['benificiary_address'], + // // // adminTin: + // // // formKey.currentState!.value['benificiary_tin'], + // // // adminTelno: + // // // formKey.currentState!.value['benificiary_telno']); + // // // context.read().add(AddFaas(faas: faas)); + // // // _loadTempId(); + // // _pageController.nextPage( + // // duration: _kDuration, curve: _kCurve); + // }), + // ), + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_right, color: Colors.white), + onPressed: () { + var land = LandPropertyOwner( + id: 1, + transCode: landKey + .currentState!.value['transaction_code'] + .toString(), + tdn: landKey.currentState!.value['td_no'], + cloaNo: landKey.currentState!.value['cloa_no'], + dated: landKey.currentState!.value['dated'], + assessedById: "1", + assessedByName: "cyril", + dateCreated: landKey.currentState!.value['dated'], + dateModified: landKey.currentState!.value['dated'], + pin: landKey.currentState!.value['pin'], + surveyNo: landKey.currentState!.value['survey_no'], + lotNo: landKey.currentState!.value['lot_no'], + blkNo: landKey.currentState!.value['blk'], + owner: landKey.currentState!.value['owner'], + address: landKey.currentState!.value['address'], + telno: landKey.currentState!.value['tel_no'], + tin: landKey.currentState!.value['tin'], + adminUser: landKey.currentState!.value['admin'], + adminAddress: + landKey.currentState!.value['admin_address'], + adminTin: landKey.currentState!.value['admin_tin'], + // faasType: "LAND", + adminTelno: landKey.currentState!.value['admin_telno']); + + context + .read() + .add(AddPropertyOwnerLand(land: land)); + + widget.NextBtn(); + }, + ) + ], + ), + const SizedBox( + height: 20, + ), + ]), + )); + } +} diff --git a/lib/screens/passo/Land/add_land/value_adjustments.dart b/lib/screens/passo/Land/add_land/value_adjustments.dart new file mode 100644 index 0000000..35dbaf2 --- /dev/null +++ b/lib/screens/passo/Land/add_land/value_adjustments.dart @@ -0,0 +1,246 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart'; +import 'package:unit2/screens/passo/Land/add_land/AddLandValueAdjustmentModal.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/widgets/passo/custom_button.dart'; + +class ValueAdjustmentPage extends StatefulWidget { + Function PrevBtn; + Function NextBtn; + ValueAdjustmentPage(this.PrevBtn, this.NextBtn); + @override + _ValueAdjustmentPage createState() => _ValueAdjustmentPage(); +} + +class _ValueAdjustmentPage extends State { + // double _totalMarketValue(items) { + // double total = 0; + // items.forEach((row) { + // total += double.parse(row); + // }); + // return total; + // } + + void deleteItem(int itemId) { + context + .read() + .add(DeleteLandValueAdjustments(id: itemId)); + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // TODO: implement listener + }, builder: (context, state) { + final state = context.watch().state; + if (state is LandValueAdjustmentsLoaded) { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only( + left: 0, top: 20, right: 0, bottom: 10), + child: const Text('VALUE ADJUSTMENTS', + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + textAlign: TextAlign.left), + ), + Align( + alignment: Alignment.topRight, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + ), + onPressed: () { + context + .read() + .add(ShowLandValueAdjustments()); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('ADD ITEM'), // <-- Text + const SizedBox( + width: 5, + ), + const Icon( + // <-- Icon + Icons.add, + size: 24.0, + ), + ], + ), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + // ignore: prefer_const_literals_to_create_immutables + columns: [ + const DataColumn( + label: Text('Base Market Value'), + ), + const DataColumn( + label: Text('Adjustment Factors'), + ), + const DataColumn( + label: Text('% Adjustment'), + ), + const DataColumn( + label: Text('Value Adjustment'), + ), + const DataColumn( + label: Text('Market Value'), + ), + const DataColumn( + label: Text('Action'), + ) + ], + rows: state.val_adj.map((dataRow) { + return DataRow( + cells: [ + DataCell(Text(dataRow.baseMarketval!)), + DataCell(Text(dataRow.adjustmentFactors!)), + DataCell(Text(dataRow.adjustment!)), + DataCell(Text(dataRow.valueAdjustment!)), + DataCell(Text(dataRow.marketValue!)), + DataCell(Row( + children: [ + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () { + deleteItem(dataRow.id!); + }, + ), + SizedBox( + width: 10, + ), + InkWell( + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.edit, + color: Colors.white, + size: 20.0, + ), + ), + onTap: () {}, + ), + ], + )) + ], + ); + }).toList())) + ], + ), + ), + )), + // Padding( + // padding: const EdgeInsets.only(left: 20.0, right: 20.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // 'Total', + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ), + // Text( + // NumberFormat.currency(locale: 'en-PH', symbol: "₱") + // .format('1.0'), + // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + // ) + // ], + // ), + // ), + Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + icon: const Icon(Icons.chevron_left_rounded, + color: Colors.white), + onPressed: () { + { + widget.PrevBtn(); + } + ; + }, + ), + CustomButton( + icon: const Icon(Icons.chevron_right_rounded, + color: Colors.white), + onPressed: () { + { + widget.NextBtn(); + } + ; + }, + ) + ], + ), + ), + ], + ); + } + if (state is LandValueAdjustmentsDeletedState) { + if (state.success) { + WidgetsBinding.instance.addPostFrameCallback((_) { + successAlert(context, "Deletion Successful", + "Extra item has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadLandValueAdjustments()); + }); + }); + } + } + if (state is ShowAddLandValueAdjustmentsScreen) { + return ConstrainedBox( + constraints: BoxConstraints(maxHeight: 1000.0), + child: AlertDialog( + insetPadding: EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 10.0, + ), + title: Text( + 'ADD VALUE ADJUSTMENTS', + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [Expanded(child: AddLandValueAdjustmentModal())], + ), + ), + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/passo/Test Envi/multi_dropdown.dart b/lib/screens/passo/Test Envi/multi_dropdown.dart new file mode 100644 index 0000000..61a88e4 --- /dev/null +++ b/lib/screens/passo/Test Envi/multi_dropdown.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:multiselect/multiselect.dart'; + +class Multi_Select extends StatelessWidget { + const Multi_Select(); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + brightness: Brightness.light, + primarySwatch: Colors.red, + primaryColor: Colors.red, + primaryColorLight: Colors.redAccent, + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: Color(0xFFEEEEEE), + ), + ), + themeMode: ThemeMode.dark, + darkTheme: ThemeData( + brightness: Brightness.dark, + primarySwatch: Colors.red, + primaryColor: Colors.red, + primaryColorLight: Colors.redAccent, + appBarTheme: const AppBarTheme(backgroundColor: Color(0xFF1b1926)), + snackBarTheme: const SnackBarThemeData(backgroundColor: Colors.red), + canvasColor: const Color(0xFF272537), + dialogBackgroundColor: const Color(0xFF343346), + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: Color(0xFF383849), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.all( + Radius.circular(35.0), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.all( + Radius.circular(35.0), + ), + ), + ), + ), + home: const _Multi_Select(title: 'Flutter Demo Home Page'), + ); + } +} + +class _Multi_Select extends StatefulWidget { + const _Multi_Select({required this.title}); + final String title; + + @override + State<_Multi_Select> createState() => _Multi_SelectState(); +} + +class _Multi_SelectState extends State<_Multi_Select> { + int _counter = 0; + + void _incrementCounter() { + setState(() { + _counter++; + }); + } + + List selected = []; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Padding( + padding: const EdgeInsets.all(20.0), + // DropDownMultiSelect comes from multiselect + child: DropDownMultiSelect( + selected_values_style: TextStyle(color: Colors.white), + onChanged: (List x) { + setState(() { + selected = x; + }); + }, + options: ['a', 'b', 'c', 'd'], + selectedValues: selected, + whenEmpty: 'Select Something', + ), + ), + )); + } +} diff --git a/lib/screens/passo/Test Envi/speed_dial.dart b/lib/screens/passo/Test Envi/speed_dial.dart new file mode 100644 index 0000000..7d4c1c9 --- /dev/null +++ b/lib/screens/passo/Test Envi/speed_dial.dart @@ -0,0 +1,529 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; + +void main() => runApp(const SpeedDial()); + +class SpeedDials extends StatefulWidget { + const SpeedDials({Key? key}) : super(key: key); + @override + _SpeedDials createState() => _SpeedDials(); +} + +class _SpeedDials extends State { + var theme = ValueNotifier(ThemeMode.dark); + + @override + Widget build(BuildContext context) { + const appTitle = 'Flutter Speed Dial Example'; + return ValueListenableBuilder( + valueListenable: theme, + builder: (context, value, child) => MaterialApp( + title: appTitle, + home: MyHomePage(theme: theme), + debugShowCheckedModeBanner: false, + theme: ThemeData( + brightness: Brightness.light, + primaryColor: Colors.blue, + ), + darkTheme: ThemeData( + brightness: Brightness.dark, + primaryColor: Colors.lightBlue[900], + ), + themeMode: value, + )); + } +} + +class MyHomePage extends StatefulWidget { + final ValueNotifier theme; + const MyHomePage({Key? key, required this.theme}) : super(key: key); + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State with TickerProviderStateMixin { + var renderOverlay = true; + var visible = true; + var switchLabelPosition = false; + var extend = false; + var mini = false; + var rmicons = false; + var customDialRoot = false; + var closeManually = false; + var useRAnimation = true; + var isDialOpen = ValueNotifier(false); + var speedDialDirection = SpeedDialDirection.up; + var buttonSize = const Size(56.0, 56.0); + var childrenButtonSize = const Size(56.0, 56.0); + var selectedfABLocation = FloatingActionButtonLocation.endDocked; + var items = [ + FloatingActionButtonLocation.startFloat, + FloatingActionButtonLocation.startDocked, + FloatingActionButtonLocation.centerFloat, + FloatingActionButtonLocation.endFloat, + FloatingActionButtonLocation.endDocked, + FloatingActionButtonLocation.startTop, + FloatingActionButtonLocation.centerTop, + FloatingActionButtonLocation.endTop, + ]; + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + if (isDialOpen.value) { + isDialOpen.value = false; + return false; + } + return true; + }, + child: Scaffold( + appBar: AppBar( + title: const Text("Flutter Speed Dial Example"), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + physics: const BouncingScrollPhysics(), + child: Center( + child: Container( + constraints: const BoxConstraints(maxWidth: 800), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric( + vertical: 6, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("SpeedDial Location", + style: Theme.of(context).textTheme.bodyLarge), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Theme.of(context).brightness == + Brightness.dark + ? Colors.grey[800] + : Colors.grey[200], + borderRadius: BorderRadius.circular(10)), + child: DropdownButton( + value: selectedfABLocation, + isExpanded: true, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 20, + underline: const SizedBox(), + onChanged: (fABLocation) => setState( + () => selectedfABLocation = fABLocation!), + selectedItemBuilder: (BuildContext context) { + return items.map((item) { + return Align( + alignment: Alignment.centerLeft, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 10), + child: Text(item.value))); + }).toList(); + }, + items: items.map((item) { + return DropdownMenuItem< + FloatingActionButtonLocation>( + value: item, + child: Text( + item.value, + ), + ); + }).toList(), + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric( + vertical: 6, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("SpeedDial Direction", + style: Theme.of(context).textTheme.bodyLarge), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Theme.of(context).brightness == + Brightness.dark + ? Colors.grey[800] + : Colors.grey[200], + borderRadius: BorderRadius.circular(10)), + child: DropdownButton( + value: speedDialDirection, + isExpanded: true, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 20, + underline: const SizedBox(), + onChanged: (sdo) { + setState(() { + speedDialDirection = sdo!; + selectedfABLocation = (sdo.isUp && + selectedfABLocation.value + .contains("Top")) || + (sdo.isLeft && + selectedfABLocation.value + .contains("start")) + ? FloatingActionButtonLocation.endDocked + : sdo.isDown && + !selectedfABLocation.value + .contains("Top") + ? FloatingActionButtonLocation.endTop + : sdo.isRight && + selectedfABLocation.value + .contains("end") + ? FloatingActionButtonLocation + .startDocked + : selectedfABLocation; + }); + }, + selectedItemBuilder: (BuildContext context) { + return SpeedDialDirection.values + .toList() + .map((item) { + return Container( + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 10), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + describeEnum(item).toUpperCase())), + ); + }).toList(); + }, + items: SpeedDialDirection.values + .toList() + .map((item) { + return DropdownMenuItem( + value: item, + child: Text(describeEnum(item).toUpperCase()), + ); + }).toList(), + ), + ), + ], + ), + ), + if (!customDialRoot) + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: extend, + title: const Text("Extend Speed Dial"), + onChanged: (val) { + setState(() { + extend = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: visible, + title: const Text("Visible"), + onChanged: (val) { + setState(() { + visible = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: mini, + title: const Text("Mini"), + onChanged: (val) { + setState(() { + mini = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: customDialRoot, + title: const Text("Custom dialRoot"), + onChanged: (val) { + setState(() { + customDialRoot = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: renderOverlay, + title: const Text("Render Overlay"), + onChanged: (val) { + setState(() { + renderOverlay = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: closeManually, + title: const Text("Close Manually"), + onChanged: (val) { + setState(() { + closeManually = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: rmicons, + title: const Text("Remove Icons (for children)"), + onChanged: (val) { + setState(() { + rmicons = val; + }); + }), + if (!customDialRoot) + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: useRAnimation, + title: const Text("Use Rotation Animation"), + onChanged: (val) { + setState(() { + useRAnimation = val; + }); + }), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + value: switchLabelPosition, + title: const Text("Switch Label Position"), + onChanged: (val) { + setState(() { + switchLabelPosition = val; + if (val) { + if ((selectedfABLocation.value.contains("end") || + selectedfABLocation.value + .toLowerCase() + .contains("top")) && + speedDialDirection.isUp) { + selectedfABLocation = + FloatingActionButtonLocation.startDocked; + } else if ((selectedfABLocation.value + .contains("end") || + !selectedfABLocation.value + .toLowerCase() + .contains("top")) && + speedDialDirection.isDown) { + selectedfABLocation = + FloatingActionButtonLocation.startTop; + } + } + }); + }), + const Text("Button Size"), + Slider( + value: buttonSize.width, + min: 50, + max: 500, + label: "Button Size", + onChanged: (val) { + setState(() { + buttonSize = Size(val, val); + }); + }, + ), + const Text("Children Button Size"), + Slider( + value: childrenButtonSize.height, + min: 50, + max: 500, + onChanged: (val) { + setState(() { + childrenButtonSize = Size(val, val); + }); + }, + ), + Container( + padding: const EdgeInsets.symmetric( + vertical: 6, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Navigation", + style: Theme.of(context).textTheme.bodyLarge), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => + MyHomePage(theme: widget.theme), + ), + ); + }, + child: const Text("Push Duplicate Page")), + ], + ), + ), + ], + ), + ), + )), + floatingActionButtonLocation: selectedfABLocation, + floatingActionButton: SpeedDial( + // animatedIcon: AnimatedIcons.menu_close, + // animatedIconTheme: IconThemeData(size: 22.0), + // / This is ignored if animatedIcon is non null + // child: Text("open"), + // activeChild: Text("close"), + icon: Icons.add, + activeIcon: Icons.close, + spacing: 3, + mini: mini, + openCloseDial: isDialOpen, + childPadding: const EdgeInsets.all(5), + spaceBetweenChildren: 4, + dialRoot: customDialRoot + ? (ctx, open, toggleChildren) { + return ElevatedButton( + onPressed: toggleChildren, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue[900], + padding: const EdgeInsets.symmetric( + horizontal: 22, vertical: 18), + ), + child: const Text( + "Custom Dial Root", + style: TextStyle(fontSize: 17), + ), + ); + } + : null, + buttonSize: + buttonSize, // it's the SpeedDial size which defaults to 56 itself + // iconTheme: IconThemeData(size: 22), + label: extend + ? const Text("Open") + : null, // The label of the main button. + /// The active label of the main button, Defaults to label if not specified. + activeLabel: extend ? const Text("Close") : null, + + /// Transition Builder between label and activeLabel, defaults to FadeTransition. + // labelTransitionBuilder: (widget, animation) => ScaleTransition(scale: animation,child: widget), + /// The below button size defaults to 56 itself, its the SpeedDial childrens size + childrenButtonSize: childrenButtonSize, + visible: visible, + direction: speedDialDirection, + switchLabelPosition: switchLabelPosition, + + /// If true user is forced to close dial manually + closeManually: closeManually, + + /// If false, backgroundOverlay will not be rendered. + renderOverlay: renderOverlay, + // overlayColor: Colors.black, + // overlayOpacity: 0.5, + onOpen: () => debugPrint('OPENING DIAL'), + onClose: () => debugPrint('DIAL CLOSED'), + useRotationAnimation: useRAnimation, + tooltip: 'Open Speed Dial', + heroTag: 'speed-dial-hero-tag', + // foregroundColor: Colors.black, + // backgroundColor: Colors.white, + // activeForegroundColor: Colors.red, + // activeBackgroundColor: Colors.blue, + elevation: 8.0, + animationCurve: Curves.elasticInOut, + isOpenOnStart: false, + shape: customDialRoot + ? const RoundedRectangleBorder() + : const StadiumBorder(), + // childMargin: EdgeInsets.symmetric(horizontal: 10, vertical: 5), + children: [ + SpeedDialChild( + child: !rmicons ? const Icon(Icons.accessibility) : null, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + label: 'First', + onTap: () => setState(() => rmicons = !rmicons), + onLongPress: () => debugPrint('FIRST CHILD LONG PRESS'), + ), + SpeedDialChild( + child: !rmicons ? const Icon(Icons.brush) : null, + backgroundColor: Colors.deepOrange, + foregroundColor: Colors.white, + label: 'Second', + onTap: () => debugPrint('SECOND CHILD'), + ), + SpeedDialChild( + child: !rmicons ? const Icon(Icons.margin) : null, + backgroundColor: Colors.indigo, + foregroundColor: Colors.white, + label: 'Show Snackbar', + visible: true, + onTap: () => ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text(("Third Child Pressed")))), + onLongPress: () => debugPrint('THIRD CHILD LONG PRESS'), + ), + ], + ), + bottomNavigationBar: BottomAppBar( + shape: const CircularNotchedRectangle(), + notchMargin: 8.0, + child: Row( + mainAxisAlignment: selectedfABLocation == + FloatingActionButtonLocation.startDocked + ? MainAxisAlignment.end + : selectedfABLocation == FloatingActionButtonLocation.endDocked + ? MainAxisAlignment.start + : MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + IconButton( + icon: const Icon(Icons.nightlight_round), + tooltip: "Switch Theme", + onPressed: () => { + widget.theme.value = widget.theme.value.index == 2 + ? ThemeMode.light + : ThemeMode.dark + }, + ), + ValueListenableBuilder( + valueListenable: isDialOpen, + builder: (ctx, value, _) => IconButton( + icon: const Icon(Icons.open_in_browser), + tooltip: (!value ? "Open" : "Close") + (" Speed Dial"), + onPressed: () => {isDialOpen.value = !isDialOpen.value}, + )) + ], + ), + ), + ), + ); + } +} + +extension EnumExt on FloatingActionButtonLocation { + /// Get Value of The SpeedDialDirection Enum like Up, Down, etc. in String format + String get value => toString().split(".")[1]; +} diff --git a/lib/screens/passo/building_home.dart b/lib/screens/passo/building_home.dart new file mode 100644 index 0000000..c2dcaeb --- /dev/null +++ b/lib/screens/passo/building_home.dart @@ -0,0 +1,406 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import 'package:unit2/bloc/passo/barangay/barangay_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/class_components/class_components_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/general_description/general_description_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/landref/landref_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/location/location_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/structural_material/structural_material_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_classification/land_classification_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_ext/land_ext_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart'; +import 'package:unit2/bloc/passo/land/other_improvements/other_improvements_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_location/type_of_location_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_road/type_of_road_bloc.dart'; + +import 'package:unit2/bloc/passo/memoranda/memoranda_bloc.dart'; +import 'package:unit2/bloc/passo/municipality/municipality_bloc.dart'; + +import 'package:unit2/bloc/passo/signatories/signatories_bloc.dart'; + +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_appraisal_edit.dart'; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/model/passo/structureMaterial.dart'; +import 'package:unit2/model/profile/basic_information/primary-information.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/screens/passo/Building/edit_building.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/screens/passo/Test%20Envi/multi_dropdown.dart'; +import 'package:unit2/screens/passo/Test%20Envi/speed_dial.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; + +import '../../model/passo/bldg_loc.dart'; + +class BuildingHome extends StatelessWidget { + const BuildingHome({super.key}); + + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + Profile profile; + return Scaffold( + body: ProgressHUD( + padding: const EdgeInsets.only(left: 24, right: 24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder(builder: (context, state) { + if (state is UserLoggedIn) { + profileId = state.userData!.user!.login!.user!.profileId; + token = state.userData!.user!.login!.token!; + profile = state.userData!.employeeInfo!.profile!; + return BlocConsumer( + listener: ( + context, + state, + ) { + if (state is PropertyInfoLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is PropertyInfoLoaded || + state is PropertyInfoErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + }, + builder: (context, state) { + if (state is PropertyInfoLoaded) { + List propertyList = state.property_info; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: propertyList.length, + itemBuilder: (BuildContext context, int index) { + return _listCard( + propertyList[index], context, index); + }, + ), + ), + ); + } + if (state is PropertyInfoErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadPropertyInfo()); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + })), + floatingActionButton: SpeedDial( + +//provide here features of your parent FAB + icon: Icons.add, + backgroundColor: primary, + heroTag: null, + useRotationAnimation: true, + activeIcon: Icons.close, + animationCurve: Curves.elasticInOut, + children: [ + SpeedDialChild( + child: const Icon( + Icons.maps_home_work_rounded, + color: primary, + ), + label: 'Building & Other Structure', + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return MultiBlocProvider(providers: [ + BlocProvider( + create: (context) => + PropertyInfoBloc()..add(LoadPropertyInfo()), + ), + BlocProvider( + create: (context) => + ClassComponentsBloc()..add(LoadClassComponents()), + ), + BlocProvider( + create: (context) => + UnitConstructBloc()..add(LoadUnitConstruct()), + ), + BlocProvider( + create: (context) => + AdditionalItemBloc()..add(LoadAdditionalItems()), + ), + BlocProvider( + create: (context) => PropertyAppraisalBloc() + ..add(LoadPropertyAppraisal( + appraisal: PropertyAppraisal())), + ), + BlocProvider( + create: (context) => PropertyAssessmentBloc() + ..add(LoadPropertyAssessment())), + BlocProvider( + create: (context) => + SignatoriesBloc()..add(LoadSignatories())), + BlocProvider( + create: (context) => + MunicipalityBloc()..add(LoadMunicipality())), + BlocProvider( + create: (context) => + BarangayBloc()..add(LoadBarangay(id: '01'))), + BlocProvider( + create: (context) => + MemorandaBloc()..add(LoadMemoranda())), + ], child: AddBuilding()); + })); + }), + SpeedDialChild( + child: const Icon( + Icons.forest_rounded, + color: primary, + ), + label: 'Land/Other Improvements', + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return MultiBlocProvider(providers: [ + BlocProvider( + create: (context) => + LandPropertyOwnerInfoBloc()..add(LoadLand())), + BlocProvider( + create: (context) => LandClassificationBloc() + ..add(LoadLandClassification())), + BlocProvider( + create: (context) => LandSubClassificationBloc() + ..add(LoadLandSubClassification( + cityCode: "1", classCode: 1))), + BlocProvider( + create: (context) => + LandAppraisalBloc()..add(LoadLandAppraisal())), + BlocProvider( + create: (context) => + MunicipalityBloc()..add(LoadMunicipality())), + BlocProvider( + create: (context) => + BarangayBloc()..add(LoadBarangay(id: '01'))), + BlocProvider( + create: (context) => OtherImprovementsBloc() + ..add(LoadOtherImprovement())), + BlocProvider( + create: (context) => LandTreesImprovementsBloc() + ..add(LoadLandTreesImprovements())), + BlocProvider( + create: (context) => LandValueAdjustmentsBloc() + ..add(LoadLandValueAdjustments())), + BlocProvider( + create: (context) => + TypeOfLocationBloc()..add(LoadTypeOfLocation())), + BlocProvider( + create: (context) => + TypeOfRoadBloc()..add(LoadTypeOfRoad())), + BlocProvider( + create: (context) => LandPropertyAssessmentBloc() + ..add(LoadLandPropertyAssessment())), + BlocProvider( + create: (context) => + SignatoriesBloc()..add(LoadSignatories())), + BlocProvider( + create: (context) => LandExtBloc()..add(LoadLandExt())), + BlocProvider( + create: (context) => + MemorandaBloc()..add(LoadMemoranda())), + ], child: AddLand()); + })); + }, + ), + SpeedDialChild( + child: const Icon( + Icons.precision_manufacturing_rounded, + color: primary, + ), + label: 'Machinery', + onTap: () {}, + ), + // SpeedDialChild( + // child: const Icon( + // Icons.report_problem_rounded, + // color: primary, + // ), + // label: 'Testing Screen', + // onTap: () { + // Navigator.of(context) + // .push(MaterialPageRoute(builder: (ctx) => Multi_Select())); + // }, + // ), + ]), + ); + } +} + +Card _listCard(PropertyInfo property_info, context, index) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + //set border radius more than 50% of height and width to make circle + ), + margin: const EdgeInsets.all(5.0), + elevation: 5, + shadowColor: Colors.grey, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: InkWell( + onTap: () async { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => + PropertyInfoBloc()..add(LoadPropertyInfo()), + ), + BlocProvider( + create: (context) => + UnitConstructBloc()..add(LoadUnitConstruct()), + ), + BlocProvider( + create: (context) => + ClassComponentsBloc()..add(LoadClassComponents()), + ), + BlocProvider( + create: (context) => + SignatoriesBloc()..add(LoadSignatories())), + BlocProvider( + create: (context) => LocationBloc() + ..add( + LoadLocation(bldgloc: BldgLoc(), id: property_info.id)), + ), + BlocProvider( + create: (context) => LandrefBloc() + ..add( + LoadLandref(landRef: LandRef(), id: property_info.id)), + ), + BlocProvider( + create: (context) => GeneralDescriptionBloc() + ..add(LoadGenDesc( + gendesc: GeneralDesc(), id: property_info.id)), + ), + BlocProvider( + create: (context) => AdditionalItemsEditBloc() + ..add(LoadAdditionalItemsEdit( + items: const [], + id: property_info.id)), + ), + BlocProvider( + create: (context) => PropertyAssessmentEditBloc() + ..add(LoadPropertyAssessmentEdit( + assessmentsEdit: PropertyAssessmentEdit(), + id: property_info.id)), + ), + BlocProvider( + create: (context) => PropertyAppraisalEditBloc() + ..add(LoadPropertyAppraisalEdit( + appraisalEdit: PropertyAppraisalEdit(), + id: property_info.id)), + ), + BlocProvider( + create: (context) => + MunicipalityBloc()..add(LoadMunicipality())), + BlocProvider( + create: (context) => + BarangayBloc()..add(LoadBarangay(id: '01'))), + BlocProvider( + create: (context) => MemorandaBloc()..add(LoadMemoranda())), + BlocProvider( + create: (context) => StructuralMaterialBloc() + ..add(LoadStructuralMaterial( + structure: StructureMaterials(), + id: property_info.id))), + ], + child: EditBuilding( + index: index, + faas: property_info, + title: 'Bldg & Structure Edit', + ), + ); + })); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40, // Adjust this to your desired size + height: 40, // Adjust this to your desired size + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: primary, // Border color + width: 2, // Border width + ), + ), + child: Icon( + Icons.maps_home_work_rounded, + color: primary, // Icon color + ), + ), + SizedBox( + width: 20, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${property_info.owner}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.left, + ), + SizedBox(height: 5), + Text( + '${property_info.tdn}', + style: TextStyle( + fontSize: 13, + ), + textAlign: TextAlign.left, + ), + ], + ), + ), + IconButton(onPressed: () {}, icon: const Icon(Icons.chevron_right)), + ], + ), + ), + ), + ); +} diff --git a/lib/screens/passo/land_home .dart b/lib/screens/passo/land_home .dart new file mode 100644 index 0000000..4326133 --- /dev/null +++ b/lib/screens/passo/land_home .dart @@ -0,0 +1,406 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import 'package:unit2/bloc/passo/barangay/barangay_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_item/additional_item_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/additional_items_edit/additional_items_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/class_components/class_components_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/general_description/general_description_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/landref/landref_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/location/location_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal/property_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_appraisal_edit/property_appraisal_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment/property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_assessment_edit/property_assessment_edit_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/structural_material/structural_material_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/unit_construct/unit_construct_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_appraisal/land_appraisal_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_classification/land_classification_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_ext/land_ext_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_assessment/land_property_assessment_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_subclassification/land_subclassification_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_trees_improvements/land_trees_improvements_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_value_adjustments/land_value_adjustments_bloc.dart'; +import 'package:unit2/bloc/passo/land/other_improvements/other_improvements_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_location/type_of_location_bloc.dart'; +import 'package:unit2/bloc/passo/land/type_of_road/type_of_road_bloc.dart'; + +import 'package:unit2/bloc/passo/memoranda/memoranda_bloc.dart'; +import 'package:unit2/bloc/passo/municipality/municipality_bloc.dart'; + +import 'package:unit2/bloc/passo/signatories/signatories_bloc.dart'; + +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/land_property_owner.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:unit2/model/passo/property_appraisal_edit.dart'; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/model/passo/structureMaterial.dart'; +import 'package:unit2/model/profile/basic_information/primary-information.dart'; +import 'package:unit2/screens/passo/Building/add_building.dart'; +import 'package:unit2/screens/passo/Building/edit_building.dart'; +import 'package:unit2/screens/passo/Land/add_land.dart'; +import 'package:unit2/screens/passo/Test%20Envi/multi_dropdown.dart'; +import 'package:unit2/screens/passo/Test%20Envi/speed_dial.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; + +import '../../model/passo/bldg_loc.dart'; + +class LandHome extends StatelessWidget { + const LandHome({super.key}); + + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + Profile profile; + return Scaffold( + body: ProgressHUD( + padding: const EdgeInsets.only(left: 24, right: 24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder(builder: (context, state) { + if (state is UserLoggedIn) { + profileId = state.userData!.user!.login!.user!.profileId; + token = state.userData!.user!.login!.token!; + profile = state.userData!.employeeInfo!.profile!; + return BlocConsumer( + listener: ( + context, + state, + ) { + if (state is LandLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is LandLoaded || state is LandErrorState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + }, + builder: (context, state) { + if (state is LandLoaded) { + List propertyList = state.land; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: propertyList.length, + itemBuilder: (BuildContext context, int index) { + return _listCard( + propertyList[index], context, index); + }, + ), + ), + ); + } + if (state is LandErrorState) { + return SomethingWentWrong( + message: onError, + onpressed: () { + context + .read() + .add(LoadLand()); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + })), + floatingActionButton: SpeedDial( + +//provide here features of your parent FAB + icon: Icons.add, + backgroundColor: primary, + heroTag: null, + useRotationAnimation: true, + activeIcon: Icons.close, + animationCurve: Curves.elasticInOut, + children: [ + SpeedDialChild( + child: const Icon( + Icons.maps_home_work_rounded, + color: primary, + ), + label: 'Building & Other Structure', + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return MultiBlocProvider(providers: [ + BlocProvider( + create: (context) => + PropertyInfoBloc()..add(LoadPropertyInfo()), + ), + BlocProvider( + create: (context) => + ClassComponentsBloc()..add(LoadClassComponents()), + ), + BlocProvider( + create: (context) => + UnitConstructBloc()..add(LoadUnitConstruct()), + ), + BlocProvider( + create: (context) => + AdditionalItemBloc()..add(LoadAdditionalItems()), + ), + BlocProvider( + create: (context) => PropertyAppraisalBloc() + ..add(LoadPropertyAppraisal( + appraisal: PropertyAppraisal())), + ), + BlocProvider( + create: (context) => PropertyAssessmentBloc() + ..add(LoadPropertyAssessment())), + BlocProvider( + create: (context) => + SignatoriesBloc()..add(LoadSignatories())), + BlocProvider( + create: (context) => + MunicipalityBloc()..add(LoadMunicipality())), + BlocProvider( + create: (context) => + BarangayBloc()..add(LoadBarangay(id: '01'))), + BlocProvider( + create: (context) => + MemorandaBloc()..add(LoadMemoranda())), + ], child: AddBuilding()); + })); + }), + SpeedDialChild( + child: const Icon( + Icons.forest_rounded, + color: primary, + ), + label: 'Land/Other Improvements', + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return MultiBlocProvider(providers: [ + BlocProvider( + create: (context) => + LandPropertyOwnerInfoBloc()..add(LoadLand())), + BlocProvider( + create: (context) => LandClassificationBloc() + ..add(LoadLandClassification())), + BlocProvider( + create: (context) => LandSubClassificationBloc() + ..add(LoadLandSubClassification( + cityCode: "1", classCode: 1))), + BlocProvider( + create: (context) => + LandAppraisalBloc()..add(LoadLandAppraisal())), + BlocProvider( + create: (context) => + MunicipalityBloc()..add(LoadMunicipality())), + BlocProvider( + create: (context) => + BarangayBloc()..add(LoadBarangay(id: '01'))), + BlocProvider( + create: (context) => OtherImprovementsBloc() + ..add(LoadOtherImprovement())), + BlocProvider( + create: (context) => LandTreesImprovementsBloc() + ..add(LoadLandTreesImprovements())), + BlocProvider( + create: (context) => LandValueAdjustmentsBloc() + ..add(LoadLandValueAdjustments())), + BlocProvider( + create: (context) => + TypeOfLocationBloc()..add(LoadTypeOfLocation())), + BlocProvider( + create: (context) => + TypeOfRoadBloc()..add(LoadTypeOfRoad())), + BlocProvider( + create: (context) => LandPropertyAssessmentBloc() + ..add(LoadLandPropertyAssessment())), + BlocProvider( + create: (context) => + SignatoriesBloc()..add(LoadSignatories())), + BlocProvider( + create: (context) => LandExtBloc()..add(LoadLandExt())), + BlocProvider( + create: (context) => + MemorandaBloc()..add(LoadMemoranda())), + ], child: AddLand()); + })); + }, + ), + SpeedDialChild( + child: const Icon( + Icons.precision_manufacturing_rounded, + color: primary, + ), + label: 'Machinery', + onTap: () {}, + ), + // SpeedDialChild( + // child: const Icon( + // Icons.report_problem_rounded, + // color: primary, + // ), + // label: 'Testing Screen', + // onTap: () { + // Navigator.of(context) + // .push(MaterialPageRoute(builder: (ctx) => Multi_Select())); + // }, + // ), + ]), + ); + } +} + +Card _listCard(LandPropertyOwner property_info, context, index) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + //set border radius more than 50% of height and width to make circle + ), + margin: const EdgeInsets.all(5.0), + elevation: 5, + shadowColor: Colors.grey, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: InkWell( + onTap: () async { + // Navigator.push(context, + // MaterialPageRoute(builder: (BuildContext context) { + // return MultiBlocProvider( + // providers: [ + // BlocProvider( + // create: (context) => + // PropertyInfoBloc()..add(LoadPropertyInfo()), + // ), + // BlocProvider( + // create: (context) => + // UnitConstructBloc()..add(LoadUnitConstruct()), + // ), + // BlocProvider( + // create: (context) => + // ClassComponentsBloc()..add(LoadClassComponents()), + // ), + // BlocProvider( + // create: (context) => + // SignatoriesBloc()..add(LoadSignatories())), + // BlocProvider( + // create: (context) => LocationBloc() + // ..add( + // LoadLocation(bldgloc: BldgLoc(), id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => LandrefBloc() + // ..add( + // LoadLandref(landRef: LandRef(), id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => GeneralDescriptionBloc() + // ..add(LoadGenDesc( + // gendesc: GeneralDesc(), id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => AdditionalItemsEditBloc() + // ..add(LoadAdditionalItemsEdit( + // items: const [], + // id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => PropertyAssessmentEditBloc() + // ..add(LoadPropertyAssessmentEdit( + // assessmentsEdit: PropertyAssessmentEdit(), + // id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => PropertyAppraisalEditBloc() + // ..add(LoadPropertyAppraisalEdit( + // appraisalEdit: PropertyAppraisalEdit(), + // id: property_info.id)), + // ), + // BlocProvider( + // create: (context) => + // MunicipalityBloc()..add(LoadMunicipality())), + // BlocProvider( + // create: (context) => + // BarangayBloc()..add(LoadBarangay(id: '01'))), + // BlocProvider( + // create: (context) => MemorandaBloc()..add(LoadMemoranda())), + // BlocProvider( + // create: (context) => StructuralMaterialBloc() + // ..add(LoadStructuralMaterial( + // structure: StructureMaterials(), + // id: property_info.id))), + // ], + // child: EditBuilding( + // index: index, + // faas: property_info, + // title: 'Bldg & Structure Edit', + // ), + // ); + // })); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40, // Adjust this to your desired size + height: 40, // Adjust this to your desired size + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: primary, // Border color + width: 2, // Border width + ), + ), + child: Icon( + Icons.forest_rounded, + color: primary, // Icon color + ), + ), + SizedBox( + width: 20, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${property_info.owner}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.left, + ), + SizedBox(height: 5), + Text( + '${property_info.tdn}', + style: TextStyle( + fontSize: 13, + ), + textAlign: TextAlign.left, + ), + ], + ), + ), + IconButton(onPressed: () {}, icon: const Icon(Icons.chevron_right)), + ], + ), + ), + ), + ); +} diff --git a/lib/screens/passo/passo_dashboard.dart b/lib/screens/passo/passo_dashboard.dart new file mode 100644 index 0000000..c423b8f --- /dev/null +++ b/lib/screens/passo/passo_dashboard.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/passo/land/land_property_owner_info/land_property_owner_info_bloc.dart'; +import 'package:unit2/screens/passo/building_home.dart'; +import 'package:unit2/screens/passo/land_home%20.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/empty_data.dart'; + +class PassoDashBoard extends StatefulWidget { + @override + _PassoDashBoard createState() => _PassoDashBoard(); +} + +class _PassoDashBoard extends State { + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 3, + child: Scaffold( + body: NestedScrollView( + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + new SliverAppBar( + backgroundColor: primary, + title: Text('Faas Dashboard'), + centerTitle: true, + pinned: true, + floating: true, + bottom: TabBar( + isScrollable: true, + tabs: [ + Tab(child: Text('Building')), + Tab(child: Text('Land')), + Tab(child: Text('Machineries')), + ], + ), + ), + ]; + }, + body: TabBarView( + children: [ + BlocProvider( + create: (context) => + PropertyInfoBloc()..add(const LoadPropertyInfo()), + child: const BuildingHome(), + ), + BlocProvider( + create: (context) => + LandPropertyOwnerInfoBloc()..add(const LoadLand()), + child: const LandHome(), + ), + EmptyData( + message: "Development ongoing ...", + ) + ], + ), + )), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/address/add_modal.dart b/lib/screens/profile/components/basic_information/address/add_modal.dart new file mode 100644 index 0000000..1ba59f0 --- /dev/null +++ b/lib/screens/profile/components/basic_information/address/add_modal.dart @@ -0,0 +1,522 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/utils/global.dart'; +import '../../../../../model/location/barangay.dart'; +import '../../../../../model/location/city.dart'; +import '../../../../../model/location/country.dart'; +import '../../../../../model/location/provinces.dart'; +import '../../../../../model/location/region.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/location_utilities.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class AddAddressScreen extends StatefulWidget { + final int profileId; + final String token; + const AddAddressScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _AddAddressScreenState(); +} + +class _AddAddressScreenState extends State { + ////boolean + bool hasLotandBlock = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + ////selected + AddressCategory? selectedAddressCategory; + String? selectedAreaClass; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Barangay? selectedBarangay; + Country? selectedCountry; + ////Lists + final List areaClass = [ + const Area(value: "Rural Area", group: 0), + const Area(value: "Sitio", group: 1), + const Area(value: "Village", group: 1), + const Area(value: "Urban Area", group: 0), + const Area(value: "Town", group: 1), + const Area(value: "City", group: 1), + const Area(value: "Metropolis", group: 1), + const Area(value: "Megacity", group: 1), + ]; + final List category = [ + AddressCategory(id: 1, name: "Permanent", type: "home"), + AddressCategory(id: 2, name: "Residential", type: "home"), + AddressCategory(id: 3, name: "Birthplace", type: "home") + ]; + List? provinces; + List? citymuns; + List? barangays; + final formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is AddAddressState) { + return FormBuilder( + key: formKey, + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: SizedBox( + height: screenHeight * 88, + child: ListView( + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: + normalTextFieldStyle("Category*", "Category"), + name: "category", + onChanged: (AddressCategory? category) { + selectedAddressCategory = category; + }, + items: category + .map>( + (AddressCategory category) { + return DropdownMenuItem( + value: category, child: Text(category.name!)); + }).toList()), + const SizedBox( + height: 12, + ), + ////Area Class + FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Area class *", "Area class"), + name: "area_class", + onChanged: (Area? area) { + selectedAreaClass = area!.value; + }, + items: areaClass + .map>((Area area) { + return area.group == 0 + ? DropdownMenuItem( + enabled: false, + value: area, + child: Text(area.value.toUpperCase(), + style: const TextStyle( + color: Colors.black38))) + : DropdownMenuItem( + value: area, + enabled: true, + child: Text( + " ${area.value.toUpperCase()}")); + }).toList()), + const SizedBox( + height: 12, + ), + ////stateful builder + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + ////with block & Lot Switch + FormBuilderSwitch( + initialValue: hasLotandBlock, + activeColor: second, + onChanged: (value) { + setState(() { + hasLotandBlock = value!; + }); + }, + decoration: normalTextFieldStyle( + "With Lot and Block?", 'Graduated?'), + name: 'graudated', + title: Text(hasLotandBlock ? "YES" : "NO"), + ), + SizedBox( + height: hasLotandBlock ? 12 : 0, + ), + SizedBox( + width: screenWidth, + child: hasLotandBlock + ? Row( + children: [ + ////block # + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators + .compose([numericRequired]), + keyboardType: + TextInputType.number, + name: "block_number", + decoration: + normalTextFieldStyle( + "Block #*", "Block #"), + )), + const SizedBox( + width: 8, + ), + //// lot # + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators + .compose([numericRequired]), + name: "lot_number", + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "Lot #*", "Lot #"), + )), + ], + ) + : Container(), + ), + ], + ); + }), + const SizedBox( + height: 12, + ), + //// Address Line + FormBuilderTextField( + name: "address_line", + decoration: normalTextFieldStyle( + "Address Line ", "Address Line"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 8 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + FormBuilderDropdown( + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + onChanged: (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + getProvinces(); + } + }, + initialValue: null, + decoration: normalTextFieldStyle( + "Region*", "Region"), + name: 'region', + items: state.regions + .map>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 8, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: + (Province? province) { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + getCities(); + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? city) { + if (selectedMunicipality != + city) { + setState(() { + barangayCall = true; + }); + selectedMunicipality = city; + getBarangays(); + } + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: barangayCall, + child: DropdownButtonFormField< + Barangay>( + isExpanded: true, + onChanged: (Barangay? baragay) { + selectedBarangay = baragay; + }, + decoration: + normalTextFieldStyle( + "Barangay*", + "Barangay"), + value: selectedBarangay, + items: barangays == null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>( + (Barangay barangay) { + return DropdownMenuItem( + value: barangay, + child: Text(barangay + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: FormBuilderDropdown( + initialValue: null, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: + Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + const SizedBox(height: 24,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + String? lotNumber; + String? blockNumber; + String? addressLine; + Country country = selectedCountry ??= Country( + id: 175, name: 'Philippines', code: 'PH'); + AddressClass address = AddressClass( + barangay: selectedBarangay, + id: null, + category: null, + areaClass: selectedAreaClass, + cityMunicipality: selectedMunicipality, + country: country); + if (hasLotandBlock) { + lotNumber = + formKey.currentState!.value['lot_number']; + blockNumber = + formKey.currentState!.value['block_number']; + } + addressLine = + formKey.currentState?.value['address_line']; + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(AddAddress( + address: address, + profileId: widget.profileId, + token: widget.token, + blockNumber: blockNumber != null + ? int.parse(blockNumber) + : null, + categoryId: selectedAddressCategory!.id!, + details: addressLine, + lotNumber: lotNumber != null + ? int.parse(lotNumber) + : null)); + } + }, + child: const Text(submit)), + ), + + ], + ), + ), + )); + } + return const Placeholder(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + barangayCall = true; + getBarangays(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getBarangays() async { + try { + List newBarangays = await LocationUtils.instance + .getBarangay(code: selectedMunicipality!.code.toString()); + barangays = newBarangays; + setState(() { + selectedBarangay = newBarangays[0]; + barangayCall = false; + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } +} + +class Area { + final int group; + final String value; + const Area({required this.group, required this.value}); +} diff --git a/lib/screens/profile/components/basic_information/address/edit_modal.dart b/lib/screens/profile/components/basic_information/address/edit_modal.dart new file mode 100644 index 0000000..83ac0d4 --- /dev/null +++ b/lib/screens/profile/components/basic_information/address/edit_modal.dart @@ -0,0 +1,703 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/global_context.dart'; +import '../../../../../model/location/barangay.dart'; +import '../../../../../model/location/city.dart'; +import '../../../../../model/location/country.dart'; +import '../../../../../model/location/provinces.dart'; +import '../../../../../model/location/region.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/location_utilities.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class EditAddressScreen extends StatefulWidget { + final int profileId; + final String token; + const EditAddressScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _EditAddressScreenState(); +} + +class _EditAddressScreenState extends State { + ////boolean + bool hasLotandBlock = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + ////selected + AddressCategory? selectedAddressCategory; + Area? selectedAreaClass; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Barangay? selectedBarangay; + Country? selectedCountry; + ////Lists + final List areaClass = [ + const Area(value: "Rural Area", group: 0), + const Area(value: "Sitio", group: 1), + const Area(value: "Village", group: 1), + const Area(value: "Urban Area", group: 0), + const Area(value: "Town", group: 1), + const Area(value: "City", group: 1), + const Area(value: "Metropolis", group: 1), + const Area(value: "Megacity", group: 1), + ]; + final List category = [ + AddressCategory(id: 1, name: "Permanent", type: "home"), + AddressCategory(id: 2, name: "Residential", type: "home"), + AddressCategory(id: 3, name: "Birthplace", type: "home") + ]; + List? provinces; + List? citymuns; + List? barangays; + final formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is EditAddressState) { + overseas = state.overseas; + if (!overseas) { + selectedRegion = state.currentRegion; + provinces = state.provinces; + selectedProvince = state.currentProvince; + citymuns = state.cities; + selectedMunicipality = state.currentCity; + barangays = state.baragays; + selectedBarangay = state.currentBarangay; + selectedCountry = state.currentCountry; + } else { + selectedCountry = state.currentCountry; + } + selectedAddressCategory = category.firstWhere( + (AddressCategory category) => + category.id == state.address.address!.category!.id); + if (state.address.address?.areaClass != null) { + selectedAreaClass = areaClass.firstWhere((Area area) => + area.value.toLowerCase() == + state.address.address!.areaClass!.toLowerCase()); + } else { + selectedAreaClass = null; + } + if (state.address.subdivision != null) { + hasLotandBlock = true; + } else { + hasLotandBlock = false; + } + return FormBuilder( + key: formKey, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 32, horizontal: 24), + child: SizedBox( + height: screenHeight * 88, + child: ListView( + children: [ + //// category + FormBuilderDropdown( + initialValue: selectedAddressCategory, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: + normalTextFieldStyle("Category*", "Category"), + name: "category", + onChanged: (AddressCategory? category) { + selectedAddressCategory = category; + }, + items: category + .map>( + (AddressCategory category) { + return DropdownMenuItem( + value: category, child: Text(category.name!)); + }).toList()), + const SizedBox( + height: 12, + ), + ////Area Class + FormBuilderDropdown( + initialValue: selectedAreaClass, + decoration: normalTextFieldStyle( + "Area class *", "Area class"), + name: "area_class", + onChanged: (Area? area) { + selectedAreaClass = area; + }, + items: areaClass + .map>((Area area) { + return area.group == 0 + ? DropdownMenuItem( + enabled: false, + value: area, + child: Text(area.value.toUpperCase(), + style: const TextStyle( + color: Colors.black38))) + : DropdownMenuItem( + value: area, + enabled: true, + child: Text( + " ${area.value.toUpperCase()}")); + }).toList()), + const SizedBox( + height: 12, + ), + ////stateful builder + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + ////with block & Lot Switch + FormBuilderSwitch( + initialValue: hasLotandBlock, + activeColor: second, + onChanged: (value) { + setState(() { + hasLotandBlock = value!; + }); + }, + decoration: normalTextFieldStyle( + "With Lot and Block?", 'Graduated?'), + name: 'graudated', + title: Text(hasLotandBlock ? "YES" : "NO"), + ), + SizedBox( + height: hasLotandBlock ? 12 : 0, + ), + SizedBox( + width: screenWidth, + child: hasLotandBlock + ? Row( + children: [ + ////block # + Flexible( + flex: 1, + child: FormBuilderTextField( + initialValue: state.address + .subdivision?.blockNo + ?.toString(), + validator: FormBuilderValidators + .compose([numericRequired]), + keyboardType: + TextInputType.number, + name: "block_number", + decoration: + normalTextFieldStyle( + "Block #*", "Block #"), + )), + const SizedBox( + width: 8, + ), + //// lot # + Flexible( + flex: 1, + child: FormBuilderTextField( + initialValue: state + .address.subdivision?.lotNo + ?.toString(), + validator: FormBuilderValidators + .compose([numericRequired]), + name: "lot_number", + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "Lot #*", "Lot #"), + )), + ], + ) + : Container(), + ), + ], + ); + }), + const SizedBox( + height: 12, + ), + //// Address Line + FormBuilderTextField( + initialValue: state.address.details, + name: "address_line", + decoration: normalTextFieldStyle( + "Address Line *", "Address Line"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 8 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + DropdownButtonFormField( + isExpanded: true, + value: selectedRegion, + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + onChanged: (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + //// GET PROVINCES + try{ + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion!.code + .toString()); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + //// GET CITIES + try{ + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAY + try{ + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + ////GET CITY MUNICIPALITY + try{ + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAYS + try{ + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + } + }, + decoration: normalTextFieldStyle( + "Region*", "Region"), + items: state.regions + .map>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 8, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: (Province? + province) async { + if (selectedProvince != + province) { + selectedProvince = + province; + setState(() { + cityCall = true; + }); + + //// GET CITIES + try{ + citymuns = await LocationUtils + .instance + .getCities( + code: + selectedProvince! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAY + try{ + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: (CityMunicipality? + city) async { + if (selectedMunicipality != + city) { + setState(() { + barangayCall = true; + }); + selectedMunicipality = city; + selectedMunicipality = city; + //// GET BARANGAYS + try{ + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + }catch(e){ + NavigationService.navigatorKey.currentContext?.read().add(CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + } + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: barangayCall, + child: DropdownButtonFormField< + Barangay>( + isExpanded: true, + onChanged: (Barangay? baragay) { + selectedBarangay = baragay; + }, + decoration: + normalTextFieldStyle( + "Barangay*", + "Barangay"), + value: selectedBarangay, + items: barangays == null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>( + (Barangay barangay) { + return DropdownMenuItem( + value: barangay, + child: Text(barangay + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: FormBuilderDropdown( + initialValue:selectedCountry!.id == 175?null:selectedCountry, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: + Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + setState((){ + selectedCountry = value; + }); + }, + ), + ), + ), + ], + ); + }), + const SizedBox(height: 8,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + String? lotNumber; + String? blockNumber; + String? addressLine; + + if (overseas) { + selectedCountry = selectedCountry; + } else { + selectedCountry = Country( + id: 175, + name: 'Philippines', + code: 'PH'); + } + + AddressClass address = AddressClass( + barangay: + overseas ? null : selectedBarangay, + id: state.address.id, + category: null, + areaClass: selectedAreaClass?.value, + cityMunicipality: overseas + ? null + : selectedMunicipality, + country: selectedCountry); + if (hasLotandBlock) { + lotNumber = formKey + .currentState!.value['lot_number']; + blockNumber = formKey + .currentState!.value['block_number']; + } + addressLine = formKey + .currentState?.value['address_line']; + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(UpdateAddress( + address: address, + profileId: widget.profileId, + token: widget.token, + blockNumber: blockNumber != null + ? int.parse(blockNumber) + : null, + categoryId: selectedAddressCategory!.id!, + details: addressLine, + lotNumber: lotNumber != null + ? int.parse(lotNumber) + : null)); + } + }, + child: const Text(submit)), + ), + + ], + ), + ), + )); + } + return const Placeholder(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + barangayCall = true; + getBarangays(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getBarangays() async { + try { + List newBarangays = await LocationUtils.instance + .getBarangay(code: selectedMunicipality!.code.toString()); + barangays = newBarangays; + setState(() { + selectedBarangay = newBarangays[0]; + barangayCall = false; + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } +} + +class Area { + final int group; + final String value; + const Area({required this.group, required this.value}); +} diff --git a/lib/screens/profile/components/basic_information/address_screen.dart b/lib/screens/profile/components/basic_information/address_screen.dart new file mode 100644 index 0000000..c7ebf40 --- /dev/null +++ b/lib/screens/profile/components/basic_information/address_screen.dart @@ -0,0 +1,373 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/address/add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/address/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../utils/alerts.dart'; + +class AddressScreen extends StatelessWidget { + const AddressScreen({super.key}); + + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is AddAddressState?const Text("Add Address"):context.watch().state is EditAddressState?const Text("Edit Address"):const Text("Addresses"), + centerTitle: true, + backgroundColor: primary, + actions:(context.watch().state is AddressLoadedState)?[ + AddLeading(onPressed: () { + context.read().add(ShowAddAddressForm()); + }) + ]:(context.watch().state is AddAddressState || context.watch().state is EditAddressState)?[ + CloseLeading(onPressed:() { + context.read().add(LoadAddress()); + }) + ]:[] + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is AddressLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is AddressLoadedState || + state is AddressErrorState || + state is AddAddressState || + state is EditAddressState || + state is AddressAddedState || state is EditAddressState || state is AddressUpdatedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is AddressAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Adding Failed", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } + ////updated State + if (state is AddressUpdatedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Update Failed", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } + //// Deleted + if (state is AddressDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull", + "Address has been deleted successfully", () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Address", () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } + }, + builder: (context, state) { + if (state is AddressLoadedState) { + bool overseas; + String? cityMunicipality; + String? province; + String? region; + String? barangay; + if (state.addresses.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.addresses.length, + itemBuilder: + (BuildContext context, int index) { + String? subdivision = + state.addresses[index].details ?? ''; + String? category = state.addresses[index] + .address?.category?.name??''; + + if (state.addresses[index].address?.cityMunicipality != null) { + barangay = state.addresses[index].address! + .barangay != + null + ? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},' + : ''; + cityMunicipality = state + .addresses[index] + .address! + .cityMunicipality! + .description!; + province = state + .addresses[index] + .address! + .cityMunicipality! + .province! + .description!; + region = state + .addresses[index] + .address! + .cityMunicipality! + .province! + .region! + .description!; + overseas = false; + } else { + overseas = true; + } + + return Column( + children: [ + Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: + const EdgeInsets.fromLTRB( + 8, 16, 0, 16), + child: Row(children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: screenWidth, + child: Row( + + children: [ + Flexible( + child: Text( + subdivision, + style: + Theme.of(context) + .textTheme + .titleMedium!.copyWith(color: primary,fontWeight: FontWeight.w600), + ), + ), + SizedBox( + width: subdivision.isEmpty? 0: 24, + ), + Flexible( + child: Text( + category, + style: + Theme.of(context) + .textTheme + .bodySmall, + ), + ) + ], + ), + ), + + const SizedBox( + height: 8, + ), + Container( + child: overseas + ? Text( + "COUNTRY: ${state.addresses[index].address?.country?.name?.toUpperCase()}", + textAlign: + TextAlign + .start, + style: Theme.of( + context) + .textTheme + .titleSmall, + ) + : Text( + "$barangay $cityMunicipality, $province, $region", + style: Theme.of( + context) + .textTheme + .titleSmall, + )), + ], + )), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete eligibilty-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + context + .read() + .add(DeleteAddress( + id: state + .addresses[ + index] + .id!, + profileId: profileId + .toString(), + token: token!)); + }, "Delete?", + "Confirm Delete?"); + + } + if (value == 1) { + bool overseas; + ////edit eligibilty-= = = = = = = = =>> + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + + if (state + .addresses[index] + .address + ?.cityMunicipality == + null) { + overseas = true; + } else { + overseas = false; + } + context + .read() + .add(ShowEditAddressForm( + overseas: + overseas, + address: state + .addresses[ + index])); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ]), + ), + ], + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have address added. Please click + to add."); + } + } + if (state is AddressErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () {context.read().add(LoadAddress());}); + } + if (state is AddAddressState) { + return AddAddressScreen( + profileId: profileId!, token: token!); + } + if (state is EditAddressState) { + return EditAddressScreen( + profileId: profileId!, token: token!); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/citizenship/add_modal.dart b/lib/screens/profile/components/basic_information/citizenship/add_modal.dart new file mode 100644 index 0000000..d1a75f0 --- /dev/null +++ b/lib/screens/profile/components/basic_information/citizenship/add_modal.dart @@ -0,0 +1,16 @@ +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; + +class MyWidget extends StatefulWidget { + const MyWidget({super.key}); + + @override + State createState() => _MyWidgetState(); +} + +class _MyWidgetState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} \ No newline at end of file diff --git a/lib/screens/profile/components/basic_information/citizenship/loading.dart b/lib/screens/profile/components/basic_information/citizenship/loading.dart new file mode 100644 index 0000000..7ae534a --- /dev/null +++ b/lib/screens/profile/components/basic_information/citizenship/loading.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +class CitizenshipLoading extends StatelessWidget { + const CitizenshipLoading({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Container( + height: 120, + width: 120, + decoration: const BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: const [ + SpinKitFadingCircle(size: 42, color: Colors.white), + SizedBox( + height: 12, + ), + Text( + "Please wait..", + style: TextStyle(color: Colors.white), + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/profile/components/basic_information/citizenship_screen.dart b/lib/screens/profile/components/basic_information/citizenship_screen.dart new file mode 100644 index 0000000..3980950 --- /dev/null +++ b/lib/screens/profile/components/basic_information/citizenship_screen.dart @@ -0,0 +1,450 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/primary_information/citizenship/citizenship_bloc.dart'; +import 'package:unit2/model/profile/basic_information/citizenship.dart'; +import 'package:unit2/screens/profile/components/basic_information/citizenship/loading.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../model/location/country.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/alerts.dart'; + +class CitizenShipScreen extends StatefulWidget { + final int profileId; + final String token; + + const CitizenShipScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _CitizenShipScreenState(); +} + +List countries = []; +bool naturalBorn = false; +Country? selectedCountry; +final formKey = GlobalKey(); + +class _CitizenShipScreenState extends State { + @override + Widget build(BuildContext context) { + final bloc = BlocProvider.of(context); + return ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocConsumer( + listener: (context, state) { + if (state is CitizenshipAddedState) { + if (state.responseStatus['success']) { + successAlert( + context, "Add Successfull!", state.responseStatus['message'], + () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } + } + + if (state is CitizenshipEditedState) { + if (state.responseStatus['success']) { + successAlert(context, "Update Successfull!", + state.responseStatus['message'], () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } else { + errorAlert(context, "Update Failed", + state.responseStatus['message'], () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } + } + + ////DELETED STATE + if (state is CitizenshipDeleltedState) { + if (state.succcess) { + successAlert(context, "Deletion Successfull", + "Contact Info has been deleted successfully", () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } else { + errorAlert( + context, "Deletion Failed", "Error deleting Contact Info", + () { + Navigator.of(context).pop(); + context.read().add(const LoadCitizenship()); + }); + } + } + }, + builder: (context, state) { + if (state is CitizenshipLoaded) { + return Scaffold( + appBar: AppBar( + title: const Text(citizenshipScreenTitle), + centerTitle: true, + backgroundColor: primary, + actions: [ + AddLeading(onPressed: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text("Add Citizenship"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + initialValue: null, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + const SizedBox( + height: 12, + ), + FormBuilderSwitch( + initialValue: naturalBorn, + activeColor: second, + onChanged: (value) { + setState(() { + naturalBorn = value!; + }); + }, + decoration: normalTextFieldStyle( + "Natural Born?", 'Natural Born?'), + name: 'graudated', + title: Text(naturalBorn ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle(primary, + Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + Navigator.pop(context); + bloc.add(AddCitizenship( + coiuntryId: + selectedCountry!.id!, + naturalBorn: naturalBorn, + profileId: widget.profileId, + token: widget.token)); + } + }, + child: const Text(submit)), + ) + ]), + ), + ); + }); + }) + ], + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 24, + ), + child: SizedBox( + width: screenWidth, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Philippines", + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w600, + color: primary), + ), + const SizedBox( + height: 3, + ), + Text( + "Filipino", + style: Theme.of(context).textTheme.bodyMedium, + ), + ]), + ), + ), + ListTile( + leading: const Icon(FontAwesome5.exclamation_circle), + title: Text( + "Your Filipino citizenship is added by default", + style: Theme.of(context).textTheme.bodySmall, + ), + ), + const Divider( + height: 2, + thickness: 1, + ), + SizedBox( + child: state.citizenships.isEmpty + ? Padding( + padding: const EdgeInsets.all(24), + child: Text( + "If you have citizenships other than Filipino, kindly add in this section", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall, + ), + ) + : SizedBox( + height: screenHeight * .70, + width: double.infinity, + child: ListView( + children: state.citizenships + .map((e) => Card( + child: Row( + children: [ + Expanded( + child: ListTile( + dense: true, + title: Text( + e.country!.name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w600, + color: primary), + ), + subtitle: Text( + e.naturalBorn! + ? "Natural Born" + : "Naturalized"), + ), + ), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete contact-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, + () { + context + .read< + CitizenshipBloc>() + .add(DeleteCitizenship( + coiuntryId: e + .country! + .id!, + naturalBorn: + e + .naturalBorn!, + profileId: widget + .profileId, + token: widget + .token)); + }, "Delete?", + "Are you sure you want to delete this contact info?"); + } + if (value == 1) { + ////edit contact-= = = = = = = = =>> + + showDialog( + context: context, + builder: (context) { + selectedCountry = state + .countries + .firstWhere((element) => + element + .id == + e.country! + .id); + return AlertDialog( + title: const Text( + "Add Citizenship"), + content: + FormBuilder( + key: formKey, + child: Column( + mainAxisSize: + MainAxisSize + .min, + children: [ + DropdownButtonFormField< + Country>( + isExpanded: + true, + value: + selectedCountry, + validator: + FormBuilderValidators.required(errorText: "This field is required"), + items: state + .countries + .map>((Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox(child: Text(country.name!))); + }).toList(), + decoration: normalTextFieldStyle( + "Country*", + "Country"), + onChanged: + (Country? value) { + selectedCountry = + value; + }, + ), + const SizedBox( + height: + 12, + ), + FormBuilderSwitch( + initialValue: + e.naturalBorn, + activeColor: + second, + onChanged: + (value) { + setState(() { + naturalBorn = value!; + }); + }, + decoration: normalTextFieldStyle( + "Natural Born?", + 'Natural Born?'), + name: + 'graudated', + title: Text(naturalBorn + ? "YES" + : "NO"), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: + double.infinity, + height: + 60, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + Citizenship newCitizenship = Citizenship(country: selectedCountry, naturalBorn: naturalBorn); + if (formKey.currentState!.saveAndValidate()) { + Navigator.pop(context); + bloc.add(EditCitizenship(citizenship: newCitizenship, profileId: widget.profileId, token: widget.token,oldCountryId: e.country!.id!)); + } + }, + child: const Text(submit)), + ) + ]), + ), + ); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + )) + .toList(), + ), + )) + ])); + } + if (state is CitizenshipLoadingState) { + return const Scaffold(body: CitizenshipLoading()); + } + if (state is CitizenshipErrorState) { + return Scaffold( + body: SomethingWentWrong( + message: state.message, onpressed: () {})); + } + return Container(); + }, + ), + ); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/contact_information/add_modal.dart b/lib/screens/profile/components/basic_information/contact_information/add_modal.dart new file mode 100644 index 0000000..0d7d0c2 --- /dev/null +++ b/lib/screens/profile/components/basic_information/contact_information/add_modal.dart @@ -0,0 +1,261 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; + +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../utils/formatters.dart'; + +class AddContactInformationScreen extends StatefulWidget { + final int profileId; + final String token; + const AddContactInformationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _AddContactInformationScreenState(); +} + +class _AddContactInformationScreenState + extends State { + final formKey = GlobalKey(); + ServiceType? selectedServiceType; + CommService? selectedCommServiceProvider; + List commServiceProviders = []; + bool callServiceType = false; + bool primaryaContact = false; + bool active = false; + String? numberMail; + final numberMailController = TextEditingController(); + + @override + void dispose() { + numberMailController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is ContactAddingState) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 24), + child: FormBuilder( + key: formKey, + child: StatefulBuilder(builder: (context, setState) { + return ListView( + children: [ + ////Service Type + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "service_type", + items: state.serviceTypes + .map>( + (ServiceType e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + decoration: normalTextFieldStyle("Service Type*", ""), + onChanged: (var service) async { + if (selectedServiceType != service) { + selectedServiceType = service; + setState(() { + callServiceType = true; + selectedCommServiceProvider = null; + numberMailController.text = ""; + }); + + try { + commServiceProviders = await ContactService + .instance + .getServiceProvider( + serviceTypeId: + selectedServiceType!.id!); + } catch (e) { + context + .read() + .add(CallErrorEvent(message: e.toString())); + } + setState(() { + setState(() { + callServiceType = false; + }); + }); + } + }), + const SizedBox( + height: 12, + ), + ////Service Provider + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: callServiceType, + child: DropdownButtonFormField( + isExpanded: true, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: commServiceProviders.isEmpty + ? [] + : commServiceProviders + .map>( + (CommService e) { + return DropdownMenuItem( + value: e, + child: Text(e + .serviceProvider!.agency!.name!)); + }).toList(), + decoration: normalTextFieldStyle( + "Communication Service *", ""), + onChanged: (var serviceProvider) { + selectedCommServiceProvider = serviceProvider; + }), + ), + ), + selectedServiceType != null + ? selectedServiceType?.id == 2 + //// Landline + ? FormBuilderTextField( + controller: numberMailController, + inputFormatters: [landLineFormatter], + name: 'number-mail', + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Landline number *", + "(area code) xxx - xxxx"), + ) + : selectedServiceType!.id == 1 || + selectedServiceType!.id == 19 + //// Mobile number + ? FormBuilderTextField( + keyboardType: TextInputType.number, + controller: numberMailController, + name: 'number-mail', + inputFormatters: [mobileFormatter], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Mobile number *", + "+63 (9xx) xxx - xxxx"), + ) + : selectedServiceType!.id == 4 + ////Social Media + ? FormBuilderTextField( + controller: numberMailController, + name: 'number-mail', + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Account ID / Username *", ""), + ) + : selectedServiceType!.id == 3 + ////Email Address + ? FormBuilderTextField( + controller: numberMailController, + name: 'number-mail', + validator: FormBuilderValidators + .compose([ + FormBuilderValidators.email( + errorText: + "Input vaild email"), + FormBuilderValidators.required( + errorText: + "This field is required") + ]), + decoration: normalTextFieldStyle( + "Email Address*", ""), + ) + : Container() + : const SizedBox(), + SizedBox( + height: selectedServiceType != null ? 12 : 0, + ), + //// Primary + FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + primaryaContact = value!; + }); + }, + decoration: + normalTextFieldStyle("Primary?", 'Primary?'), + name: 'overseas', + title: Text(primaryaContact ? "YES" : "NO"), + ), + //// Active + const SizedBox( + height: 12, + ), + FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + active = value!; + }); + }, + decoration: normalTextFieldStyle("Active?", ''), + name: 'overseas', + title: Text(active ? "YES" : "NO"), + ), + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + numberMail = + formKey.currentState!.value['number-mail']; + CommService commService = + selectedCommServiceProvider!; + ContactInfo contactInfo = ContactInfo( + id: null, + active: active, + primary: primaryaContact, + numbermail: numberMail, + commService: commService); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + AddContactInformation( + contactInfo: contactInfo, + profileId: widget.profileId, + token: widget.token)); + } + }, + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + ), + ), + ], + ); + })), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart b/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart new file mode 100644 index 0000000..f2e713d --- /dev/null +++ b/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart @@ -0,0 +1,287 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../../../theme-data.dart/colors.dart'; + +class EditContactInformationScreen extends StatefulWidget { + final int profileId; + final String token; + const EditContactInformationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditContactInformationScreenState(); +} + +class _EditContactInformationScreenState + extends State { + final formKey = GlobalKey(); + ServiceType? selectedServiceType; + CommService? selectedCommProvider; + List commServiceProviders = []; + String? numberMail; + bool callServiceType = false; + bool? primaryaContact; + bool? active; + + var mobileFormatter = MaskTextInputFormatter( + mask: "+63 (###) ###-####", + filter: {"#": RegExp(r"^[1-9][0-9]*$")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + var landLineFormatter = MaskTextInputFormatter( + mask: "(###) ###-###", + filter: {"#": RegExp(r"^[0-9]")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + final numberMailController = TextEditingController(); + @override + void dispose() { + numberMailController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is ContactEditingState) { + selectedServiceType = state.selectedServiceType; + selectedCommProvider = state.selectedProvider; + commServiceProviders = state.commServiceProviders; + primaryaContact = state.contactInfo.primary; + active = state.contactInfo.active; + numberMailController.text = state.contactInfo.numbermail!; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 24), + child: FormBuilder( + key: formKey, + child: ListView( + children: [ + StatefulBuilder(builder: (context, setState) { + return Column(children: [ + ////Service Type + DropdownButtonFormField( + isExpanded: true, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + value: selectedServiceType, + items: state.serviceTypes + .map>( + (ServiceType e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + decoration: + normalTextFieldStyle("Service Type*", ""), + onChanged: (var service) async { + if (selectedServiceType!.id != service!.id) { + selectedServiceType = service; + setState(() { + callServiceType = true; + callServiceType = true; + + numberMailController.text = ""; + }); + try { + commServiceProviders = await ContactService + .instance + .getServiceProvider( + serviceTypeId: + selectedServiceType!.id!); + } catch (e) { + context.read().add( + CallErrorEvent(message: e.toString())); + } + selectedCommProvider = null; + setState(() { + setState(() { + callServiceType = false; + }); + }); + } + }), + const SizedBox( + height: 12, + ), + ////Service Provider + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: callServiceType, + child: DropdownButtonFormField( + isExpanded: true, + value: selectedCommProvider, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: commServiceProviders.isEmpty + ? [] + : commServiceProviders + .map>( + (CommService e) { + return DropdownMenuItem( + value: e, + child: Text(e.serviceProvider! + .agency!.name!)); + }).toList(), + decoration: normalTextFieldStyle( + "Communication Service *", ""), + onChanged: (var commServiceProvider) { + selectedCommProvider = commServiceProvider; + }), + ), + ), + selectedServiceType != null + ? selectedServiceType?.id == 2 + //// Landline + ? FormBuilderTextField( + controller: numberMailController, + name: 'number-mail', + inputFormatters: [landLineFormatter], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Landline number *", + "(area code) xxx - xxxx"), + ) + : selectedServiceType!.id == 1 || + selectedServiceType!.id == 19 + //// Mobile number + ? FormBuilderTextField( + controller: numberMailController, + name: 'number-mail', + inputFormatters: [mobileFormatter], + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Mobile number *", + "+63 (9xx) xxx - xxxx"), + ) + : selectedServiceType!.id == 4 + ////Social Media + ? FormBuilderTextField( + controller: numberMailController, + name: 'number-mail', + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Account ID / Username *", ""), + ) + : selectedServiceType!.id == 3 + ////Email Address + ? FormBuilderTextField( + controller: + numberMailController, + name: 'number-mail', + validator: FormBuilderValidators + .compose([ + FormBuilderValidators.email( + errorText: + "Input vaild email"), + FormBuilderValidators.required( + errorText: + "This field is required") + ]), + decoration: + normalTextFieldStyle( + "Email Address*", ""), + ) + : Container() + : const SizedBox(), + ]); + }), + SizedBox( + height: selectedServiceType != null ? 12 : 0, + ), + //// Primary + StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + primaryaContact = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'primary', + title: const Text("Primary ?"), + ); + }), + //// Active + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: active, + activeColor: second, + onChanged: (value) { + setState(() { + active = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'active', + title: const Text("Active ?"), + ); + }), + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + numberMail = + formKey.currentState!.value['number-mail']; + CommService commService = selectedCommProvider!; + ContactInfo contactInfo = ContactInfo( + id: state.contactInfo.id, + active: active, + primary: primaryaContact, + numbermail: numberMail, + commService: commService); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + EditContactInformation( + contactInfo: contactInfo, + profileId: widget.profileId, + token: widget.token)); + } + }, + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + ), + ) + ], + )), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/basic_information/contact_information_screen.dart b/lib/screens/profile/components/basic_information/contact_information_screen.dart new file mode 100644 index 0000000..05f3325 --- /dev/null +++ b/lib/screens/profile/components/basic_information/contact_information_screen.dart @@ -0,0 +1,392 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/contact_information/add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/contact_information/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +class ContactInformationScreen extends StatelessWidget { + const ContactInformationScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + int profileId; + String token; + return SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is ContactAddingState + ? const Text("Add Contact") + : context.watch().state is ContactEditingState + ? const Text("Edit Contact") + : const Text("Contact Information"), + centerTitle: true, + backgroundColor: primary, + actions: context.watch().state is ContactLoadedState + ? [ + AddLeading(onPressed: () { + context.read().add(ShowAddForm()); + }) + ] + : (context.watch().state is ContactAddingState || + context.watch().state + is ContactEditingState) + ? [ + CloseLeading(onPressed: () { + context.read().add(LoadContacts()); + }) + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token!; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is ContactLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ContactLoadedState || + state is ContactErrorState || + state is ContactAddingState || + state is ContactEditingState || + state is ContactDeletedState || + state is ContactAddedState || + state is ContactEditedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////ADDED CONTACT STATE + if (state is ContactAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } + } + + ////EDIT CONTACT STATE + if (state is ContactEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } + } + + ////DELETED STATE + if (state is ContactDeletedState) { + if (state.succcess) { + successAlert(context, "Deletion Successfull", + "Contact Info has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Contact Info", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadContacts()); + }); + } + } + }, + builder: (context, state) { + if (state is ContactLoadedState) { + if (state.contactInformation.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.contactInformation.length, + itemBuilder: + (BuildContext context, int index) { + String numberMail = state + .contactInformation[index] + .numbermail!; + String commService = state + .contactInformation[index] + .commService! + .serviceProvider! + .alias!; + return Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.fromLTRB( + 12, 12, 0, 12), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Row( + children: [ + Expanded( + child: Text( + numberMail, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight + .w500, + color: + primary)), + ), + ], + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Text( + commService + .toString() + .toUpperCase(), + style: Theme.of( + context) + .textTheme + .titleSmall, + ), + ), + state.contactInformation[index] + .active == + true + ? const Badge( + backgroundColor: + Colors + .green, + label: + Text( + "Active", + ), + ) + : const Badge( + backgroundColor: + Colors + .red, + label: + Text( + "Inactive", + ), + ), + const SizedBox( + width: 5), + state.contactInformation[index] + .primary == + true + ? const Badge( + backgroundColor: + Colors + .blue, + label: Text( + "Primary"), + ) + : const SizedBox() + ], + ), + ), + Text(state + .contactInformation[ + index] + .commService! + .serviceProvider! + .agency! + .name + .toString()), + ]), + ), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete contact-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + context + .read() + .add(DeleteContactInformation( + contactInfo: + state.contactInformation[ + index], + profileId: + profileId, + token: token)); + }, "Delete?", + "Are you sure you want to delete this contact info?"); + } + if (value == 1) { + ////edit contact-= = = = = = = = =>> + context + .read() + .add(ShowEditForm( + contactInfo: state + .contactInformation[ + index])); + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have contact information added. Please click + to add"); + } + } + if (state is ContactAddingState) { + return AddContactInformationScreen( + profileId: profileId, + token: token, + ); + } + if (state is ContactEditingState) { + return EditContactInformationScreen( + profileId: profileId, token: token); + } + if (state is ContactErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context + .read() + .add(LoadContacts()); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )), + ); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/edit_basic_info_modal.dart b/lib/screens/profile/components/basic_information/edit_basic_info_modal.dart new file mode 100644 index 0000000..4a24280 --- /dev/null +++ b/lib/screens/profile/components/basic_information/edit_basic_info_modal.dart @@ -0,0 +1,547 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/model/profile/basic_information/primary-information.dart'; +import 'package:unit2/screens/profile/components/basic_information/profile_other_info.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/formatters.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/validators.dart'; + +class EditBasicProfileInfoScreen extends StatefulWidget { + final int profileId; + final String token; + const EditBasicProfileInfoScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditBasicProfileInfoScreenState(); +} +final bdayController = TextEditingController(); +ProfileOtherInfo? selectedIndigency; +ProfileOtherInfo? selectedEthnicity; +ProfileOtherInfo? selectedReligion; +ProfileOtherInfo? selectedDisability; +ProfileOtherInfo? selectedGender; +String? selectedSex; +String? selectedBloodType; +String? selectedStatus; +String? selectedExtension; +final _formKey = GlobalKey(); + + +class _EditBasicProfileInfoScreenState + extends State { + @override + void dispose() { + super.dispose(); + } + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is BasicInformationEditingState) { + bdayController.text = state.primaryInformation.birthdate.toString(); + selectedSex = state.sexes.firstWhere((element) => + element.toLowerCase() == + state.primaryInformation.sex!.toLowerCase()); + if (state.primaryInformation.bloodType != null && state.primaryInformation.bloodType != "N/A") { + selectedBloodType = state.bloodTypes.firstWhere((element) => + element.toLowerCase() == + state.primaryInformation.bloodType?.toLowerCase()); + } + if (state.primaryInformation.nameExtension != null && + state.primaryInformation.nameExtension != "N/A") { + selectedExtension = state.extensions.firstWhere((element) => + element.toLowerCase() == + state.primaryInformation.nameExtension?.toLowerCase()); + } + if (state.primaryInformation.civilStatus != null) { + selectedStatus = state.civilStatus.firstWhere((element) => + element.toLowerCase() == + state.primaryInformation.civilStatus?.toLowerCase()); + } + if (state.primaryInformation.gender != null && + state.primaryInformation.gender != "N/A") { + selectedGender = state.genders.firstWhere((element) => + element.name!.toLowerCase() == + state.primaryInformation.gender?.toLowerCase()); + } + if (state.primaryInformation.ip != null && + state.primaryInformation.ip != "N/A") { + selectedIndigency = state.indigenous.firstWhere((element) => + element.name!.toLowerCase() == + state.primaryInformation.ip!.toLowerCase()); + } + if (state.primaryInformation.ethnicity != null && + state.primaryInformation.ethnicity != "N/A") { + selectedEthnicity = state.ethnicity.firstWhere((element) => + element.name!.toLowerCase() == + state.primaryInformation.ethnicity!.toLowerCase()); + } + if (state.primaryInformation.religion != null && + state.primaryInformation.religion != "N/A") { + selectedReligion = state.religion.firstWhere((element) => + element.name!.toLowerCase() == + state.primaryInformation.religion!.toLowerCase()); + } + if (state.primaryInformation.disability != null && + state.primaryInformation.disability != "N/A") { + selectedDisability = state.disability.firstWhere((element) => + element.name!.toLowerCase() == + state.primaryInformation.disability!.toLowerCase()); + } + + + + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32), + child: FormBuilder( + key: _formKey, + child: Column( + children: [ + Flexible( + child: ListView( + children: [ + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "lastname", + inputFormatters: [ + UpperCaseTextFormatter() + ], + initialValue: state.primaryInformation.lastName, + decoration: normalTextFieldStyle("Last name *", ""), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 15, + ), + FormBuilderTextField( + name: "firstname", + inputFormatters: [ + UpperCaseTextFormatter() + ], + initialValue: state.primaryInformation.firstName, + decoration: normalTextFieldStyle("First name *", ""), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 2, + child: FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + name: "middlename", + initialValue: state.primaryInformation.middleName??'', + decoration: normalTextFieldStyle("Middle name", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + //// name extension + child: DropdownButtonFormField( + value: selectedExtension, + decoration: + normalTextFieldStyle("Name Extension", ""), + + items: state.extensions + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + + selectedExtension = e; + }, + ), + ) + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Bday + Flexible( + flex: 1, + child: DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "*").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1970), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + ), + const SizedBox( + width: 10, + ), + + ////sex + Flexible( + flex: 1, + child: FormBuilderDropdown( + initialValue: selectedSex, + decoration: normalTextFieldStyle("Sex *", ""), + name: "sex", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: state.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex= e; + }, + ), + ) + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////blood type + Flexible( + flex: 1, + child: FormBuilderDropdown( + initialValue: selectedBloodType, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("Blood type *", ""), + name: "bloodtype", + items: state.bloodTypes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 10, + ), + //// civil status + Flexible( + flex: 1, + child: FormBuilderDropdown( + initialValue: selectedStatus, + decoration: normalTextFieldStyle("Civil status *", ""), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "extension", + items: state.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedStatus = e; + }, + ), + ), + const SizedBox( + width: 10, + ), + //// gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + value: selectedGender, + decoration: normalTextFieldStyle("Gender", ""), + items: state.genders + .map((element) => + DropdownMenuItem( + value: element, + child: Text(element.name!))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + name: "height", + validator: numericRequired, + initialValue: state.primaryInformation.heightM + .toString() + .toString(), + decoration: normalTextFieldStyle("Height (Meter) *", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + + child: FormBuilderTextField( + validator: numericRequired, + name: "weigth", + initialValue: + state.primaryInformation.weightKg!.toString(), + decoration: normalTextFieldStyle("Weight (Kg) *", ""), + ), + ), + ]), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + name: "prefix", + initialValue: state.primaryInformation.titlePrefix + .toString() + .toString(), + decoration: normalTextFieldStyle( + "Title Prefix", "Dr.,Atty.,Engr."), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + name: "suffix", + initialValue: state.primaryInformation.titleSuffix, + decoration: normalTextFieldStyle( + "Title Suffix", "PhD.,MD.,MS.,CE"), + ), + ), + ]), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Indigency + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + value: selectedIndigency, + decoration: normalTextFieldStyle("Indigency", ""), + items: state.indigenous + .map((element) => + DropdownMenuItem( + value: element, + child: Text(element.name!))) + .toList(), + onChanged: (e) { + selectedIndigency = e; + }, + ), + ), + const SizedBox( + width: 10, + ), + ////Ethnicity + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + value: selectedEthnicity, + decoration: normalTextFieldStyle("Ethnicity", ""), + items: state.ethnicity + .map((element) => + DropdownMenuItem( + value: element, + child: Text(element.name!))) + .toList(), + onChanged: (e) { + selectedEthnicity = e; + print(selectedEthnicity!.name); + print(selectedEthnicity! + .id); + }, + ), + ), + ]), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////religion + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + value: selectedReligion, + decoration: normalTextFieldStyle("Religion", ""), + items: state.religion + .map((element) => + DropdownMenuItem( + value: element, + child: Text(element.name!))) + .toList(), + onChanged: (e) { + selectedReligion = e; + }, + ), + ), + const SizedBox( + width: 10, + ), + ////disabilty + Flexible( + flex: 1, + child: DropdownButtonFormField( + + isExpanded: true, + value: selectedDisability, + decoration: normalTextFieldStyle("Disability", ""), + items: state.disability + .map((element) => + DropdownMenuItem( + value: element, + child: Text(element.name!))) + .toList(), + onChanged: (e) { + selectedDisability = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 24, + ), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String lastName = + _formKey.currentState!.value['lastname']; + String firstName = + _formKey.currentState!.value['firstname']; + String? middleName = + _formKey.currentState?.value['middlename']; + String? pref = + _formKey.currentState?.value['prefix']; + String suf = _formKey.currentState?.value['suffix']; + DateTime birthdate = + DateTime.parse(bdayController.text); + double? hM = + _formKey.currentState!.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? wKg = + _formKey.currentState!.value['weigth'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weigth']); + Profile primaryInformation = Profile( + webuserId: null, + id: state.primaryInformation.id, + lastName: lastName, + firstName: firstName, + middleName: middleName, + nameExtension: selectedExtension, + sex: selectedSex, + birthdate: birthdate, + civilStatus: selectedStatus, + bloodType: selectedBloodType =="NONE"?null:selectedBloodType, + heightM: hM, + weightKg: wKg, + photoPath: state.primaryInformation.photoPath, + esigPath: state.primaryInformation.esigPath, + maidenName: state.primaryInformation.maidenName, + deceased: state.primaryInformation.deceased, + uuidQrcode: state.primaryInformation.uuidQrcode, + titlePrefix: pref, + titleSuffix: suf, + showTitleId: + state.primaryInformation.showTitleId, + ethnicity: selectedEthnicity?.name, + disability: selectedDisability?.name, + gender: selectedGender?.name, + religion: selectedReligion?.name, + ip: selectedIndigency?.name); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + EditBasicProfileInformation( + disabilityId: selectedDisability?.id, + ethnicityId: selectedEthnicity?.id, + genderId: selectedGender?.id, + indigencyId: selectedIndigency?.id, + profileId: widget.profileId, + profileInformation: primaryInformation, + religionId: selectedReligion?.id, + token: widget.token)); + } + }, + child: const Text("Submit")), + ) + ], + ), + ), + ], + ), + ), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/basic_information/family/add_mobile_modal.dart b/lib/screens/profile/components/basic_information/family/add_mobile_modal.dart new file mode 100644 index 0000000..21b1560 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/add_mobile_modal.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; + +class AddMobileNumber extends StatelessWidget { + final Function onPressed; + final GlobalKey formKey; + const AddMobileNumber({super.key, required this.onPressed,required this.formKey}); + + @override + + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Emergency Contact Information"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: 'number_mail', + inputFormatters: [mobileFormatter], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Mobile number *", "+63 (9xx) xxx - xxxx"), + ), + const SizedBox( + height: 20, + ), + SizedBox( + width: 200, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + child: const Text("Submit"), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + onPressed(); + } + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/family/child_add_modal.dart b/lib/screens/profile/components/basic_information/family/child_add_modal.dart new file mode 100644 index 0000000..f1dac9e --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/child_add_modal.dart @@ -0,0 +1,353 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../model/profile/family_backround.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class ChildAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + const ChildAlert( + {super.key, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes,required this.familyBloc, required this.profileId, required this.token}); + + @override + State createState() => _ChildAlertState(); +} + +class _ChildAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Family - Child"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + FormBuilderDropdown( + + decoration: normalTextFieldStyle("Name extension", ""), + name: "extension", + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Sex *", ""), + name: "sex", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Gender", ""), + name: "gender", + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Blood type", ""), + name: "bloodtype", + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Civil status", ""), + name: "extension", + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + name: "height", + validator:FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender =="NONE"?null:selectedGender; + String? extension = selectedExtension=="NONE"?null:selectedExtension; + String? blood = selectedBloodType =="NONE"?null:selectedBloodType; + String? civilStatus = selectedCivilStatus =="NONE"?null:selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height']==null? null: + double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight']==null?null: + double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: null, + sex: sex, + gender: gender, + deceased: false, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground(company: company,position: position,relatedPerson: person,relationship: relationship,companyAddress: companyAddress,emergencyContact: emergnecyContacts,incaseOfEmergency: incaseOfEmergency,companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(AddFamily(familyBackground: familyBackground, profileId: widget.profileId, token: widget.token,relationshipId: 4)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} \ No newline at end of file diff --git a/lib/screens/profile/components/basic_information/family/child_edit_modal.dart b/lib/screens/profile/components/basic_information/family/child_edit_modal.dart new file mode 100644 index 0000000..29f0347 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/child_edit_modal.dart @@ -0,0 +1,376 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/family/family_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; + +class ChildEditAlert extends StatefulWidget { + final FamilyBackground familyBackground; + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + + const ChildEditAlert( + {super.key, + required this.familyBackground, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes, required this.familyBloc, required this.profileId, required this.token}); + + @override + State createState() => _ChildEditAlertState(); +} + +class _ChildEditAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + selectedExtension = widget.familyBackground.relatedPerson?.nameExtension; + selectedGender = widget.familyBackground.relatedPerson?.gender; + selectedSex = widget.familyBackground.relatedPerson?.sex; + selectedBloodType = widget.familyBackground.relatedPerson?.bloodType; + selectedCivilStatus = widget.familyBackground.relatedPerson?.civilStatus; + bdayController.text = widget.familyBackground.relatedPerson!.birthdate!.toString(); + deceased = widget.familyBackground.relatedPerson!.deceased!; + return AlertDialog( + title: const Text("Family - Child"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + initialValue: widget.familyBackground.relatedPerson!.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + initialValue: widget.familyBackground.relatedPerson!.firstName, + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + initialValue: widget.familyBackground.relatedPerson?.middleName, + name: "middlename", + + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + DropdownButtonFormField( + value: selectedExtension, + decoration: normalTextFieldStyle("Name extension", ""), + + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: DropdownButtonFormField( + decoration: normalTextFieldStyle("Sex *", ""), + value: selectedSex, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Gender", ""), + value: selectedGender, + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Blood type", ""), + value: selectedBloodType, + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Civil status", ""), + value: selectedCivilStatus, + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson?.heightM == null? null:widget.familyBackground.relatedPerson?.heightM.toString(), + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson?.weightKg == null? null:widget.familyBackground.relatedPerson?.weightKg.toString(), + name: "weight", + validator:FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender =="NONE"?null:selectedGender; + String? extension = selectedExtension=="NONE"?null:selectedExtension; + String? blood = selectedBloodType =="NONE"?null:selectedBloodType; + String? civilStatus = selectedCivilStatus =="NONE"?null:selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height']==null? null: + double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight']==null?null: + double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: widget.familyBackground.relatedPerson!.id, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground(company: company,position: position,relatedPerson: person,relationship: relationship,companyAddress: companyAddress,emergencyContact: emergnecyContacts,incaseOfEmergency: incaseOfEmergency,companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(Updatefamily(familyBackground: familyBackground, profileId: widget.profileId, token: widget.token,relationshipId: 4)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/father_add_modal.dart b/lib/screens/profile/components/basic_information/family/father_add_modal.dart new file mode 100644 index 0000000..4d8fd9e --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/father_add_modal.dart @@ -0,0 +1,374 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/family/family_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import 'package:unit2/utils/formatters.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class FatherAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + + const FatherAlert( + {super.key, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes, + required this.familyBloc, + required this.profileId, + required this.token}); + + @override + State createState() => _FatherAlertState(); +} + +class _FatherAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Family - Parental Parent"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + FormBuilderDropdown( + decoration: normalTextFieldStyle("Name extension", ""), + name: "extension", + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "*").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Sex *", ""), + name: "sex", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Gender", ""), + name: "gender", + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Blood type", ""), + name: "bloodtype", + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Civil status", ""), + name: "extension", + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: null, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(AddFamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: 1)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/father_edit_modal.dart b/lib/screens/profile/components/basic_information/family/father_edit_modal.dart new file mode 100644 index 0000000..cd7aa52 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/father_edit_modal.dart @@ -0,0 +1,409 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/family/family_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; + +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class FatherEditAlert extends StatefulWidget { + final FamilyBackground familyBackground; + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + + const FatherEditAlert( + {super.key, + required this.familyBackground, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes, + required this.familyBloc, + required this.profileId, + required this.token}); + + @override + State createState() => _FatherEditAlertState(); +} + +class _FatherEditAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + selectedExtension = widget.familyBackground.relatedPerson?.nameExtension; + selectedGender = widget.familyBackground.relatedPerson?.gender; + selectedSex = widget.familyBackground.relatedPerson?.sex; + selectedBloodType = widget.familyBackground.relatedPerson?.bloodType; + selectedCivilStatus = widget.familyBackground.relatedPerson?.civilStatus; + bdayController.text = + widget.familyBackground.relatedPerson!.birthdate!.toString(); + deceased = widget.familyBackground.relatedPerson!.deceased!; + return AlertDialog( + title: const Text("Family - Parental Parent"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.firstName, + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson?.middleName, + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + DropdownButtonFormField( + value: selectedExtension, + decoration: normalTextFieldStyle("Name extension", ""), + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: DropdownButtonFormField( + decoration: normalTextFieldStyle("Sex *", ""), + value: selectedSex, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Gender", ""), + value: selectedGender, + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Blood type", ""), + value: selectedBloodType, + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Civil status", ""), + value: selectedCivilStatus, + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.heightM == + null + ? null + : widget.familyBackground.relatedPerson?.heightM + .toString(), + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Number only"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.weightKg == + null + ? null + : widget.familyBackground.relatedPerson?.weightKg + .toString(), + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Number only"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: widget.familyBackground.relatedPerson!.id, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(Updatefamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: 1)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/mother_add_modal.dart b/lib/screens/profile/components/basic_information/family/mother_add_modal.dart new file mode 100644 index 0000000..e91b965 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/mother_add_modal.dart @@ -0,0 +1,410 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../model/profile/family_backround.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class MotherAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + const MotherAlert( + {super.key, + required this.familyBloc, + required this.profileId, + required this.token, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes}); + + @override + State createState() => _MotherAlertState(); +} + +class _MotherAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Family - Maternal Parent"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + FormBuilderDropdown( + decoration: normalTextFieldStyle("Name extension", ""), + name: "extension", + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), +////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "*").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Sex *", ""), + name: "sex", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Gender", ""), + name: "gender", + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Blood type", ""), + name: "bloodtype", + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Civil status", ""), + name: "extension", + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + + ////height + child: FormBuilderTextField( + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 8, + ), + Text( + "Maiden Name", + style: Theme.of(context).textTheme.labelLarge, + ), + const SizedBox( + height: 8, + ), + ////maiden lastname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "maiden_lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + + const SizedBox( + height: 8, + ), + ////maiden middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "maiden_middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String? maidenMiddleName = _formKey + .currentState?.value['maiden_middlename']; + String maidenLastName = + _formKey.currentState!.value['maiden_lastname']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: MaidenName( + lastName: maidenLastName, + middleName: maidenMiddleName), + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: null, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(AddFamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: 2)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/mother_edit_modal.dart b/lib/screens/profile/components/basic_information/family/mother_edit_modal.dart new file mode 100644 index 0000000..f6d287b --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/mother_edit_modal.dart @@ -0,0 +1,398 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/family/family_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class MotherEditAlert extends StatefulWidget { + final FamilyBackground familyBackground; + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + + const MotherEditAlert( + {super.key, + required this.familyBackground, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.sexes, required this.familyBloc, required this.profileId, required this.token}); + + @override + State createState() => _MotherEditAlertState(); +} + +class _MotherEditAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + bool deceased = false; + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + selectedExtension = widget.familyBackground.relatedPerson?.nameExtension; + selectedGender = widget.familyBackground.relatedPerson?.gender; + selectedSex = widget.familyBackground.relatedPerson?.sex; + selectedBloodType = widget.familyBackground.relatedPerson?.bloodType; + selectedCivilStatus = widget.familyBackground.relatedPerson?.civilStatus; + bdayController.text = widget.familyBackground.relatedPerson!.birthdate!.toString(); + deceased = widget.familyBackground.relatedPerson!.deceased!; + return AlertDialog( + title: const Text("Family - Parental Parent"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: widget.familyBackground.relatedPerson!.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: widget.familyBackground.relatedPerson!.firstName, + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: widget.familyBackground.relatedPerson?.middleName, + name: "middlename", + + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + DropdownButtonFormField( + value: selectedExtension, + decoration: normalTextFieldStyle("Name extension", ""), + + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "*").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: DropdownButtonFormField( + decoration: normalTextFieldStyle("Sex *", ""), + value: selectedSex, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Gender", ""), + value: selectedGender, + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Blood type", ""), + value: selectedBloodType, + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Civil status", ""), + value: selectedCivilStatus, + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + + initialValue: widget.familyBackground.relatedPerson?.heightM == null? null:widget.familyBackground.relatedPerson?.heightM.toString(), + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson?.weightKg == null? null:widget.familyBackground.relatedPerson?.weightKg.toString(), + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 8, + ), + Text( + "Maiden Name", + style: Theme.of(context).textTheme.labelLarge, + ), + const SizedBox( + height: 8, + ), + ////maiden lastname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: widget.familyBackground.relatedPerson?.maidenName?.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "maiden_lastname", + decoration: normalTextFieldStyle("Last name", ""), + ), + + const SizedBox( + height: 8, + ), + ////maiden middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: widget.familyBackground.relatedPerson?.maidenName?.middleName, + name: "maiden_middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String? maidenMiddleName = _formKey.currentState?.value['maiden_middlename']; + String maidenLastName = _formKey.currentState!.value['maiden_lastname']; + String bday = bdayController.text; + String? gender = selectedGender =="NONE"?null:selectedGender; + String? extension = selectedExtension=="NONE"?null:selectedExtension; + String? blood = selectedBloodType =="NONE"?null:selectedBloodType; + String? civilStatus = selectedCivilStatus =="NONE"?null:selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height']==null? null: + double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight']==null?null: + double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: MaidenName(middleName: maidenMiddleName,lastName: maidenLastName), + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: widget.familyBackground.relatedPerson!.id, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground(company: company,position: position,relatedPerson: person,relationship: relationship,companyAddress: companyAddress,emergencyContact: emergnecyContacts,incaseOfEmergency: incaseOfEmergency,companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(Updatefamily(familyBackground: familyBackground, profileId: widget.profileId, token: widget.token,relationshipId: 1)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/related_add_modal.dart b/lib/screens/profile/components/basic_information/family/related_add_modal.dart new file mode 100644 index 0000000..4f27934 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/related_add_modal.dart @@ -0,0 +1,403 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../model/profile/family_backround.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class RelatedAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final List relationships; + final String token; + final int profileId; + final FamilyBloc familyBloc; + + const RelatedAlert({ + super.key, + required this.bloodType, + required this.token, + required this.profileId, + required this.familyBloc, + required this.civilStatus, + required this.relationships, + required this.gender, + required this.nameExtensions, + required this.sexes, + }); + + @override + State createState() => _RelatedAlertState(); +} + +class _RelatedAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + Relationship? selectedRelationship; + bool deceased = false; +@override + void dispose() { +bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Family - Other Related Person"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////Relationship + FormBuilderDropdown( + decoration: normalTextFieldStyle("Relationship *", ""), + name: "extension", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.relationships.map( + (element) { + return DropdownMenuItem( + value: element, + child: Text(element.type!), + ); + }, + ).toList(), + onChanged: (e) { + selectedRelationship = e; + }, + ), + const SizedBox( + height: 8, + ), + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + FormBuilderDropdown( + decoration: normalTextFieldStyle("Name extension", ""), + name: "extension", + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Sex", ""), + name: "sex *", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Gender", ""), + name: "gender", + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Blood type", ""), + name: "bloodtype", + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Civil status", ""), + name: "extension", + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + name: "weight", + validator:FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 8, + ), + + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: null, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(AddFamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: selectedRelationship!.id!)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/related_edit_modal.dart b/lib/screens/profile/components/basic_information/family/related_edit_modal.dart new file mode 100644 index 0000000..72849db --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/related_edit_modal.dart @@ -0,0 +1,430 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/family/family_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import 'package:unit2/utils/formatters.dart'; + +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; + +class RelatedEditAlert extends StatefulWidget { + final FamilyBackground familyBackground; + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final String token; + final int profileId; + final FamilyBloc familyBloc; + final List relationships; + + const RelatedEditAlert( + {super.key, + required this.familyBackground, + required this.bloodType, + required this.civilStatus, + required this.gender, + required this.nameExtensions, + required this.relationships, + required this.sexes, + required this.familyBloc, + required this.profileId, + required this.token}); + + @override + State createState() => _RelatedEditAlertState(); +} + +class _RelatedEditAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + Relationship? selectedRelationship; + bool deceased = false; + @override + void dispose() { + bdayController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + selectedExtension = widget.familyBackground.relatedPerson?.nameExtension; + selectedGender = widget.familyBackground.relatedPerson?.gender; + selectedSex = widget.familyBackground.relatedPerson?.sex; + selectedBloodType = widget.familyBackground.relatedPerson?.bloodType; + selectedCivilStatus = widget.familyBackground.relatedPerson?.civilStatus; + selectedRelationship = widget.relationships.firstWhere((element) => element.id == widget.familyBackground.relationship!.id); + bdayController.text = + widget.familyBackground.relatedPerson!.birthdate!.toString(); + deceased = widget.familyBackground.relatedPerson!.deceased!; + return AlertDialog( + title: const Text("Family - Other Related Person"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////Relationship + DropdownButtonFormField( + decoration: normalTextFieldStyle("Relationship *", ""), + value: selectedRelationship, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.relationships.map( + (element) { + return DropdownMenuItem( + value: element, + child: Text(element.type!), + ); + }, + ).toList(), + onChanged: (e) { + selectedRelationship = e; + }, + ), + const SizedBox(height: 8,), + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.firstName, + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson?.middleName, + name: "middlename", + + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + DropdownButtonFormField( + value: selectedExtension, + decoration: normalTextFieldStyle("Name extension", ""), + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1900), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: DropdownButtonFormField( + decoration: normalTextFieldStyle("Sex *", ""), + value: selectedSex, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Gender", ""), + value: selectedGender, + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Blood type", ""), + value: selectedBloodType, + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Civil status", ""), + value: selectedCivilStatus, + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.heightM == + null + ? null + : widget.familyBackground.relatedPerson?.heightM + .toString(), + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.weightKg == + null + ? null + : widget.familyBackground.relatedPerson?.weightKg + .toString(), + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + Company? company; + PositionTitle? position; + double? height = + _formKey.currentState?.value['height'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = + _formKey.currentState?.value['weight'] == null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + String? companyAddress; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: widget.familyBackground.relatedPerson!.id, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: null); + Navigator.of(context).pop(); + + widget.familyBloc.add(Updatefamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: selectedRelationship!.id!)); + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/spouse_add_modal.dart b/lib/screens/profile/components/basic_information/family/spouse_add_modal.dart new file mode 100644 index 0000000..dca9326 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/spouse_add_modal.dart @@ -0,0 +1,797 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; + +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../model/profile/family_backround.dart'; +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; +import '../../../shared/add_for_empty_search.dart'; + +class SpouseAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final List positions; + final List agencies; + final List category; + final FamilyBloc familyBloc; + final String token; + final int profileId; + + const SpouseAlert( + {super.key, + required this.token, + required this.profileId, + required this.familyBloc, + required this.bloodType, + required this.civilStatus, + required this.agencies, + required this.category, + required this.positions, + required this.gender, + required this.nameExtensions, + required this.sexes}); + + @override + State createState() => _SpouseAlertState(); +} + +class _SpouseAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + PositionTitle? selectedPosition; + Category? selectedAgencyCategory; + Agency? selectedAgency; + bool deceased = false; + + final agencyFocusNode = FocusNode(); + final positionFocusNode = FocusNode(); + final appointmentStatusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + + final addAgencyController = TextEditingController(); + final addPositionController = TextEditingController(); + + bool hasOccupation = false; + bool showAgency = false; + bool? isPrivate = false; + bool showIsPrivateRadio = false; + @override + void dispose() { + bdayController.dispose(); + agencyFocusNode.dispose(); + positionFocusNode.dispose(); + appointmentStatusNode.dispose(); + agencyCategoryFocusNode.dispose(); + addAgencyController.dispose(); + addPositionController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("Family - Spouse"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + FormBuilderDropdown( + decoration: normalTextFieldStyle("Name extension", ""), + name: "extension", + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList()), + + const SizedBox( + height: 8, + ), + + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1970), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Sex *", ""), + name: "sex", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Gender", ""), + name: "gender", + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Blood type", ""), + name: "bloodtype", + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: FormBuilderDropdown( + decoration: normalTextFieldStyle("Civil status", ""), + name: "civil_status", + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + name: "height", + validator: FormBuilderValidators.numeric( + errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: + normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + name: "weight", + validator: FormBuilderValidators.numeric( + errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 8, + ), + ////Has Occupation + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: hasOccupation, + title: Text(hasOccupation ? "YES" : "NO"), + decoration: + normalTextFieldStyle("Has Occupation?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + hasOccupation = value!; + }); + }, + + name: 'hasOccupation', + validator: FormBuilderValidators.required(), + ), + Container( + child: hasOccupation + ? Column( + children: [ + const SizedBox( + height: 8, + ), + StatefulBuilder( + builder: (context, setState) { + ////Position + return SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: widget.positions + .map((PositionTitle position) => + SearchFieldListItem( + position.title!, + item: position, + child: Padding( + padding: + const EdgeInsets + .symmetric( + horizontal: + 10), + child: ListTile( + title: Text( + position.title!, + overflow: + TextOverflow + .visible, + ), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Position *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + positionFocusNode.unfocus(); + }, + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + positionFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Position", + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = + PositionTitle( + id: null, + title: + addPositionController + .text + .toUpperCase()); + + widget.positions.insert( + 0, newAgencyPosition); + + addPositionController.text = + ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 8, + ), + StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: widget.agencies + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + "Agency *", "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + agencyFocusNode.unfocus(); + }, + )), + onSuggestionTap: (agency) { + setState(() { + selectedAgency = + agency.item; + + if (selectedAgency! + .privateEntity == + null) { + showIsPrivateRadio = true; + } else { + showIsPrivateRadio = + false; + } + + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: + addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController + .text + .toUpperCase(), + category: null, + privateEntity: + null); + + widget.agencies.insert( + 0, newAgency); + selectedAgency = + newAgency; + addAgencyController + .text = ""; + showAgency = true; + + showIsPrivateRadio = + true; + + Navigator.pop(context); + }); + }, + title: "Add Agency")), + + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: + agencyCategoryFocusNode, + itemHeight: 70, + suggestionDirection: + SuggestionDirection + .up, + suggestions: widget + .category + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text( + category + .name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedAgencyCategory = + agencyCategory + .item; + agencyCategoryFocusNode + .unfocus(); + selectedAgency = Agency( + id: null, + name: + selectedAgency! + .name, + category: + selectedAgencyCategory, + privateEntity: + null); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon(Icons + .arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode + .unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + const SizedBox( + height: 8, + ), + ////PRVIATE SECTOR + SizedBox( + width: screenWidth, + child: showIsPrivateRadio + ? FormBuilderSwitch( + initialValue: isPrivate, + title: Text(isPrivate! + ? "YES" + : "NO"), + decoration: + normalTextFieldStyle( + "Private Entity?", + ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + isPrivate = value; + selectedAgency = Agency( + id: null, + name: + selectedAgency! + .name, + category: + selectedAgencyCategory, + privateEntity: + isPrivate); + agencyFocusNode + .unfocus(); + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + + const SizedBox( + height: 8, + ), + ////Company Address + FormBuilderTextField( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + name: "company_address", + decoration: normalTextFieldStyle( + "Company Address/Business Address *", + "Company Address/Business Address *"), + ), + const SizedBox( + height: 8, + ), + ////Company Tel Number + FormBuilderTextField( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + name: "company_tel", + decoration: normalTextFieldStyle( + "Company /Business Tel./Mobile # *", + "Company /Business Tel./Mobile # *"), + ), + ], + ); + }), + ], + ) + : const SizedBox(), + ), + ], + ); + }), + ), + + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = + selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + String? companyAddress = _formKey + .currentState?.value['company_address']; + String? companyContactNumber = + _formKey.currentState?.value['company_tel']; + Company? company = selectedAgency == null + ? null + : Company( + id: selectedAgency?.id, + name: selectedAgency?.name, + category: selectedAgencyCategory, + privateEntity: isPrivate); + PositionTitle? position = selectedPosition; + double? height = _formKey + .currentState?.value['height'] == + null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = _formKey + .currentState?.value['weight'] == + null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: null, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: company, + position: position, + relatedPerson: person, + relationship: relationship, + companyAddress: companyAddress, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: + companyContactNumber); + Navigator.of(context).pop(); + + widget.familyBloc.add(AddFamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: 3)); + } + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/family/spouse_edit_modal.dart b/lib/screens/profile/components/basic_information/family/spouse_edit_modal.dart new file mode 100644 index 0000000..5526016 --- /dev/null +++ b/lib/screens/profile/components/basic_information/family/spouse_edit_modal.dart @@ -0,0 +1,840 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import '../../../../../bloc/profile/family/family_bloc.dart'; +import '../../../../../model/profile/family_backround.dart'; +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../model/utils/position.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; +import '../../../shared/add_for_empty_search.dart'; + +class SpouseEditAlert extends StatefulWidget { + final List nameExtensions; + final List gender; + final List sexes; + final List bloodType; + final List civilStatus; + final List positions; + final List agencies; + final List category; + final FamilyBloc familyBloc; + final String token; + final int profileId; + final FamilyBackground familyBackground; + + const SpouseEditAlert( + {super.key, + required this.familyBackground, + required this.token, + required this.profileId, + required this.familyBloc, + required this.bloodType, + required this.civilStatus, + required this.agencies, + required this.category, + required this.positions, + required this.gender, + required this.nameExtensions, + required this.sexes}); + + @override + State createState() => _SpouseEditAlertState(); +} + +class _SpouseEditAlertState extends State { + final _formKey = GlobalKey(); + final bdayController = TextEditingController(); + + ////selected + String? selectedExtension; + String? selectedGender; + String? selectedSex; + String? selectedBloodType; + String? selectedCivilStatus; + PositionTitle? selectedPosition; + Category? selectedAgencyCategory; + Agency? selectedAgency; + bool deceased = false; + + final agencyFocusNode = FocusNode(); + final positionFocusNode = FocusNode(); + final appointmentStatusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + + final addAgencyController = TextEditingController(); + final addPositionController = TextEditingController(); + final oldPositionController = TextEditingController(); + final oldAppointmentStatusController = TextEditingController(); + final oldAgencyController = TextEditingController(); + bool hasOccupation = false; + bool showAgency = false; + bool? isPrivate = false; + bool showIsPrivateRadio = false; + @override + Widget build(BuildContext context) { + selectedExtension = widget.familyBackground.relatedPerson?.nameExtension; + selectedGender = widget.familyBackground.relatedPerson?.gender; + selectedSex = widget.familyBackground.relatedPerson?.sex; + selectedBloodType = widget.familyBackground.relatedPerson?.bloodType; + selectedCivilStatus = widget.familyBackground.relatedPerson?.civilStatus; + bdayController.text = + widget.familyBackground.relatedPerson!.birthdate!.toString(); + deceased = widget.familyBackground.relatedPerson!.deceased!; + hasOccupation = widget.familyBackground.position != null; + oldPositionController.text = widget.familyBackground.position == null + ? "" + : widget.familyBackground.position!.title!; + oldAgencyController.text = widget.familyBackground.company == null + ? "" + : widget.familyBackground.company!.name!; + selectedAgency = widget.familyBackground.company == null + ? null + : Agency( + id: widget.familyBackground.company!.id, + name: widget.familyBackground.company!.name, + category: widget.familyBackground.company!.category, + privateEntity: widget.familyBackground.company!.privateEntity); + return AlertDialog( + title: const Text("Family - Spouse"), + contentPadding: const EdgeInsets.all(24), + content: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.lastName, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle("Last name *", ""), + ), + const SizedBox( + height: 8, + ), + //// firstname + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson!.firstName, + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle("First name *", ""), + ), + const SizedBox( + height: 8, + ), + ////middle name + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: + widget.familyBackground.relatedPerson?.middleName, + name: "middlename", + decoration: normalTextFieldStyle("Middle name", ""), + ), + + const SizedBox( + height: 8, + ), + //// extension + DropdownButtonFormField( + value: selectedExtension, + decoration: normalTextFieldStyle("Name extension", ""), + items: widget.nameExtensions + .map((element) => DropdownMenuItem( + value: element, + child: Text(element), + )) + .toList(), + onChanged: (e) { + selectedExtension = e; + }, + ), + + const SizedBox( + height: 8, + ), + ////Bday + DateTimePicker( + controller: bdayController, + use24HourFormat: false, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + timeHintText: "Birthdate", + decoration: + normalTextFieldStyle("Birthdate *", "").copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + firstDate: DateTime(1970), + lastDate: DateTime(2100), + icon: const Icon(Icons.date_range), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + //// sex + child: DropdownButtonFormField( + decoration: normalTextFieldStyle("Sex *", ""), + value: selectedSex, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: widget.sexes + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedSex = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + ////gender + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Gender", ""), + value: selectedGender, + items: widget.gender + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedGender = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + ////Blood Type + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Blood type", ""), + value: selectedBloodType, + items: widget.bloodType + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedBloodType = e; + }, + ), + ), + const SizedBox( + width: 8, + ), + //// Civil Status + Flexible( + flex: 1, + child: DropdownButtonFormField( + isExpanded: true, + decoration: normalTextFieldStyle("Civil status", ""), + value: selectedCivilStatus, + items: widget.civilStatus + .map((element) => DropdownMenuItem( + value: element, child: Text(element))) + .toList(), + onChanged: (e) { + selectedCivilStatus = e; + }, + ), + ), + ]), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + ////height + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.heightM == + null + ? null + : widget.familyBackground.relatedPerson?.heightM + .toString(), + name: "height", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Height (Meter)", ""), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 1, + //// weight + child: FormBuilderTextField( + initialValue: widget.familyBackground.relatedPerson + ?.weightKg == + null + ? null + : widget.familyBackground.relatedPerson?.weightKg + .toString(), + name: "weight", + validator: FormBuilderValidators.numeric(errorText: "Enter a number"), + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle("Weight (Kg.)", ""), + ), + ), + const SizedBox( + height: 8, + ), + ]), + ), + const SizedBox( + height: 8, + ), + ////Deceased + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: deceased, + title: Text(deceased ? "YES" : "NO"), + decoration: normalTextFieldStyle("Deceased?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + deceased = value!; + }); + }, + + name: 'deceased', + validator: FormBuilderValidators.required(), + ); + }), + ), + const SizedBox( + height: 8, + ), + ////Has Occupation + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: hasOccupation, + title: Text(hasOccupation ? "YES" : "NO"), + decoration: + normalTextFieldStyle("Has Occupation?", ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + hasOccupation = value!; + }); + }, + + name: 'hasOccupation', + validator: FormBuilderValidators.required(), + ), + Container( + child: hasOccupation + ? Column( + children: [ + const SizedBox( + height: 8, + ), + StatefulBuilder( + builder: (context, setState) { + ////Position + return SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: oldPositionController, + suggestionDirection: + SuggestionDirection.down, + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: widget.positions + .map((PositionTitle position) => + SearchFieldListItem( + position.title!, + item: position, + child: Padding( + padding: + const EdgeInsets + .symmetric( + horizontal: + 10), + child: ListTile( + title: Text(position + .title!,overflow: TextOverflow + .visible,), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Position *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + positionFocusNode.unfocus(); + }, + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + positionFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: Container( + padding: const EdgeInsets.only(top: 25), + child: EmptyWidget( + title: "Add Position", + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = + PositionTitle( + id: null, + title: + addPositionController + .text + .toUpperCase()); + + widget.positions.insert( + 0, newAgencyPosition); + + addPositionController.text = + ""; + Navigator.pop(context); + }); + }), + ), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 8, + ), + StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + ////Company + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: oldAgencyController, + itemHeight: 100, + suggestionDirection: + SuggestionDirection.down, + focusNode: agencyFocusNode, + suggestions: widget.agencies + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + "Agency *", "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + agencyFocusNode.unfocus(); + }, + )), + onSuggestionTap: (agency) { + setState(() { + selectedAgency = + agency.item; + + if (selectedAgency! + .privateEntity == + null) { + showIsPrivateRadio = true; + } else { + showIsPrivateRadio = + false; + } + + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: + addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController + .text + .toUpperCase(), + category: null, + privateEntity: + null); + + widget.agencies.insert( + 0, newAgency); + selectedAgency = + newAgency; + addAgencyController + .text = ""; + showAgency = true; + + showIsPrivateRadio = + true; + + Navigator.pop(context); + }); + }, + title: "Add Agency")), + + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: + agencyCategoryFocusNode, + itemHeight: 70, + suggestions: widget + .category + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text( + category + .name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedAgencyCategory = + agencyCategory + .item; + agencyCategoryFocusNode + .unfocus(); + selectedAgency = Agency( + id: null, + name: + selectedAgency! + .name, + category: + selectedAgencyCategory, + privateEntity: + null); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon(Icons + .arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode + .unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + const SizedBox( + height: 8, + ), + ////PRVIATE SECTOR + SizedBox( + width: screenWidth, + child: showIsPrivateRadio + ? FormBuilderSwitch( + initialValue: isPrivate, + title: Text(isPrivate! + ? "YES" + : "NO"), + decoration: + normalTextFieldStyle( + "Private Entity?", + ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + isPrivate = value; + selectedAgency = Agency( + id: null, + name: + selectedAgency! + .name, + category: + selectedAgencyCategory, + privateEntity: + isPrivate); + agencyFocusNode + .unfocus(); + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + + const SizedBox( + height: 8, + ), + ////Company Address + FormBuilderTextField( + initialValue: widget + .familyBackground + .companyAddress, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + name: "company_address", + decoration: normalTextFieldStyle( + "Company Address/Business Address *", + "Company Address/Business Address *"), + ), + const SizedBox( + height: 8, + ), + ////Company Tel Number + FormBuilderTextField( + initialValue: widget + .familyBackground + .companyContactNumber, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + name: "company_tel", + decoration: normalTextFieldStyle( + "Company /Business Tel./Mobile # *", + "Company /Business Tel./Mobile # *"), + ), + ], + ); + }), + ], + ) + : const SizedBox(), + ), + ], + ); + }), + ), + + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + height: 50, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + if (_formKey.currentState!.saveAndValidate()) { + String fname = + _formKey.currentState!.value['firstname']; + String lastName = + _formKey.currentState!.value['lastname']; + String? mname = + _formKey.currentState?.value['middlename']; + String bday = bdayController.text; + String? gender = selectedGender == "NONE" + ? null + : selectedGender; + String? extension = selectedExtension == "NONE" + ? null + : selectedExtension; + String? blood = selectedBloodType == "NONE" + ? null + : selectedBloodType; + String? civilStatus = + selectedCivilStatus == "NONE" + ? null + : selectedCivilStatus; + String? sex = selectedSex; + String? companyAddress = _formKey + .currentState?.value['company_address']; + String? companyContactNumber = + _formKey.currentState?.value['company_tel']; + Company? company = selectedAgency == null + ? null + : Company( + id: selectedAgency?.id, + name: selectedAgency?.name, + category: selectedAgencyCategory, + privateEntity: isPrivate); + PositionTitle? position = selectedPosition; + double? height = _formKey + .currentState?.value['height'] == + null + ? null + : double.tryParse( + _formKey.currentState?.value['height']); + double? weight = _formKey + .currentState?.value['weight'] == + null + ? null + : double.tryParse( + _formKey.currentState?.value['weight']); + Relationship relationship = Relationship( + id: 1, + type: "Paternal_Parent", + category: "Family"); + List? emergnecyContacts; + bool incaseOfEmergency = false; + RelatedPerson person = RelatedPerson( + titlePrefix: null, + firstName: fname, + maidenName: null, + middleName: mname, + lastName: lastName, + birthdate: DateTime.parse(bday), + id: widget.familyBackground.relatedPerson!.id, + sex: sex, + gender: gender, + deceased: deceased, + heightM: height, + weightKg: weight, + esigPath: null, + bloodType: blood, + photoPath: null, + uuidQrcode: null, + nameExtension: extension, + civilStatus: civilStatus, + titleSuffix: null, + showTitleId: false, + ); + FamilyBackground familyBackground = + FamilyBackground( + company: hasOccupation ? company : null, + position: hasOccupation ? position : null, + relatedPerson: person, + relationship: relationship, + companyAddress: + hasOccupation ? companyAddress : null, + emergencyContact: emergnecyContacts, + incaseOfEmergency: incaseOfEmergency, + companyContactNumber: hasOccupation + ? companyContactNumber + : null); + Navigator.of(context).pop(); + + widget.familyBloc.add(Updatefamily( + familyBackground: familyBackground, + profileId: widget.profileId, + token: widget.token, + relationshipId: 3)); + } + } + }, + child: const Text(submit)), + ), + ], + )), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/identification/add_modal.dart b/lib/screens/profile/components/basic_information/identification/add_modal.dart new file mode 100644 index 0000000..3ef7946 --- /dev/null +++ b/lib/screens/profile/components/basic_information/identification/add_modal.dart @@ -0,0 +1,938 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart'; +import 'package:unit2/model/utils/industry_class.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/formatters.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../../../model/location/city.dart'; +import '../../../../../model/location/country.dart'; +import '../../../../../model/location/provinces.dart'; +import '../../../../../model/location/region.dart'; +import '../../../../../model/profile/basic_information/identification_information.dart'; +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/global_context.dart'; +import '../../../../../utils/location_utilities.dart'; +import '../../../shared/add_for_empty_search.dart'; + +class AddIdentificationScreen extends StatefulWidget { + final int profileId; + final String token; + const AddIdentificationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _AddIdentificationScreenState(); +} + +class _AddIdentificationScreenState extends State { + final addAgencyController = TextEditingController(); + final dateIssuedController = TextEditingController(); + final expirationController = TextEditingController(); + final agencyFocusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + bool showAgency = false; + bool showIsPrivateRadio = false; + bool asPdfReference = false; + bool isPrivate = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool otherAgency = false; + ////selected + Agency? selectedAgency; + Category? selectedCategoty; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + List? provinces; + List? citymuns; + DateTime? issuedDate; + DateTime? expirationDate; + final formKey = GlobalKey(); + List? requiredAgency = [ + Agency( + id: 173, + name: "GOVERNMENT SERVICE INSURANCE SYSTEM (GSIS)", + category: Category( + id: 16, + name: "Government-Owned and Controlled Corporations (GOCC)", + industryClass: IndustryClass( + description: null, name: "Public Governance", id: 16)), + privateEntity: false), + Agency( + id: 2, + name: "SOCIAL SECURITY SYSTEM (SSS)", + category: Category( + id: 202, + name: "Government-Owned and Controlled Corporations (GOCC)", + industryClass: IndustryClass( + id: 16, name: "Public Governance", description: null)), + privateEntity: false), + Agency( + id: 3, + name: "HOME DEVELOPMENT MUTUAL FUND (PAG-IBIG FUND)", + category: Category( + id: 202, + name: "Government-Owned and Controlled Corporations (GOCC)", + industryClass: IndustryClass( + name: "Public Governance", id: 16, description: null)), + privateEntity: false), + Agency( + id: 4, + name: "BUREAU OF INTERNAL REVENUE (BIR)", + category: Category( + id: 201, + name: "National Government Agency", + industryClass: IndustryClass( + id: 16, name: "Public Governance", description: null), + ), + privateEntity: false), + Agency( + id: 165, + name: "PHILIPPINE HEALTH INSURANCE CORPORATION (PHILHEALTH)", + category: Category( + id: 202, + name: "Government-Owned and Controlled Corporations (GOCC)", + industryClass: IndustryClass( + id: 16, name: "Public Governance", description: null)), + privateEntity: false), + Agency(id: 0, name: "OTHERS"), + ]; + List requiredIds = [173, 2, 3, 4, 165]; + @override + void dispose() { + dateIssuedController.dispose(); + addAgencyController.dispose(); + expirationController.dispose(); + agencyFocusNode.dispose(); + agencyCategoryFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, + builder: (context, state) { + if (state is IdentificationAddingState) { + for (var agency in state.addedAgencies) { + if (requiredIds.contains(agency.id)) { + Agency? newAgency = requiredAgency + ?.firstWhere((element) => element.id == agency.id); + if (newAgency != null) { + requiredAgency!.remove(newAgency); + } + } + } + return Padding( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: FormBuilder( + key: formKey, + child: SizedBox( + height: screenHeight * 90, + child: ListView( + children: [ + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + isExpanded: true, + decoration: normalTextFieldStyle( + "Select Agency", "Select Agency"), + name: "requiredAgency", + items: requiredAgency! + .map>( + (Agency agency) { + return DropdownMenuItem( + value: agency, + child: Container( + width: double.infinity, + decoration: + box1().copyWith(boxShadow: []), + child: Text( + agency.name!, + maxLines: 3, + )), + ); + }).toList(), + onChanged: (value) { + selectedAgency = value; + + if (value!.id == 0) { + setState(() { + otherAgency = true; + }); + } else { + isPrivate = value.privateEntity!; + setState(() { + otherAgency = false; + }); + } + }, + ), + SizedBox( + height: otherAgency ? 12 : 0, + ), + ////Other agency + SizedBox( + child: otherAgency + ? StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + ////Company + SizedBox( + child: SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 100, + focusNode: + agencyFocusNode, + suggestions: state + .agencies + .map((Agency + agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: + ListTile( + title: Text( + agency + .name!, + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency.privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + "Agency *", "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyFocusNode + .unfocus(), + )), + onSuggestionTap: + (agency) { + setState(() { + selectedAgency = + agency.item; + + if (selectedAgency! + .privateEntity == + null) { + showIsPrivateRadio = + true; + } else { + showIsPrivateRadio = + false; + } + + agencyFocusNode + .unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: + addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController + .text + .toUpperCase(), + category: + null, + privateEntity: + null); + + state.agencies + .insert(0, + newAgency); + selectedAgency = + newAgency; + addAgencyController + .text = ""; + showAgency = true; + + showIsPrivateRadio = + true; + + Navigator.pop( + context); + }); + }, + title: "Add Agency")), + ), + + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: + agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state + .agencyCategory + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text( + category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: + Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedCategoty = + agencyCategory + .item; + agencyCategoryFocusNode + .unfocus(); + selectedAgency = Agency( + id: null, + name: + selectedAgency! + .name, + category: + selectedCategoty, + privateEntity: + null); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons + .arrow_drop_down, + ), + onTap: () => + agencyCategoryFocusNode + .unfocus(), + )), + validator: (value) { + if (value! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + const SizedBox( + height: 12, + ), + ////PRVIATE SECTOR + SizedBox( + width: screenWidth, + child: showIsPrivateRadio + ? FormBuilderSwitch( + initialValue: + isPrivate, + title: Text( + isPrivate + ? "YES" + : "NO"), + decoration: + normalTextFieldStyle( + "Private Entity?", + ""), + ////onvhange private sector + onChanged: (value) { + setState(() { + isPrivate = + value!; + selectedAgency = Agency( + id: null, + name: selectedAgency! + .name, + category: + selectedCategoty, + privateEntity: + isPrivate); + agencyFocusNode + .unfocus(); + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + ], + ); + }) + : const SizedBox(), + ), + ], + ); + }), + SizedBox( + height: otherAgency ? 8 : 0, + ), + + const SizedBox( + height: 8, + ), + //// Identification numner + FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "identification_number", + decoration: normalTextFieldStyle( + "Identification Number *", ""), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Row( + children: [ + //// Date Issued + Flexible( + flex: 1, + child: DateTimePicker( + type: DateTimePickerType.date, + controller: dateIssuedController, + use24HourFormat: false, + icon: const Icon(Icons.date_range), + selectableDayPredicate: (date) { + if (expirationDate != null && + expirationDate! + .microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + issuedDate = DateTime.parse(value); + }); + }, + initialDate: expirationDate == null + ? DateTime.now() + : expirationDate!.subtract( + const Duration(days: 1)), + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: "Date Issued", + decoration: normalTextFieldStyle( + "Date Issued *", + "Date Issued *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + )), + const SizedBox( + width: 8, + ), + //// Expiration Date + Flexible( + flex: 1, + child: DateTimePicker( + type: DateTimePickerType.date, + controller: expirationController, + use24HourFormat: false, + icon: const Icon(Icons.date_range), + firstDate: DateTime(1990), + lastDate: DateTime(2100), + selectableDayPredicate: (date) { + if (issuedDate != null && + issuedDate! + .microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + timeHintText: "Expiration date", + decoration: normalTextFieldStyle( + "Expiration Date *", + "Expiration Date *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialDate: issuedDate == null + ? DateTime.now() + : issuedDate! + .add(const Duration(days: 1)), + onChanged: (value) { + setState(() { + expirationDate = + DateTime.parse(value); + }); + }, + )), + ], + ); + }), + const SizedBox( + height: 12, + ), + //// as pdf reference + StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: asPdfReference, + activeColor: second, + onChanged: (value) { + setState(() { + asPdfReference = value!; + }); + }, + decoration: normalTextFieldStyle( + "As PDF Reference?", ''), + name: 'pdf_reference', + title: Text(asPdfReference ? "YES" : "NO"), + ); + }), + const SizedBox( + height: 12, + ), + //// OVERSEAS + //// OVERSEAS + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 8 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + DropdownButtonFormField( + isExpanded: true, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: + (Region? region) async { + if (selectedRegion != + region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion! + .code + .toString()); + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + IdentificationBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + } catch (e) { + context + .read< + IdentificationBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + } + }, + value: selectedRegion, + decoration: + normalTextFieldStyle( + "Region*", "Region"), + items: state.regions.map< + DropdownMenuItem< + Region>>( + (Region region) { + return DropdownMenuItem< + Region>( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + + isExpanded: true, + value: selectedProvince, + onChanged: (Province? + province) async { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + context + .read< + IdentificationBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + } + }, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province + province) { + return DropdownMenuItem( + value: + province, + child: + FittedBox( + child: Text( + province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: + DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? + city) { + if (selectedMunicipality != + city) { + selectedMunicipality = + city; + } + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality + c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: DropdownButtonFormField< + Country>( + isExpanded: true, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + items: state.countries.map< + DropdownMenuItem< + Country>>( + (Country country) { + return DropdownMenuItem< + Country>( + value: country, + child: FittedBox( + child: Text( + country.name!))); + }).toList(), + value: selectedCountry, + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + const SizedBox(height: 8,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + IssuedAt issuedAt; + if (overseas) { + issuedAt = IssuedAt( + id: null, + barangay: null, + addressCategory: null, + issuedAtClass: null, + cityMunicipality: null, + country: selectedCountry); + } else { + issuedAt = IssuedAt( + id: null, + barangay: null, + addressCategory: null, + issuedAtClass: null, + cityMunicipality: overseas + ? null + : selectedMunicipality, + country: Country( + id: 175, + name: 'Philippines', + code: 'PH')); + } + if (selectedCategoty != null) { + selectedAgency = Agency( + id: selectedAgency?.id, + name: selectedAgency!.name, + category: selectedCategoty, + privateEntity: isPrivate); + } + Identification identification = Identification( + id: null, + agency: selectedAgency, + issuedAt: issuedAt, + asPdfReference: asPdfReference, + identificationNumber: formKey.currentState! + .value['identification_number'], + dateIssued: + dateIssuedController.text.isEmpty + ? null + : DateTime.parse( + dateIssuedController.text), + expirationDate: + expirationController.text.isEmpty + ? null + : DateTime.tryParse( + expirationController.text)); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + AddIdentification( + identification: identification, + profileId: widget.profileId, + token: widget.token)); + } + }, + child: const Text(submit)), + ), + + + ], + ), + )), + ); + } + return Container(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } +} diff --git a/lib/screens/profile/components/basic_information/identification/edit_modal.dart b/lib/screens/profile/components/basic_information/identification/edit_modal.dart new file mode 100644 index 0000000..5a7d0b7 --- /dev/null +++ b/lib/screens/profile/components/basic_information/identification/edit_modal.dart @@ -0,0 +1,562 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../../../model/location/city.dart'; +import '../../../../../model/location/country.dart'; +import '../../../../../model/location/provinces.dart'; +import '../../../../../model/location/region.dart'; +import '../../../../../model/profile/basic_information/identification_information.dart'; +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/global_context.dart'; +import '../../../../../utils/location_utilities.dart'; +class EditIdentificationScreen extends StatefulWidget { + final int profileId; + final String token; + const EditIdentificationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditIdentificationScreenState(); +} + +class _EditIdentificationScreenState extends State { + final addAgencyController = TextEditingController(); + final dateIssuedController = TextEditingController(); + final expirationController = TextEditingController(); + final agencyFocusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + bool asPdfReference = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool otherAgency = false; + ////selected + Agency? selectedAgency; + Category? selectedCategoty; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + List? provinces; + List? citymuns; + + final formKey = GlobalKey(); +@override + void dispose() { + dateIssuedController.dispose(); + addAgencyController.dispose(); + expirationController.dispose(); + agencyFocusNode.dispose(); + agencyCategoryFocusNode.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is IdentificationEditingState) { + String? issuedDate = state.identification.dateIssued.toString(); + String? expDate = state.identification.expirationDate.toString(); + provinces = state.provinces; + citymuns = state.cities; + selectedCountry = state.currentCountry; + dateIssuedController.text = + issuedDate.isEmpty || issuedDate == "null" ? "" : issuedDate; + expirationController.text = + expDate.isEmpty || expDate == "null" ? "" : expDate; + selectedRegion = state.currentRegion; + selectedProvince = state.currentProvince; + selectedMunicipality = state.currentCity; + overseas = state.overseas; + asPdfReference = state.identification.asPdfReference!; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 24), + child: FormBuilder( + key: formKey, + child: SizedBox( + height: screenHeight * 90, + child: ListView( + children: [ + FormBuilderTextField( + initialValue: state.identification.agency!.name, + enabled: false, + name: "", + decoration: normalTextFieldStyle("", "").copyWith( + filled: true, fillColor: Colors.black12), + ), + SizedBox( + height: otherAgency ? 8 : 0, + ), + + const SizedBox( + height: 12, + ), + //// Identification numner + FormBuilderTextField( + initialValue: + state.identification.identificationNumber, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "identification_number", + decoration: normalTextFieldStyle( + "Identification Number *", ""), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context,setState) { + return Row( + children: [ + //// Date Issued + Flexible( + flex: 1, + child: DateTimePicker( + controller: dateIssuedController, + use24HourFormat: false, + icon: const Icon(Icons.date_range), + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: "Date Issued", + decoration: normalTextFieldStyle( + "Date Issued ", "Date Issued *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + onChanged: (value){ + setState((){ + issuedDate = value; + }); + }, + selectableDayPredicate: (date) { + if ((expDate != "null" && expDate != null) && + DateTime.tryParse(expDate!)! + .microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + initialDate: expDate == "null" || expDate == null + ? DateTime.now() + : DateTime.tryParse(expDate!)?.subtract( + const Duration(days: 1)), + )), + + const SizedBox( + width: 12, + ), + //// Expiration Date + Flexible( + flex: 1, + child: DateTimePicker( + controller: expirationController, + use24HourFormat: false, + icon: const Icon(Icons.date_range), + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: "Expiration date", + onChanged: (value){ + setState((){ + expDate = value; + }); + }, + decoration: normalTextFieldStyle( + "Expiration Date", + "Expiration Date") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + selectableDayPredicate: (date) { + if ((issuedDate != "null" && issuedDate != null) && + DateTime.tryParse(issuedDate!)! + .microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + initialDate: issuedDate == null && issuedDate == "null" + ? DateTime.now() + : DateTime.tryParse(issuedDate!)?.add( + const Duration(days: 1)), + )), + ], + ); + } + ), + const SizedBox( + height: 12, + ), + + //// OVERSEAS + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 12 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + DropdownButtonFormField( + isExpanded: true, + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: + (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion! + .code + .toString()); + } catch (e) { + context + .read< + IdentificationBloc>() + .add(ShowErrorState( + message: + e.toString())); + } + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + IdentificationBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + + } + }, + value: selectedRegion, + decoration: normalTextFieldStyle( + "Region*", "Region"), + items: state.regions.map< + DropdownMenuItem>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + value: selectedProvince, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + onChanged: (Province? + province) async { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + context + .read< + IdentificationBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province + province) { + return DropdownMenuItem( + value: province, + child: + FittedBox( + child: Text( + province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province *", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? city) { + if (selectedMunicipality != + city) { + selectedMunicipality = + city; + } + }, + decoration: + normalTextFieldStyle( + "Municipality *", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: + DropdownButtonFormField( + isExpanded: true, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: + Text(country.name!))); + }).toList(), + value: selectedCountry?.id==175?null:selectedCountry, + decoration: normalTextFieldStyle( + "Country *", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + + const SizedBox(height: 8,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + IssuedAt? issuedAt; + if (!overseas) { + issuedAt = IssuedAt( + id: state.identification.issuedAt!.id, + barangay: null, + addressCategory: state.identification.issuedAt?.addressCategory, + issuedAtClass: null, + cityMunicipality: selectedMunicipality, + country: Country(id: 175,code: "PH",name: "PHILIPPINES")); + }else{ + issuedAt = IssuedAt( + id: state.identification.issuedAt!.id, + barangay: null, + addressCategory: state.identification.issuedAt?.addressCategory, + issuedAtClass: null, + cityMunicipality: null, + country: selectedCountry); + } + + Identification identification = + Identification( + id: state.identification.id, + agency: state.identification.agency, + issuedAt: issuedAt, + asPdfReference: asPdfReference, + identificationNumber: + formKey + .currentState!.value[ + 'identification_number'], + dateIssued: + dateIssuedController + .text.isEmpty + ? null + : DateTime + .parse( + dateIssuedController + .text), + expirationDate: expirationController + .text.isEmpty + ? null + : DateTime.tryParse( + expirationController.text)); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + UpdateIdentifaction( + identification: identification, + profileId: widget.profileId, + token: widget.token)); + } + }, + child: const Text(submit)), + ), + ], + ), + )), + ); + } + return Container(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } +} diff --git a/lib/screens/profile/components/basic_information/identification_information_screen.dart b/lib/screens/profile/components/basic_information/identification_information_screen.dart new file mode 100644 index 0000000..eedd08d --- /dev/null +++ b/lib/screens/profile/components/basic_information/identification_information_screen.dart @@ -0,0 +1,371 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/identification/add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/identification/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../bloc/user/user_bloc.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../widgets/Leadings/close_leading.dart'; + +class IdentificationsScreen extends StatelessWidget { + const IdentificationsScreen({super.key}); + + @override + Widget build(BuildContext context) { + String? token; + int? profileId; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is IdentificationAddingState ? const Text("Add Identification"):context.watch().state is IdentificationEditingState?const Text("Edit Identification"):const Text("Identifications"), + + centerTitle: true, + backgroundColor: primary, + actions: (context.watch().state is IdentificationLoadedState)?[ + AddLeading(onPressed: () { + context.read().add(ShowAddIdentificationForm()); + }) + ]:(context.watch().state is IdentificationAddingState || context.watch().state is IdentificationEditingState)?[ + CloseLeading(onPressed:() { + context.read().add(LoadIdentifications()); + }) + ]:[] + + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is IdentificationLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is IdentificationLoadedState || + state is IdentificationAddingState || + state is IdentificationEditingState || + state is IdenficationErrorState || + state is IdentificationAddedState || + state is IdentificationDeletedState || + state is IdentificationEditedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + //// Added State + if (state is IdentificationAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } + } + //// Updated State + if (state is IdentificationEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } + } + + ////Deleted State + if (state is IdentificationDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull!", + "Identification Deleted Successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadIdentifications()); + }); + } + } + }, + builder: (context, state) { + if (state is IdentificationLoadedState) { + if (state.identificationInformation.isNotEmpty) { + String issuedAt; + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: + state.identificationInformation.length, + itemBuilder: + (BuildContext context, int index) { + String agency = state + .identificationInformation[index] + .agency! + .name!; + String idNumber = state + .identificationInformation[index] + .identificationNumber!; + bool government = state + .identificationInformation[index] + .agency! + .privateEntity!; + if(state.identificationInformation[index].issuedAt?.country?.id != 175){ + issuedAt= state.identificationInformation[index].issuedAt!.country!.name!.toUpperCase(); + }else{ + issuedAt = + "${state.identificationInformation[index].issuedAt!.cityMunicipality?.description!} ${state.identificationInformation[index].issuedAt!.cityMunicipality?.province!.description}"; + } + return Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text(agency, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w500,color: primary)), + + const SizedBox( + height: 5, + ), + + + Text( + "$idNumberText : $idNumber", + style: Theme.of( + context) + .textTheme + .titleSmall, + ), + + + + const SizedBox( + height: 5, + ), + Text(issuedAt,style: Theme.of(context).textTheme.titleSmall,), + const SizedBox(height: 8,), + Badge( + backgroundColor: + government != true?success2:second, + label: Text( + government == true + ? privateText + .toUpperCase() + : governmentText + .toUpperCase(), + style: Theme.of( + context) + .textTheme + .bodySmall! + .copyWith( + color: Colors + .white), + )) + ]), + ), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete identification-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + BlocProvider.of( + context) + .add(DeleteIdentification( + identificationId: + state + .identificationInformation[ + index] + .id!, + profileId: + profileId!, + token: token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + bool isOverseas; + ////edit voluntary work-= = = = = = = = =>> + final progress = + ProgressHUD.of(context); + progress!.showWithText( + "Loading..."); + if (state + .identificationInformation[ + index] + .issuedAt + ?.cityMunicipality!=null) { + isOverseas = false; + } else { + isOverseas = true; + } + context + .read< + IdentificationBloc>() + .add(ShowEditIdentificationForm( + identification: + state.identificationInformation[ + index], + profileId: + profileId!, + token: token!, + overseas: + isOverseas)); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have identifications added. Please click + to add."); + } + } + if (state is IdentificationAddingState) { + return AddIdentificationScreen( + token: token!, + profileId: profileId!, + ); + } + if (state is IdenficationErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () {context.read().add(LoadIdentifications());}); + } + if (state is IdentificationEditingState) { + return EditIdentificationScreen( + profileId: profileId!, token: token!); + } + + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/basic_information/primary_information_screen.dart b/lib/screens/profile/components/basic_information/primary_information_screen.dart new file mode 100644 index 0000000..1927bb1 --- /dev/null +++ b/lib/screens/profile/components/basic_information/primary_information_screen.dart @@ -0,0 +1,364 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/edit_basic_info_modal.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../utils/alerts.dart'; + +class PrimaryInfo extends StatefulWidget { + final int profileId; + final String token; + const PrimaryInfo({super.key, required this.profileId, required this.token}); + + @override + State createState() => _PrimaryInfoState(); +} + +class _PrimaryInfoState extends State { + @override + Widget build(BuildContext context) { + bool enabled = false; + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + return Scaffold( + appBar: AppBar( + title: context.watch().state + is BasicInformationEditingState + ? const Text("Edit Profile") + : const Text("Primary Information"), + centerTitle: true, + backgroundColor: primary, + actions: context.watch().state + is BasicInformationProfileLoaded + ? [ + IconButton( + onPressed: () { + context.read().add( + ShowPrimaryInfoEditForm(token: widget.token)); + }, + icon: const Icon(Icons.edit)) + ] + : context.watch().state + is BasicInformationEditingState + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(LoadBasicPrimaryInfo()); + }) + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is BasicPrimaryInformationLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is BasicInformationProfileLoaded || + state is BasicInformationEditingState || + state is BasicPrimaryInformationErrorState || + state is BasicProfileInfoEditedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + if (state is BasicProfileInfoEditedState) { + if (state.response['success']) { + successAlert(context, "Updated Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadBasicPrimaryInfo()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(LoadBasicPrimaryInfo()); + }); + } + } + }, + builder: (context, state) { + if (state is BasicInformationProfileLoaded) { + return Container( + padding: + const EdgeInsets.symmetric(vertical: 24, horizontal: 24), + child: Column( + children: [ + const SizedBox( + height: 28, + ), + FormBuilderTextField( + enabled: enabled, + name: lastname, + initialValue: state.primaryBasicInformation.lastName!, + decoration: normalTextFieldStyle("Last name", ""), + ), + const SizedBox( + height: 15, + ), + FormBuilderTextField( + enabled: enabled, + name: firstname, + initialValue: state.primaryBasicInformation.firstName!, + decoration: normalTextFieldStyle("First name", ""), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 2, + child: FormBuilderTextField( + enabled: enabled, + name: middlename, + initialValue: state.primaryBasicInformation.middleName??'' + , + decoration: + normalTextFieldStyle("Middle name", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: extensionName, + initialValue: state.primaryBasicInformation + .nameExtension ??= 'N/A', + decoration: + normalTextFieldStyle("Name extension", ""), + ), + ) + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: extensionName, + initialValue: dteFormat2.format( + state.primaryBasicInformation.birthdate!), + decoration: + normalTextFieldStyle("Birth date", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: sex, + initialValue: state.primaryBasicInformation.sex!, + decoration: normalTextFieldStyle("Sex", ""), + ), + ) + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: "bloodType", + initialValue: + state.primaryBasicInformation.bloodType!, + decoration: + normalTextFieldStyle("Blood type", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: "civilStatus", + initialValue: + state.primaryBasicInformation.civilStatus!, + decoration: + normalTextFieldStyle("Civil Status", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: "gender", + initialValue: state + .primaryBasicInformation.gender ??= "N/A", + decoration: normalTextFieldStyle("Gender", ""), + ), + ), + ]), + ), + const SizedBox( + height: 15, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + maxLines: 2, + enabled: enabled, + name: height, + initialValue: state + .primaryBasicInformation.heightM! + .toString(), + decoration: normalTextFieldStyle("Height", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: width, + initialValue: state + .primaryBasicInformation.weightKg! + .toString(), + decoration: normalTextFieldStyle("Weight", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: prefixSuffix, + initialValue: + "${state.primaryBasicInformation.titlePrefix ??= "NA"} | ${state.primaryBasicInformation.titleSuffix ??= "N/A"}", + decoration: normalTextFieldStyle( + "Title Prefix and Suffix", ""), + ), + ), + ]), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + maxLines: 2, + enabled: enabled, + name: height, + initialValue: state.primaryBasicInformation.ip ??= + "N/A", + decoration: + normalTextFieldStyle("Indigenous", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + enabled: enabled, + name: width, + initialValue: state + .primaryBasicInformation.ethnicity ??= "N/A", + decoration: normalTextFieldStyle("Ethnicity", ""), + ), + ), + ]), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row(children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + maxLines: 2, + enabled: enabled, + name: height, + initialValue: state + .primaryBasicInformation.religion ??= "N/A", + decoration: normalTextFieldStyle("Religion", ""), + ), + ), + const SizedBox( + width: 10, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + maxLines: 2, + enabled: enabled, + name: width, + initialValue: state + .primaryBasicInformation.disability ??= "N/A", + decoration: + normalTextFieldStyle("Disability", ""), + ), + ), + ]), + ), + ], + ), + ); + } + if (state is BasicPrimaryInformationErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(LoadBasicPrimaryInfo()); + }); + } + if (state is BasicInformationEditingState) { + return EditBasicProfileInfoScreen( + profileId: widget.profileId, token: widget.token); + } + return Container(); + }, + ), + )); + } +} diff --git a/lib/screens/profile/components/basic_information/profile_other_info.dart b/lib/screens/profile/components/basic_information/profile_other_info.dart new file mode 100644 index 0000000..79f75da --- /dev/null +++ b/lib/screens/profile/components/basic_information/profile_other_info.dart @@ -0,0 +1,25 @@ + + +class ProfileOtherInfo { + final int? id; + final String? name; + final String? description; + + ProfileOtherInfo({ + required this.id, + required this.name, + required this.description, + }); + + factory ProfileOtherInfo.fromJson(Map json) => ProfileOtherInfo( + id: json["id"], + name: json["name"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "name": name, + "description": description, + }; +} diff --git a/lib/screens/profile/components/education/add_modal.dart b/lib/screens/profile/components/education/add_modal.dart new file mode 100644 index 0000000..163f8fb --- /dev/null +++ b/lib/screens/profile/components/education/add_modal.dart @@ -0,0 +1,531 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/text_container.dart'; +import '../../shared/add_for_empty_search.dart'; + +class AddEducationScreen extends StatefulWidget { + final int profileId; + final String token; + const AddEducationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _AddEducationScreenState(); +} + +class _AddEducationScreenState extends State { + final List educationLevel = [ + const EducationLevel(type: "label", value: "Basic Education", group: 1), + const EducationLevel(type: "level", value: "Elementary", group: 1), + const EducationLevel(type: "level", value: "Secondary (non-K12)", group: 1), + const EducationLevel(type: "level", value: "Junior High", group: 1), + const EducationLevel(type: "level", value: "Senior High", group: 1), + const EducationLevel(type: "label", value: "Higher Education", group: 2), + const EducationLevel(type: "level", value: "Collegiate", group: 2), + const EducationLevel(type: "level", value: "Vocational", group: 2), + const EducationLevel(type: "label", value: "Post Graduate", group: 2), + const EducationLevel(type: "level", value: "Masteral", group: 2), + const EducationLevel(type: "level", value: "Doctorate", group: 2), + ]; + List valueItemHonorList = []; +////selected + EducationLevel? selectedLevel; + School? selectedSchool; + Course? selectedProgram; + List selectedHonors = []; + List? selectedValueItem; + final formKey = GlobalKey(); + ////congrollers + final addProgramController = TextEditingController(); + final addSchoolController = TextEditingController(); + final fromController = TextEditingController(); + final untilController = TextEditingController(); + final yearGraduated = TextEditingController(); + ////focus node + final programFocusNode = FocusNode(); + final schoolFocusNode = FocusNode(); + final honorFocusNode = FocusNode(); + ////booleans + bool graduated = true; + int? unitsEarned; + //// +@override + void dispose() { + addProgramController.dispose(); + addSchoolController.dispose(); + fromController.dispose(); + untilController.dispose(); + + programFocusNode.dispose(); + schoolFocusNode.dispose(); + honorFocusNode.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is AddEducationState) { + valueItemHonorList = state.honors.map((Honor honor) { + return ValueItem(label: honor.name!, value: honor.name); + }).toList(); + return Container( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: FormBuilder( + key: formKey, + child: SizedBox( + child: ListView(children: [ + //// LEVEL + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: + normalTextFieldStyle("level*", "level"), + name: "education_level", + onChanged: (EducationLevel? level) { + setState(() { + selectedLevel = level; + }); + }, + items: educationLevel + .map>( + (EducationLevel level) { + return level.type == "label" + ? DropdownMenuItem( + enabled: false, + value: level, + child: Text(level.value.toUpperCase(), + style: const TextStyle( + color: Colors.black38))) + : DropdownMenuItem( + value: level, + enabled: true, + child: Text( + " ${level.value.toUpperCase()}")); + }).toList()), + const SizedBox( + height: 12, + ), + ////school + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.schools + .map((School school) => + SearchFieldListItem(school.name!, + item: school, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text(school.name!,overflow: TextOverflow.visible,)), + ))) + .toList(), + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: schoolFocusNode, + searchInputDecoration: + normalTextFieldStyle("School *", "").copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + schoolFocusNode.unfocus(); + }, + )), + onSuggestionTap: (school) { + setState(() { + selectedSchool = school.item; + schoolFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add School", + controller: addSchoolController, + onpressed: () { + setState(() { + School newSchool = School( + id: null, + name: addSchoolController.text + .toUpperCase()); + state.schools.insert(0, newSchool); + addSchoolController.text = ""; + + Navigator.pop(context); + }); + }), + ); + }), + const SizedBox( + height: 12, + ), + ////Programs + Container( + child: selectedLevel != null && + selectedLevel!.group != 1 + ? SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: state.programs + .map((Course program) => + SearchFieldListItem( + program.program!, + item: program, + child: Padding( + padding: const EdgeInsets + .symmetric( + horizontal: 10), + child: ListTile( + title: Text( + program.program!,overflow: TextOverflow.visible,)), + ))) + .toList(), + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: programFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Course/Programs *", "") + .copyWith( + suffixIcon: GestureDetector( + onTap: () => programFocusNode.unfocus(), + child: const Icon( + Icons.arrow_drop_down), + )), + onSuggestionTap: (position) { + setState(() { + selectedProgram = position.item; + programFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add Program", + controller: addProgramController, + onpressed: () { + setState(() { + Course newProgram = Course( + id: null, + program: addProgramController + .text + .toUpperCase()); + state.programs + .insert(0, newProgram); + addProgramController.text = ""; + + Navigator.pop(context); + }); + }), + ) + : Container()) + ], + ); + }), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + //// GRADUATED SWITCH + FormBuilderSwitch( + initialValue: graduated, + activeColor: second, + onChanged: (value) { + setState(() { + graduated = value!; + if (graduated) { + unitsEarned = null; + } else { + yearGraduated.text = ""; + } + }); + }, + decoration: normalTextFieldStyle( + "Graduated?", 'Graduated?'), + name: 'graudated', + title: Text(graduated ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + ////FROM + SizedBox( + width: screenWidth, + child: Row( + children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + decoration: + normalTextFieldStyle("from *", "from"), + name: "", + controller: fromController, + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - 100, + 1), + lastDate: DateTime( + DateTime.now().year + 100, + 1), + initialDate: DateTime.now(), + selectedDate: DateTime.now(), + onChanged: (DateTime dateTime) { + fromController.text = + dateTime.year.toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + ), + ), + const SizedBox( + width: 8, + ), + ////UNTIL + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + decoration: normalTextFieldStyle( + "until *", "until"), + name: "", + controller: untilController, + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - 100, + 1), + lastDate: DateTime( + DateTime.now().year + 100, + 1), + initialDate: DateTime.now(), + selectedDate: DateTime.now(), + onChanged: (DateTime dateTime) { + untilController.text = + dateTime.year.toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + ), + ), + const SizedBox( + width: 8, + ), + ], + ), + ), + const SizedBox( + height: 12, + ), + SizedBox( + child: graduated + ////GRADUATED YEAR + ? FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - 100, + 1), + lastDate: DateTime( + DateTime.now().year + 100, + 1), + initialDate: DateTime.now(), + selectedDate: DateTime.now(), + onChanged: (DateTime dateTime) { + yearGraduated.text = + dateTime.year.toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + name: "year_graduated", + controller: yearGraduated, + decoration: normalTextFieldStyle( + "Year Graduated *", "Year Graduated *"), + ) + //// HIGHEST UNITS EARNED + : FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + name: "units_earned", + decoration: normalTextFieldStyle( + "Highest Level/Units Earned *", + "Highest Level/Units Earned *")), + ), + ], + ); + }), + + const SizedBox( + height: 12, + ), + //// HONORS + MultiSelectDropDown( + onOptionSelected: (List selectedOptions) { + selectedValueItem = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Honors", + padding: const EdgeInsets.all(8), + options: valueItemHonorList, + selectionType: SelectionType.multi, + chipConfig: const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: const Icon(Icons.check_circle), + ), + const SizedBox( + height: 25, + ), + ////sumit button + + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + //// program + if (selectedLevel!.value == "Elementary" || + selectedLevel!.value == + "Secondary (non-K12)" || + selectedLevel!.value == "Junior High" || + selectedLevel!.value == "Senior High") { + selectedProgram = null; + } + if (!graduated) { + unitsEarned = int.parse(formKey + .currentState!.value['units_earned']); + yearGraduated.text = ''; + } else {} + ////education + Education newEducation = Education( + id: null, + level: selectedLevel!.value, + course: selectedProgram, + school: selectedSchool); + ////honors + if (selectedValueItem != null) { + for (var honor in selectedValueItem!) { + Honor newHonor = state.honors.firstWhere( + (element) => element.name == honor.value); + selectedHonors.add(newHonor); + } + } + + EducationalBackground educationalBackground = + EducationalBackground( + id: null, + honors: null, + education: newEducation, + periodTo: untilController.text, + periodFrom: fromController.text, + yearGraduated: + graduated ? yearGraduated.text : null, + unitsEarned: !graduated ? unitsEarned : null, + attachments: null, + ); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(AddEducation( + educationalBackground: educationalBackground, + profileId: widget.profileId, + token: widget.token, + honors: selectedHonors)); + } + }, + child: const Text(submit)), + + ), + + ]), + ), + ), + ); + } + return Container(); + }, + ); + } +} + +class EducationLevel { + final String value; + final String type; + final int group; + const EducationLevel( + {required this.type, required this.value, required this.group}); +} diff --git a/lib/screens/profile/components/education/edit_modal.dart b/lib/screens/profile/components/education/edit_modal.dart new file mode 100644 index 0000000..e5676be --- /dev/null +++ b/lib/screens/profile/components/education/edit_modal.dart @@ -0,0 +1,588 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/text_container.dart'; +import '../../shared/add_for_empty_search.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +class EditEducationScreen extends StatefulWidget { + final int profileId; + final String token; + const EditEducationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _EditEducationScreenState(); +} + +class _EditEducationScreenState extends State { + final List educationLevel = [ + const EducationLevel(type: "label", value: "Basic Education", group: 1), + const EducationLevel(type: "level", value: "Elementary", group: 1), + const EducationLevel(type: "level", value: "Secondary (non-K12)", group: 1), + const EducationLevel(type: "level", value: "Junior High", group: 1), + const EducationLevel(type: "level", value: "Senior High", group: 1), + const EducationLevel(type: "label", value: "Higher Education", group: 2), + const EducationLevel(type: "level", value: "Collegiate", group: 2), + const EducationLevel(type: "level", value: "Vocational", group: 2), + const EducationLevel(type: "label", value: "Post Graduate", group: 2), + const EducationLevel(type: "level", value: "Masteral", group: 2), + const EducationLevel(type: "level", value: "Doctorate", group: 2), + ]; + List valueItemHonorList = []; + List selectedValueItem = []; +////selected + EducationLevel? selectedLevel; + School? selectedSchool; + Course? selectedProgram; + List selectedHonors = []; + final formKey = GlobalKey(); + ////congrollers + final addProgramController = TextEditingController(); + final addSchoolController = TextEditingController(); + final fromController = TextEditingController(); + final untilController = TextEditingController(); + final yearGraduated = TextEditingController(); + final currentSchoolController = TextEditingController(); + final currentProgramController = TextEditingController(); + final unitsController = TextEditingController(); ////focus node + final programFocusNode = FocusNode(); + final schoolFocusNode = FocusNode(); + final honorFocusNode = FocusNode(); + ////booleans + bool graduated = true; + + @override + void dispose() { + addProgramController.dispose(); + addSchoolController.dispose(); + fromController.dispose(); + untilController.dispose(); + currentSchoolController.dispose(); + currentProgramController.dispose(); + unitsController.dispose(); + programFocusNode.dispose(); + schoolFocusNode .dispose(); + honorFocusNode .dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is EditEducationState) { + ////selected level + selectedLevel = educationLevel.firstWhere((element) => + element.value.toUpperCase() == + state.educationalBackground.education!.level); + + currentSchoolController.text = + state.educationalBackground.education!.school!.name!; + if (selectedLevel != null && selectedLevel!.group != 1) { + currentProgramController.text = + state.educationalBackground.education!.course!.program!; + } +////year grduated and units earned + if (state.educationalBackground.yearGraduated != null) { + graduated = true; + yearGraduated.text = state.educationalBackground.yearGraduated!; + } else { + unitsController.text = + state.educationalBackground.unitsEarned.toString(); + graduated = false; + } + fromController.text = state.educationalBackground.periodFrom!; + untilController.text = state.educationalBackground.periodTo!; + + ////get all honors + valueItemHonorList = state.honors.map((Honor honor) { + return ValueItem(label: honor.name!, value: honor.name); + }).toList(); + return Container( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: FormBuilder( + key: formKey, + child: SizedBox( + height: blockSizeVertical * 85, + child: ListView(children: [ + + //// LEVEL + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderDropdown( + initialValue: selectedLevel, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: + normalTextFieldStyle("level*", "level"), + name: "education_level", + onChanged: (EducationLevel? level) { + setState(() { + selectedLevel = level; + }); + }, + items: educationLevel + .map>( + (EducationLevel level) { + return level.type == "label" + ? DropdownMenuItem( + enabled: false, + value: level, + child: Text(level.value.toUpperCase(), + style: const TextStyle( + color: Colors.black38))) + : DropdownMenuItem( + value: level, + enabled: true, + child: Text( + " ${level.value.toUpperCase()}")); + }).toList()), + const SizedBox( + height: 12, + ), + ////school + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + + suggestionAction: SuggestionAction.next, + onSubmit: (p0) { + schoolFocusNode.unfocus(); + }, + controller: currentSchoolController, + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.schools + .map((School school) => + SearchFieldListItem(school.name!, + item: school, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text(school.name!,overflow: TextOverflow.visible,)), + ))) + .toList(), + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: schoolFocusNode, + searchInputDecoration: + normalTextFieldStyle("School *", "").copyWith( + suffixIcon: GestureDetector( + child: const Icon(Icons.arrow_drop_down), + onTap: () { + schoolFocusNode.unfocus(); + }, + )), + onSuggestionTap: (school) { + setState(() { + selectedSchool = school.item; + schoolFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add School", + controller: addSchoolController, + onpressed: () { + setState(() { + School newSchool = School( + id: null, + name: addSchoolController.text + .toUpperCase()); + state.schools.insert(0, newSchool); + addSchoolController.text = ""; + + Navigator.pop(context); + }); + }), + ); + }), + const SizedBox( + height: 12, + ), + + ////Programs + + Container( + child: selectedLevel != null && + selectedLevel!.group != 1 + ? SearchField( + inputFormatters: [UpperCaseTextFormatter()], + suggestionAction: + SuggestionAction.unfocus, + controller: currentProgramController, + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.programs + .map((Course program) => + SearchFieldListItem( + program.program!, + item: program, + child: Padding( + padding: const EdgeInsets + .symmetric( + horizontal: 10), + child: ListTile( + title: Text( + program.program!,overflow: TextOverflow.visible,)), + ))) + .toList(), + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: programFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Course/Programs *", "") + .copyWith( + suffixIcon: IconButton( + icon:const Icon( + Icons.arrow_drop_down), onPressed: () { programFocusNode.unfocus(); },),), + onSuggestionTap: (position) { + setState(() { + selectedProgram = position.item; + programFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add Program", + controller: addProgramController, + onpressed: () { + setState(() { + Course newProgram = Course( + id: null, + program: addProgramController + .text + .toUpperCase()); + state.programs + .insert(0, newProgram); + addProgramController.text = ""; + + Navigator.pop(context); + }); + }), + ) + : Container()), + SizedBox(height: selectedLevel != null && + selectedLevel!.group != 1?12:0,), + ], + ); + }), + + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + //// GRADUATED SWITCH + FormBuilderSwitch( + initialValue: graduated, + activeColor: second, + onChanged: (value) { + setState(() { + graduated = value!; + if (graduated) { + unitsController.text = ""; + } else { + yearGraduated.text = ""; + } + }); + }, + decoration: normalTextFieldStyle( + "Graduated?", 'Graduated?'), + name: 'graudated', + title: Text(graduated ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + ////FROM + SizedBox( + width: screenWidth, + child: Row( + children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + decoration: + normalTextFieldStyle("from *", "from"), + name: "", + controller: fromController, + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - 100, + 1), + lastDate: DateTime( + DateTime.now().year + 100, + 1), + initialDate: DateTime.now(), + selectedDate: DateTime.now(), + onChanged: (DateTime dateTime) { + fromController.text = + dateTime.year.toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + ), + ), + const SizedBox( + width: 8, + ), + ////UNTIL + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This fied is required"), + decoration: normalTextFieldStyle( + "until *", "until"), + name: "", + controller: untilController, + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - 100, + 1), + lastDate: DateTime( + DateTime.now().year + 100, + 1), + initialDate: DateTime.now(), + selectedDate: DateTime.now(), + onChanged: (DateTime dateTime) { + untilController.text = + dateTime.year.toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + ), + ), + + + ], + ), + + ), const SizedBox(height: 20,), + SizedBox( + + child: graduated + ////GRADUATED YEAR + ? FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This fied is required"), + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SizedBox( + width: 300, + height: 300, + child: YearPicker( + firstDate: DateTime( + DateTime.now().year - + 100, + 1), + lastDate: DateTime( + DateTime.now().year + + 100, + 1), + initialDate: + DateTime.now(), + selectedDate: + DateTime.now(), + onChanged: + (DateTime dateTime) { + yearGraduated.text = + dateTime.year + .toString(); + Navigator.pop(context); + }, + ), + ), + ); + }, + ); + }, + name: "year_graduated", + controller: yearGraduated, + decoration: normalTextFieldStyle( + "Year Graduated *", + "Year Graduated *"), + ) + //// HIGHEST UNITS EARNED + : FormBuilderTextField( + initialValue: state.educationalBackground.unitsEarned?.toString(), + validator: + FormBuilderValidators.required( + errorText: + "This fied is required"), + + name: "units_earned", + decoration: normalTextFieldStyle( + "Highest Level/Units Earned *", + "Highest Level/Units Earned *")), + ) + + ], + ); + }), + const SizedBox( + height: 12, + ), + //// HONORS + StatefulBuilder(builder: (context, setState) { + return MultiSelectDropDown( + onOptionSelected: (List selectedOptions) { + selectedValueItem = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Honors", + padding: const EdgeInsets.all(8), + options: valueItemHonorList, + selectionType: SelectionType.multi, + chipConfig: const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: const Icon(Icons.check_circle), + selectedOptions: + (state.educationalBackground.honors!.isNotEmpty && + state.educationalBackground.honors != null) + ? selectedValueItem = state + .educationalBackground.honors! + .map((Honor honor) => ValueItem( + label: honor.name!, value: honor.name)) + .toList() + : [], + ); + }), + const SizedBox(height: 14,), + ////sumit button + + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + //// program + if (selectedLevel!.value == "Elementary" || + selectedLevel!.value == + "Secondary (non-K12)" || + selectedLevel!.value == "Junior High" || + selectedLevel!.value == "Senior High") { + selectedProgram = null; + } else { + selectedProgram ??= state + .educationalBackground.education!.course; + } + selectedSchool ??= + state.educationalBackground.education!.school; + ////education + Education newEducation = Education( + id: null, + level: selectedLevel!.value, + course: selectedProgram, + school: selectedSchool); + ////honors + if (selectedValueItem.isNotEmpty) { + for (var honor in selectedValueItem) { + Honor newHonor = state.honors.firstWhere( + (element) => element.name == honor.value); + selectedHonors.add(newHonor); + } + } + EducationalBackground educationalBackground = + EducationalBackground( + id: state.educationalBackground.id, + honors: null, + education: newEducation, + periodTo: untilController.text, + periodFrom: fromController.text, + yearGraduated: + graduated ? yearGraduated.text : null, + unitsEarned: !graduated + ? int.tryParse(formKey.currentState!.value['units_earned']) + : null, + attachments: null, + ); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(UpdateEducation( + educationalBackground: educationalBackground, + profileId: widget.profileId, + token: widget.token, + honors: selectedHonors)); + } + }, + child: const Text(submit)), + ), + ]), + ), + ), + ); + } + return Container(); + }, + ); + } +} + +class EducationLevel { + final String value; + final String type; + final int group; + const EducationLevel( + {required this.type, required this.value, required this.group}); +} diff --git a/lib/screens/profile/components/education/education_view_attachment.dart b/lib/screens/profile/components/education/education_view_attachment.dart new file mode 100644 index 0000000..f84ca88 --- /dev/null +++ b/lib/screens/profile/components/education/education_view_attachment.dart @@ -0,0 +1,106 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +import '../../../../utils/url_launcher_file_downloader.dart'; + +class EudcationViewAttachment extends StatefulWidget { + const EudcationViewAttachment({super.key}); + + @override + State createState() => + _EudcationViewAttachmentState(); +} + +class _EudcationViewAttachmentState extends State { + @override + Widget build(BuildContext context) { + String? fileUrl; + String? filename; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () async { + await launchInBrowser(fileUrl!); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton( + onPressed: () { + context.read().add( + ShareAttachment(fileName: filename!, source: fileUrl!)); + }, + icon: const Icon(Icons.share)), + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + builder: (context, state) { + if (state is EducationAttachmentViewState) { + fileUrl = state.fileUrl; + filename = state.fileName; + + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' + ? true + : false; + return SizedBox( + child: isPDF + ? SfPdfViewer.network( + state.fileUrl, + onDocumentLoadFailed: (details) { + Center( + child: Text(details.description), + ); + }, + ) + : Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator( + color: primary, + )); + }, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + return Container(); + }, + listener: (context, state) { + if (state is EducationalBackgroundLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EducationAttachmentViewState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + ), + )); + } +} diff --git a/lib/screens/profile/components/education_screen.dart b/lib/screens/profile/components/education_screen.dart new file mode 100644 index 0000000..aec934b --- /dev/null +++ b/lib/screens/profile/components/education_screen.dart @@ -0,0 +1,849 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/screens/profile/components/education/add_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/education/education_bloc.dart'; +import '../../../model/profile/attachment.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/Leadings/close_leading.dart'; +import '../shared/multiple_attachment.dart'; +import '../shared/single_attachment.dart'; +import 'education/edit_modal.dart'; +import 'education/education_view_attachment.dart'; + +class EducationScreen extends StatelessWidget { + const EducationScreen({super.key}); + @override + Widget build(BuildContext context) { + final parent = context; + + List? results = []; + AttachmentCategory? selectedAttachmentCategory; + List attachmentCategories = []; + int profileId; + String? token; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is AddEducationState + ? const FittedBox(child: Text("Add Educational Background")) + : context.watch().state is EditEducationState + ? const FittedBox(child: Text("Edit Educational Background")) + : const Text("Education Background"), + centerTitle: true, + backgroundColor: primary, + actions: context.watch().state + is EducationalBackgroundLoadedState + ? [ + AddLeading(onPressed: () { + context.read().add(ShowAddEducationForm()); + }) + ] + : (context.watch().state is AddEducationState || + context.watch().state + is EditEducationState) + ? [ + CloseLeading(onPressed: () { + context.read().add(LoadEducations()); + }) + ] + : [], + ), + //userbloc + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + //profilebloc + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + //education bloc + return BlocConsumer( + listener: (context, state) { + if (state is EducationalBackgroundLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EducationalBackgroundLoadedState || + state is EducationalBackgroundErrorState || + state is AddEducationState || + state is EditEducationState || + state is EducationDeletedState || + state is EditedEducationState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////ADDED STATE + if (state is EducationAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } + } + ////ATTACHMENT ADDED STATE + + if (state is EducationAttachmentAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } + } + ////EDITED STATE + if (state is EditedEducationState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } else { + errorAlert(context, "Updated Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } + } + ////DELETED STATE + if (state is EducationDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Educational Background has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Education Background", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } + } + ////ATTACHMENT DELETED STATE + if (state is EducationAttachmentDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Attachment has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Attachment", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadEducations()); + }); + } + } + }, + builder: (context, state) { + if (state is EducationalBackgroundLoadedState) { + for (var cat in state.attachmentCategory) { + if (cat.subclass!.id == 1) { + attachmentCategories.add(cat); + } + } + if (state.educationalBackground.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.educationalBackground.length, + itemBuilder: + (BuildContext context, int index) { + String level = state + .educationalBackground[index] + .education! + .level!; + String periodFrom = state + .educationalBackground[index] + .periodFrom!; + String periodTo = state + .educationalBackground[index].periodTo!; + String? program = state + .educationalBackground[index] + .education! + .course == + null + ? null + : state.educationalBackground[index] + .education!.course!.program!; + List? honors = state + .educationalBackground[index].honors! + .toList(); + String school = state + .educationalBackground[index] + .education! + .school! + .name!; + return Column( + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Row( + children: [ + Expanded( + child: Text( + level, + style: Theme.of( + context) + .textTheme + .titleSmall!)), + Text( + "$periodFrom - $periodTo", + style: Theme.of( + context) + .textTheme + .bodyMedium, + ), + ], + ), + const SizedBox( + height: 5, + ), + Text( + school, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + color: + primary, + fontWeight: + FontWeight + .w500), + ), + Container( + padding: + const EdgeInsets + .only( + top: 8), + child: honors + .isNotEmpty + ? Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + const SizedBox( + height: + 8, + ), + const Text( + " honors: ", + style: + TextStyle(fontWeight: FontWeight.w600), + ), + Column( + children: honors + .map((Honor honor) => Padding( + padding: const EdgeInsets.all(3.0), + child: Text( + "-${honor.name!.trim()}", + style: Theme.of(context).textTheme.labelSmall, + ), + )) + .toList(), + ), + ], + ) + : const SizedBox()), + program == null + ? const SizedBox() + : Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + const SizedBox( + height: 5, + ), + Text( + program), + ], + ), + ]), + ), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete -= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, + () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + context + .read< + EducationBloc>() + .add(DeleteEducation( + educationalBackground: + state.educationalBackground[ + index], + profileId: + profileId, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit -= = = = = = = = =>> + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + context + .read< + EducationBloc>() + .add(ShowEditEducationForm( + profileId: + profileId, + token: token!, + educationalBackground: + state.educationalBackground[ + index])); + } + if (value == 3) { + results.clear(); + showDialog( + context: context, + builder: + (BuildContext + context) { + return AlertDialog( + contentPadding: + const EdgeInsets + .all(0), + backgroundColor: + Colors.grey + .shade100, + icon: + const Icon( + Icons + .file_copy, + size: 32, + color: + primary, + ), + title: const Text( + "File Attachment:"), + content: StatefulBuilder( + builder: + (context, + setState) { + return Padding( + padding: const EdgeInsets + .all( + 16.0), + child: Column( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const Divider(), + Text( + program ?? + level, + style: + Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary), + ), + const SizedBox( + height: + 5, + ), + Text( + school, + style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: + 3, + ), + Text( + "$periodFrom - $periodTo", + style: Theme.of(context).textTheme.titleSmall), + const Divider(), + FormBuilderDropdown( + autovalidateMode: AutovalidateMode.always, + decoration: normalTextFieldStyle("attachment category", "attachment category"), + name: 'attachments_categorues', + validator: FormBuilderValidators.required(errorText: "This field is required"), + onChanged: (value) { + selectedAttachmentCategory = value; + }, + items: attachmentCategories.map((e) { + return DropdownMenuItem(value: e, child: Text(e.description!)); + }).toList()), + const SizedBox( + height: + 8, + ), + Text( + "You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.", + style: + Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black), + ), + const SizedBox( + height: + 5, + ), + Text( + "Acceptable Files: PDF, JPEG, PNG", + style: + Theme.of(context).textTheme.bodySmall, + ), + Text( + "Max File Size (per attachment): 1MB", + style: + Theme.of(context).textTheme.bodySmall, + ), + const Divider(), + ElevatedButton( + style: ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(Colors.white), + ), + onPressed: () async { + FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [ + 'jpg', + 'png', + 'jpeg', + 'pdf' + ]); + setState(() { + if (newResult != null) { + newResult.files.forEach((element) { + results.add(element); + }); + } + }); + }, + child: const Center( + child: Text( + "Select Files", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.black), + ))), + const Divider(), + SingleChildScrollView( + child: + SizedBox( + height: 100, + width: double.maxFinite, + child: results.isEmpty + ? const SizedBox() + : Expanded( + child: ListView.builder( + itemCount: results.length, + itemBuilder: (BuildContext context, index) { + final kb = results[index].size / 1024; + final mb = kb / 1024; + final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB'; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: double.infinity, + child: Row( + children: [ + Flexible( + child: SizedBox( + child: results[index].extension!.toLowerCase() == 'pdf' + ? SvgPicture.asset( + 'assets/svgs/pdf.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'png' + ? SvgPicture.asset( + 'assets/svgs/png.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg' + ? SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : const SizedBox())), + const SizedBox( + width: 12, + ), + Flexible( + flex: 6, + child: Text( + results[index].name, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2), + ), + ), + const SizedBox( + width: 12, + ), + Flexible( + flex: 2, + child: Text( + size, + style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey), + )), + Flexible( + flex: 1, + child: IconButton( + icon: const Icon( + Icons.close, + color: Colors.grey, + ), + onPressed: () { + setState(() { + results.removeAt(index); + }); + }, + )) + ], + )), + const Divider() + ], + ); + }), + ), + ), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: + double.maxFinite, + height: + 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + List paths = []; + + if (selectedAttachmentCategory != null && results.isNotEmpty) { + for (var res in results) { + paths.add(res.path!); + } + setState(() { + results.clear(); + }); + Navigator.pop(context); + parent.read().add(AddEducationAttachment(attachmentModule: state.educationalBackground[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString())); + } + }, + child: const Text("Submit")), + ) + ]), + ); + }), + ); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + popMenuItem( + text: "Attach", + value: 3, + icon: Icons + .attach_file), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + + ////Show Attachments + SizedBox( + child: state + .educationalBackground[ + index] + .attachments == + null || + state + .educationalBackground[ + index] + .attachments! + .isEmpty + ? const SizedBox() + : state + .educationalBackground[ + index] + .attachments != + null && + state + .educationalBackground[ + index] + .attachments! + .length == + 1 + ? + ////Single Attachment view + Column( + children: [ + const Divider(), + SingleAttachment( + view: () { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EducationBloc()..add(EducationViewAttachment(source: state.educationalBackground[index].attachments!.first.source!,fileName: state.educationalBackground[index].attachments!.first.filename!)), + child: const EudcationViewAttachment(), + )))); + }, + onpressed: + () { + confirmAlert( + context, + () { + parent.read().add(DeleteEducationAttachment( + attachment: state + .educationalBackground[ + index] + .attachments! + .first, + moduleId: state + .educationalBackground[ + index] + .id!, + profileId: + profileId, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + }, + attachment: state + .educationalBackground[ + index] + .attachments! + .first, + ), + ], + ) + ////Multiple Attachments View + : MultipleAttachments( + viewAttachment: + (source,filname) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => + BlocProvider.value( + value: EducationBloc()..add(EducationViewAttachment(source: source,fileName: filname)), + child: const EudcationViewAttachment(), + )))); + }, + profileId: + profileId, + token: token!, + eligibilityName: state + .educationalBackground[ + index] + .education! + .school! + .name!, + attachments: state + .educationalBackground[ + index] + .attachments!, + educationBloc: + BlocProvider.of< + EducationBloc>( + parent), + eligibilityBloc: + null, + workHistoryBloc: + null, + learningDevelopmentBloc: + null, + blocId: 1, + moduleId: state + .educationalBackground[ + index] + .id!, + )) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any Educational Background added. Please click + to add."); + } + } + if (state is EducationalBackgroundErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetEducationalBackground( + profileId: profileId, token: token!)); + }); + } + if (state is AddEducationState) { + return AddEducationScreen( + token: token!, + profileId: profileId, + ); + } + if (state is EditEducationState) { + return EditEducationScreen( + token: token!, + profileId: profileId, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/eligibility/add_modal.dart b/lib/screens/profile/components/eligibility/add_modal.dart new file mode 100644 index 0000000..4c1f0a8 --- /dev/null +++ b/lib/screens/profile/components/eligibility/add_modal.dart @@ -0,0 +1,500 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/model/profile/eligibility.dart'; +import '../../../../bloc/profile/eligibility/eligibility_bloc.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/utils/eligibility.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/text_container.dart'; + +class AddEligibilityScreen extends StatefulWidget { + const AddEligibilityScreen( + {super.key, required this.profileId, required this.token}); + final int profileId; + final String token; + + @override + State createState() => _AddEligibilityScreenState(); +} + +class _AddEligibilityScreenState extends State { + final formKey = GlobalKey(); + bool? overseas = false; + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + Eligibility? selectedEligibility; + List? provinces; + List? citymuns; + bool provinceCall = false; + bool cityCall = false; + final examDateController = TextEditingController(); + final validityDateController = TextEditingController(); + String? token; + String? profileId; + String? rating; + String? license; + DateTime? examDate; + DateTime? expireDate; + @override + void dispose() { + examDateController.dispose(); + validityDateController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, + builder: (context, state) { + ////ADD ELIGIBILITY STATE + if (state is AddEligibilityState) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 28), + child: FormBuilder( + key: formKey, + child: ListView(children: [ + ////ELIGIBILITIES DROPDOWN + FormBuilderDropdown( + onChanged: (Eligibility? eligibility) { + selectedEligibility = eligibility; + }, + autovalidateMode: + AutovalidateMode.onUserInteraction, + validator: (value) => + value == null ? 'required' : null, + items: state.eligibilities + .map>( + (Eligibility eligibility) { + return DropdownMenuItem( + value: eligibility, + child: Text(eligibility.title)); + }).toList(), + name: "eligibility", + decoration: normalTextFieldStyle( + "Eligibility", "Eligibility")), + const SizedBox( + height: 8, + ), + + SizedBox( + width: screenWidth, + child: Row( + children: [ + ////LICENSE NUMBER + Flexible( + flex: 1, + child: FormBuilderTextField( + onChanged: (value) { + license = value; + }, + name: 'license_number', + decoration: normalTextFieldStyle( + "license number", "license number"), + ), + ), + const SizedBox( + width: 8, + ), + ////RATING + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.numeric( + errorText: "Enter a number"), + keyboardType: + const TextInputType.numberWithOptions(), + onChanged: (value) { + rating = value; + }, + name: 'rating', + decoration: normalTextFieldStyle( + 'rating %', 'rating'), + ), + ), + ], + ), + ), + const SizedBox( + height: 8, + ), + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return Row( + children: [ + ////EXAM DATE + Flexible( + flex: 1, + child: DateTimePicker( + use24HourFormat: false, + icon: const Icon(Icons.date_range), + controller: examDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: + "Date of Examination/Conferment", + decoration: + normalTextFieldStyle("Exam date", "") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialDate: expireDate == null + ? DateTime.now() + : expireDate!.subtract( + const Duration(days: 1)), + selectableDayPredicate: (date) { + if (expireDate != null && + expireDate! + .microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + examDate = DateTime.parse(value); + }); + }, + )), + const SizedBox( + width: 8, + ), + ////VALIDITY DATE + Flexible( + flex: 1, + child: DateTimePicker( + controller: validityDateController, + firstDate: DateTime(1970), + lastDate: DateTime(2100), + decoration: normalTextFieldStyle( + "Validity date", "Validity date") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + selectableDayPredicate: (date) { + if (examDate != null && + examDate!.microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + expireDate = DateTime.parse(value); + }); + }, + initialDate: examDate == null + ? DateTime.now() + : examDate! + .add(const Duration(days: 1)), + ), + ), + ], + ); + }), + ), + const SizedBox( + height: 8, + ), + Text( + "Placement of Examination/Conferment", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith(fontSize: blockSizeVertical * 2), + ), + const SizedBox( + height: 8, + ), + ////OVERSEAS ADDRESS SWITCH + Column( + children: [ + FormBuilderSwitch( + validator: FormBuilderValidators.required( + errorText: 'This field is required'), + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Overseas Address?"), + ), + const SizedBox( + height: 8, + ), + ////COUNTRY DROPDOWN + SizedBox( + child: overseas == true + ? FormBuilderDropdown( + initialValue: null, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ) + : Column( + children: [ + ////REGION DROPDOWN + FormBuilderDropdown( + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + //// region onchange + onChanged: (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + getProvinces(); + } + }, + initialValue: selectedRegion, + decoration: normalTextFieldStyle( + "Region*", "Region"), + name: 'region', + items: state.regions + .map>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 8, + ), + ////PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: + (Province? province) { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + getCities(); + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + + //// CityMunicipalities dropdown + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + onChanged: + (CityMunicipality? city) { + selectedMunicipality = city; + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + ], + )), + ], + ), + const SizedBox(height: 24,), + SizedBox( + width: screenWidth, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + ////rating + double? rate = rating == null + ? null + : double.tryParse(rating!); + ////lisence + String? licenseNumber = license; + CityMunicipality? cityMunicipality = + selectedMunicipality; + DateTime? examDate = + examDateController.text.isEmpty + ? null + : DateTime.parse(examDateController.text); + DateTime? validityDate = validityDateController + .text.isEmpty + ? null + : DateTime.parse(validityDateController.text); + + ExamAddress examAddress = ExamAddress( + barangay: null, + id: null, + addressCategory: null, + examAddressClass: null, + country: selectedCountry ?? + Country( + id: 175, + name: 'Philippines', + code: 'PH'), + cityMunicipality: cityMunicipality); + EligibityCert eligibityCert = EligibityCert( + id: null, + rating: rate, + examDate: examDate, + attachments: null, + eligibility: selectedEligibility, + examAddress: examAddress, + validityDate: validityDate, + licenseNumber: licenseNumber, + overseas: overseas); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + AddEligibility( + eligibityCert: eligibityCert, + profileId: widget.profileId.toString(), + token: widget.token)); + } + }, + child: const Text(submit)), + ), + ]), + ), + ); + } + + return Container(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } +} diff --git a/lib/screens/profile/components/eligibility/edit_modal.dart b/lib/screens/profile/components/eligibility/edit_modal.dart new file mode 100644 index 0000000..9e0c0f4 --- /dev/null +++ b/lib/screens/profile/components/eligibility/edit_modal.dart @@ -0,0 +1,546 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/model/location/city.dart'; +import 'package:unit2/model/profile/eligibility.dart'; +import 'package:unit2/model/utils/eligibility.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/utils/location_utilities.dart'; +import '../../../../bloc/profile/eligibility/eligibility_bloc.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/text_container.dart'; + +class EditEligibilityScreen extends StatefulWidget { + final EligibityCert eligibityCert; + final int profileId; + final String token; + const EditEligibilityScreen( + {super.key, + required this.eligibityCert, + required this.profileId, + required this.token}); + + @override + State createState() => _EditEligibilityScreenState(); +} + +class _EditEligibilityScreenState extends State { + final formKey = GlobalKey(); + bool? overseas; + List? provinces; + List? citymuns; + List? regions; + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + Eligibility? selectedEligibility; + bool provinceCall = false; + bool cityCall = false; + String? token; + String? profileId; + String? rating; + String? license; + final examDateController = TextEditingController(); + final validityDateController = TextEditingController(); + + @override + void dispose() { + examDateController.dispose(); + validityDateController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, + builder: (context, state) { + //EDIT ELIGIBILITY STATE + if (state is EditEligibilityState) { + examDateController.text = state.eligibityCert.examDate == null + ? '' + : state.eligibityCert.examDate.toString(); + validityDateController.text = state.eligibityCert.validityDate == null + ? '' + : state.eligibityCert.validityDate.toString(); + DateTime? examDate = DateTime.tryParse(examDateController.text); + DateTime? expireDate = DateTime.tryParse(validityDateController.text); + provinces = state.provinces; + citymuns = state.cities; + regions = state.regions; + overseas = state.isOverseas; + selectedRegion = state.currentRegion; + selectedProvince = state.currentProvince; + selectedMunicipality = state.currentCity; + selectedEligibility = state.currentEligibility; + rating = state.eligibityCert.rating?.toString(); + license = state.eligibityCert.licenseNumber; + selectedCountry = state.selectedCountry; + return Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 28), + child: FormBuilder( + key: formKey, + child: ListView(children: [ + const SizedBox( + height: 24, + ), + ////ELIGIBILITIES DROPDOWN + DropdownButtonFormField( + validator: (value) => value == null ? 'required' : null, + isExpanded: true, + onChanged: (Eligibility? eligibility) { + selectedEligibility = eligibility; + }, + value: selectedEligibility, + items: state.eligibilities + .map>( + (Eligibility eligibility) { + return DropdownMenuItem( + value: eligibility, child: Text(eligibility.title)); + }).toList(), + decoration: normalTextFieldStyle("Eligibility", "")), + const SizedBox( + height: 12, + ), + + SizedBox( + width: screenWidth, + child: Row( + children: [ + ////LICENSE NUMBER + Flexible( + flex: 1, + child: FormBuilderTextField( + onChanged: (value) { + license = value; + }, + name: 'license_number', + initialValue: license, + decoration: normalTextFieldStyle( + "license number", "license number"), + ), + ), + const SizedBox( + width: 12, + ), + // //RATING + Flexible( + flex: 1, + child: FormBuilderTextField( + validator: FormBuilderValidators.numeric( + errorText: "Enter a number"), + keyboardType: + const TextInputType.numberWithOptions(), + onChanged: (value) { + rating = value; + }, + name: 'rating', + initialValue: + rating == null ? 'N/A' : rating.toString(), + decoration: + normalTextFieldStyle('rating', 'rating'), + ), + ), + ], + ), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: StatefulBuilder(builder: (context, setState) { + return Row( + children: [ + // //EXAM DATE + Flexible( + flex: 1, + child: DateTimePicker( + use24HourFormat: false, + controller: examDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + decoration: + normalTextFieldStyle("Exam date", "") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialDate: expireDate == null + ? DateTime.now() + : expireDate! + .subtract(const Duration(days: 1)), + selectableDayPredicate: (date) { + if (expireDate != null && + expireDate!.microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + examDate = DateTime.parse(value); + }); + }, + )), + + const SizedBox( + width: 12, + ), + ////VALIDITY DATE + Flexible( + flex: 1, + child: DateTimePicker( + use24HourFormat: false, + controller: validityDateController, + firstDate: DateTime(1970), + lastDate: DateTime(2100), + decoration: + normalTextFieldStyle("validity date", "") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + selectableDayPredicate: (date) { + if (examDate != null && + examDate!.microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + expireDate = DateTime.parse(value); + }); + }, + initialDate: examDate == null + ? DateTime.now() + : examDate!.add(const Duration(days: 1)), + ), + ), + ], + ); + }), + ), + const SizedBox( + height: 20, + ), + Text( + "Placement of Examination/Confinement", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith(fontSize: blockSizeVertical * 2), + ), + const SizedBox( + height: 12, + ), + //OVERSEAS ADDRESS SWITCH + StatefulBuilder(builder: (context, StateSetter setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Overseas Address?"), + ), + const SizedBox( + height: 12, + ), + //COUNTRY DROPDOWN + SizedBox( + child: overseas == true + ? FormBuilderDropdown( + validator: (value) => + value == null ? 'required' : null, + initialValue: selectedCountry!.id == 175 + ? null + : selectedCountry, + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ) + : Column( + children: [ + ////REGION DROPDOWN + DropdownButtonFormField( + validator: (value) => + value == null ? 'required' : null, + isExpanded: true, + onChanged: (Region? region) async { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: selectedRegion! + .code + .toString()); + } catch (e) { + context + .read() + .add(CallErrorState()); + } + selectedProvince = provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + } catch (e) { + NavigationService + .navigatorKey.currentContext + ?.read() + .add(CallErrorState()); + } + selectedMunicipality = citymuns![0]; + setState(() { + cityCall = false; + }); + }, + value: selectedRegion, + decoration: normalTextFieldStyle( + "Region*", "Region"), + items: regions == null + ? [] + : regions! + .map>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + ////PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: + (Province? province) async { + setState(() { + cityCall = true; + }); + selectedProvince = province; + try { + citymuns = await LocationUtils + .instance + .getCities( + code: + selectedProvince! + .code + .toString()); + } catch (e) { + context + .read() + .add(CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province + .description!), + )); + }).toList(), + decoration: normalTextFieldStyle( + "Province*", "Province")), + ), + ), + + //// City municipality + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: (value) => value == null + ? 'required' + : null, + isExpanded: true, + onChanged: + (CityMunicipality? city) { + selectedMunicipality = city; + }, + decoration: normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text( + c.description!)); + }).toList(), + ), + ), + ), + ], + )), + ], + ); + }), + const SizedBox( + height: 18, + ), + SizedBox( + width: screenWidth, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + ExamAddress examAddress; + ////rating + double? rate = + rating == null ? null : double.parse(rating!); + ////license + String? newLicense = license; + ////city municipality + CityMunicipality? cityMunicipality = + selectedMunicipality; + ////exam date + DateTime? examDate = examDateController.text.isEmpty + ? null + : DateTime.parse(examDateController.text); + // // validity date + DateTime? validityDate = + validityDateController.text.isEmpty + ? null + : DateTime.parse(validityDateController.text); + //// exam address + if (overseas!) { + examAddress = ExamAddress( + barangay: null, + id: state.eligibityCert.examAddress?.id, + addressCategory: state + .eligibityCert.examAddress?.addressCategory, + examAddressClass: state.eligibityCert + .examAddress?.examAddressClass, + country: selectedCountry, + cityMunicipality: null); + } else { + examAddress = ExamAddress( + barangay: + state.eligibityCert.examAddress?.barangay, + id: state.eligibityCert.examAddress?.id, + addressCategory: state + .eligibityCert.examAddress?.addressCategory, + examAddressClass: state.eligibityCert + .examAddress?.examAddressClass, + country: Country( + id: 175, name: 'Philippines', code: 'PH'), + cityMunicipality: cityMunicipality); + } + + EligibityCert eligibityCert = EligibityCert( + id: state.eligibityCert.id, + rating: rate, + examDate: examDate, + attachments: null, + eligibility: selectedEligibility, + examAddress: examAddress, + validityDate: validityDate, + licenseNumber: newLicense, + overseas: overseas); + if (formKey.currentState!.saveAndValidate()) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + UpdateEligibility( + eligibityCert: eligibityCert, + oldEligibility: + state.eligibityCert.eligibility!.id, + profileId: widget.profileId.toString(), + token: widget.token)); + } + }, + child: const Text(submit)), + ), + ]), + ), + ), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart b/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart new file mode 100644 index 0000000..2bf26a7 --- /dev/null +++ b/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart @@ -0,0 +1,113 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/url_launcher_file_downloader.dart'; +import 'package:unit2/widgets/error_state.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class EligibilityViewAttachment extends StatefulWidget { + const EligibilityViewAttachment({super.key}); + + @override + State createState() => + _EligibilityViewAttachmentState(); +} + +class _EligibilityViewAttachmentState extends State { + @override + Widget build(BuildContext context) { + String? filename; + String? fileUrl; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () async { + await launchInBrowser(fileUrl!); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton( + onPressed: () { + context.read().add( + ShareAttachment(fileName: filename!, source: fileUrl!)); + }, + icon: const Icon(Icons.share)), + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + builder: (context, state) { + if (state is EligibilityAttachmentViewState) { + fileUrl = state.fileUrl; + filename = state.fileName; + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' + ? true + : false; + return SizedBox( + child: isPDF + ? SfPdfViewer.network( + state.fileUrl, + onDocumentLoadFailed: (details) { + Center( + child: Text(details.description), + ); + }, + ) + : Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator( + color: primary, + )); + }, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + if (state is EligibilityErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + Navigator.pop(context); + }); + } + return Container(); + }, + listener: (context, state) { + if (state is EligibilityLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EligibilityAttachmentViewState || + state is EligibilityErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + ), + )); + } +} diff --git a/lib/screens/profile/components/eligibility_screen.dart b/lib/screens/profile/components/eligibility_screen.dart new file mode 100644 index 0000000..2e2a548 --- /dev/null +++ b/lib/screens/profile/components/eligibility_screen.dart @@ -0,0 +1,786 @@ +import 'dart:io'; +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/attachment.dart'; +import 'package:unit2/model/profile/eligibility.dart'; +import 'package:unit2/screens/profile/components/eligibility/add_modal.dart'; +import 'package:unit2/screens/profile/components/eligibility/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/eligibility/eligibility_bloc.dart'; +import '../../../utils/alerts.dart'; +import '../shared/multiple_attachment.dart'; +import '../shared/single_attachment.dart'; +import 'eligibility/eligibility_view_attachment.dart'; + +class EligibiltyScreen extends StatelessWidget { + const EligibiltyScreen({super.key}); + + @override + Widget build(BuildContext context) { + BuildContext parent = context; + String? token; + int? profileId; + List? results = []; + AttachmentCategory? selectedAttachmentCategory; + List attachmentCategories = []; + + return WillPopScope( + onWillPop: () async { + return true; + }, + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is AddEligibilityState + ? const Text("Add Eligiblity") + : context.watch().state is EditEligibilityState + ? const Text("Edit Eligibilty") + : const Text(elibilityScreenTitle), + centerTitle: true, + backgroundColor: primary, + actions: + (context.watch().state is EligibilityLoaded) + ? [ + AddLeading(onPressed: () { + context + .read() + .add(ShowAddEligibilityForm()); + }) + ] + : (context.watch().state + is AddEligibilityState || + context.watch().state + is EditEligibilityState) + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(const LoadEligibility()); + }) + ] + : [], + ), + body: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocConsumer( + listener: (context, state) { + if (state is EligibilityLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EligibilityLoaded || + state is AddEligibilityState || + state is EditEligibilityState || + state is EligibilityDeletedState || + state is EligibilityAddedState || + state is EligibilityEditedState || + state is EligibilityErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////DELETED STATE + if (state is EligibilityDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Eligibility has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting eligibility", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } + } + ////ATTACHMENT ADDED STATE + + if (state is EligibilityAttachmentAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } + } + ////ADDED STATE + if (state is EligibilityAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } + } + ////UPDATED STATE + if (state is EligibilityEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } + } + ////ATTACHMENT DELETED STATE + if (state is EligibilitytAttachmentDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Attachment has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Attachment", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadEligibility()); + }); + } + } + }, + builder: (context, state) { + return BlocBuilder( + builder: (context, state) { + if (state is EligibilityLoaded) { + for (var cat in state.attachmentCategory) { + if (cat.subclass!.id == 3) { + attachmentCategories.add(cat); + } + } + if (state.eligibilities.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.eligibilities.length, + itemBuilder: + (BuildContext context, int index) { + String title = state + .eligibilities[index] + .eligibility! + .title; + return Column( + children: [ + Container( + padding: + const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8), + decoration: box1(), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + title, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w500, + color: + primary), + ), + const SizedBox( + height: 5, + ), + Text( + "$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}", + style: Theme.of( + context) + .textTheme + .titleSmall), + const SizedBox( + height: 3, + ), + Text( + "Rating : ${state.eligibilities[index].rating ?? 'N/A'}", + style: Theme.of( + context) + .textTheme + .titleSmall), + ]), + ), + AppPopupMenu( + offset: const Offset( + -10, -10), + elevation: 3, + onSelected: (value) { + ////delete eligibilty-= = = = = = = = =>> + if (value == 2) { + confirmAlert( + context, () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + BlocProvider + .of( + context) + .add(DeleteEligibility( + eligibilityId: state + .eligibilities[ + index] + .id!, + profileId: + profileId + .toString(), + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit eligibilty-= = = = = = = = =>> + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + EligibityCert + eligibityCert = + state.eligibilities[ + index]; + bool overseas = eligibityCert + .examAddress! + .country! + .id + .toString() == + '175' + ? false + : true; + eligibityCert + .overseas = + overseas; + + eligibityCert + .overseas = + overseas; + + context + .read< + EligibilityBloc>() + .add(ShowEditEligibilityForm( + eligibityCert: + eligibityCert)); + } + ////Attachment + if (value == 3) { + results.clear(); + showDialog( + context: + context, + builder: + (BuildContext + context) { + return AlertDialog( + contentPadding: + const EdgeInsets + .all(0), + backgroundColor: + Colors + .grey + .shade100, + icon: + const Icon( + Icons + .file_copy, + size: 32, + color: + primary, + ), + title: const Text( + "File Attachment:"), + content: StatefulBuilder(builder: + (context, + setState) { + return Padding( + padding: + const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: + MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(), + Text( + title, + style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary), + ), + const SizedBox( + height: 5, + ), + Text("$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}", style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: 3, + ), + Text("Rating : ${state.eligibilities[index].rating ?? 'N/A'}", style: Theme.of(context).textTheme.titleSmall), + const Divider(), + FormBuilderDropdown( + autovalidateMode: AutovalidateMode.always, + decoration: normalTextFieldStyle("attachment category", "attachment category"), + name: 'attachments_categorues', + validator: FormBuilderValidators.required(errorText: "This field is required"), + onChanged: (value) { + selectedAttachmentCategory = value; + }, + items: attachmentCategories.map((e) { + return DropdownMenuItem(value: e, child: Text(e.description!)); + }).toList()), + const SizedBox( + height: 8, + ), + Text( + "You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.", + style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black), + ), + const SizedBox( + height: 5, + ), + Text( + "Acceptable Files: PDF, JPEG, PNG", + style: Theme.of(context).textTheme.bodySmall, + ), + Text( + "Max File Size (per attachment): 1MB", + style: Theme.of(context).textTheme.bodySmall, + ), + const Divider(), + ElevatedButton( + style: ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(Colors.white), + ), + onPressed: () async { + FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [ + 'jpg', + 'png', + 'jpeg', + 'pdf' + ]); + setState(() { + FilePickerResult? x; + if (newResult != null) { + newResult.files.forEach((element) { + results.add(element); + }); + } + }); + }, + child: const Center( + child: Text( + "Select Files", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.black), + ))), + const Divider(), + SingleChildScrollView( + child: SizedBox( + height: 100, + width: double.maxFinite, + child: results.isEmpty + ? const SizedBox() + : Expanded( + child: ListView.builder( + itemCount: results.length, + itemBuilder: (BuildContext context, index) { + final kb = results[index].size / 1024; + final mb = kb / 1024; + final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB'; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: double.infinity, + child: Row( + children: [ + Flexible( + child: SizedBox( + child: results[index].extension!.toLowerCase() == 'pdf' + ? SvgPicture.asset( + 'assets/svgs/pdf.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'png' + ? SvgPicture.asset( + 'assets/svgs/png.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg' + ? SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : const SizedBox())), + const SizedBox( + width: 12, + ), + Flexible( + flex: 6, + child: Text( + results[index].name, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 2, + child: Text( + size, + style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey), + )), + Flexible( + flex: 1, + child: IconButton( + icon: const Icon( + Icons.close, + color: Colors.grey, + ), + onPressed: () { + setState(() { + results.removeAt(index); + }); + }, + )) + ], + )), + const Divider() + ], + ); + }), + ), + ), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.maxFinite, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + List paths = []; + + if (selectedAttachmentCategory != null && results.isNotEmpty) { + for (var res in results) { + paths.add(res.path!); + } + setState(() { + results.clear(); + }); + Navigator.pop(context); + parent.read().add(AddEligibiltyAttachment(attachmentModule: state.eligibilities[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString())); + } + }, + child: const Text("Submit")), + ) + ]), + ); + }), + ); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: + Icons.delete), + popMenuItem( + text: "Attach", + value: 3, + icon: Icons + .attach_file), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + const Divider(), + ////Show Attachments + SizedBox( + width: screenWidth, + child: state + .eligibilities[ + index] + .attachments == + null || + state + .eligibilities[ + index] + .attachments! + .isEmpty + ? const SizedBox() + : state.eligibilities[index].attachments != + null && + state + .eligibilities[ + index] + .attachments! + .length == + 1 + ? + ////Single Attachment view + SingleAttachment( + view: (){ + + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EligibilityBloc()..add(EligibiltyViewAttachmentEvent(source: state.eligibilities[index].attachments!.first.source!,filename: state.eligibilities[index].attachments!.first.filename!)), + child: const EligibilityViewAttachment(), + )))); + + }, + onpressed: + () { + confirmAlert( + context, + () { + parent.read().add(DeleteEligibyAttachment( + attachment: state + .eligibilities[ + index] + .attachments! + .first, + moduleId: state + .eligibilities[ + index] + .id + .toString(), + profileId: profileId + .toString(), + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + }, + attachment: state + .eligibilities[ + index] + .attachments! + .first, + ) + ////Multiple Attachments View + : MultipleAttachments( + viewAttachment: (source,filename) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EligibilityBloc()..add(EligibiltyViewAttachmentEvent(source: source,filename: filename)), + child: const EligibilityViewAttachment(), + )))); + }, + profileId: + profileId!, + token: token!, + moduleId: state + .eligibilities[ + index] + .eligibility! + .id, + educationBloc: + null, + learningDevelopmentBloc: + null, + workHistoryBloc: + null, + eligibilityBloc: + BlocProvider.of< + EligibilityBloc>( + context), + blocId: 2, + eligibilityName: state + .eligibilities[ + index] + .eligibility! + .title, + attachments: state + .eligibilities[ + index] + .attachments!, + )) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any eligibilities added. Please click + to add"); + } + } + if (state is EditEligibilityState) { + return EditEligibilityScreen( + profileId: profileId!, + token: token!, + eligibityCert: state.eligibityCert); + } + if (state is AddEligibilityState) { + return AddEligibilityScreen( + token: token!, + profileId: profileId!, + ); + } + if (state is EligibilityErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetEligibilities( + token: token!, + profileId: profileId!)); + }); + } + return Container( + color: Colors.grey.shade200, + ); + }, + ); + }, + ), + ); + } + return Container(); + }); + } + return Container(); + }, + )), + ); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/family_background_screen.dart b/lib/screens/profile/components/family_background_screen.dart new file mode 100644 index 0000000..0e02b42 --- /dev/null +++ b/lib/screens/profile/components/family_background_screen.dart @@ -0,0 +1,1926 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/family_backround.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/add_mobile_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/child_add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/child_edit_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/father_edit_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/mother_add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/mother_edit_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/family/related_add_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/family/family_bloc.dart'; +import '../../../model/utils/agency.dart'; +import '../../../model/utils/category.dart'; +import '../../../model/utils/position.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/profile_utilities.dart'; +import 'basic_information/family/father_add_modal.dart'; +import 'basic_information/family/related_edit_modal.dart'; +import 'basic_information/family/spouse_add_modal.dart'; +import 'basic_information/family/spouse_edit_modal.dart'; + +class FamilyBackgroundScreen extends StatefulWidget { + const FamilyBackgroundScreen({ + super.key, + }); + + @override + State createState() => _FamilyBackgroundScreenState(); +} + +class _FamilyBackgroundScreenState extends State { + FamilyBackground? father; + FamilyBackground? mother; + FamilyBackground? spouse; + List children = []; + List otherRelated = []; + List bloodType = [ + "NONE", + "A+", + "B+", + "A-", + "B-", + "AB+", + "AB-", + "0+", + "0-" + ]; + List nameExtensions = [ + "NONE", + "N/A", + "SR.", + "JR.", + "I", + "II", + "III", + "IV", + "V", + "VI", + "VII", + "VIII", + "IX", + "X" + ]; + List sexes = ["MALE", "FEMALE"]; + List civilStatus = [ + "NONE", + "SINGLE", + "MARRIED", + "SEPARATED", + "WIDOWED" + ]; + List gender = [ + "NONE", + "AGENDER", + "ANATOMAL SEX", + "CISGENDER", + "CISHET", + "GENDER NON-CONFORMING", + "GENDER-EXPANSIVE", + "GENDER-FLUID", + "GENDERQUEER", + "GENDERVOID", + "INTERSEX", + "NON-BINARY", + "TRANSGENDER", + "OTHERS" + ]; + List positions = []; + List agencices = []; + List categories = []; + bool fatherIncaseOfEmergency = false; + List? relationshipTypes; + final formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + @override + Widget build(BuildContext context) { + final familyBloc = BlocProvider.of(context); + int? profileId; + String? token; + + return Scaffold( + key: _scaffoldKey, + backgroundColor: Colors.white, + appBar: AppBar( + title: const Text(familyBackgroundScreenTitle), + centerTitle: true, + backgroundColor: primary, + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + buildWhen: (previous, current) { + return false; + }, + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is FamilyLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is FamilyLoaded || + state is FamilyErrorState || + state is FamilyAddedState || + state is DeletedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////AddedState + if (state is FamilyAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } + } + if (state is EmergencyContactEditedState) { + if (state.response['success']) { + successAlert(context, state.response['message'], + state.response[''], () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } else { + errorAlert(context, state.response['message'], + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } + } + ////Edited State + if (state is FamilyEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } + } + + if (state is DeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Family Background has been deleted successfully", + () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Family", () { + Navigator.of(context).pop(); + context.read().add(LoadFamily()); + }); + } + } + }, + builder: (context, state) { + if (state is FamilyLoaded) { + if (state.families != null) { + children.clear(); + otherRelated.clear(); + father = null; + mother = null; + spouse = null; + for (var family in state.families!) { + if (family.relationship!.id == 1) { + father = family; + } + if (family.relationship!.id == 2) { + mother = family; + } + if (family.relationship!.id == 3) { + spouse = family; + } + if (family.relationship!.id == 4) { + children.add(family); + } + if (family.relationship!.id! > 4) { + otherRelated.add(family); + } + } + } + return ListView(children: [ + ////Father---------------------------------------------- + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Text( + fatherText.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: primary), + ), + ), + Container( + child: father == null + ? IconButton( + onPressed: () { + ////Show Add Alert Dialog + showDialog( + context: context, + builder: + (BuildContext + context) { + return FatherAlert( + familyBloc: + familyBloc, + profileId: + profileId!, + token: + token!, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: + sexes); + }); + }, + icon: const Icon( + Entypo.plus, + color: second, + )) + : const SizedBox(), + ) + ], + ), + Container( + child: father != null + ? Row( + children: [ + Expanded( + child: Flexible( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisSize: + MainAxisSize + .min, + children: [ + ListTile( + dense: true, + visualDensity: const VisualDensity( + horizontal: + -4, + vertical: + -4), + title: Text( + "${father?.relatedPerson?.firstName} ${father?.relatedPerson?.middleName ?? ''} ${father?.relatedPerson!.lastName} ${father?.relatedPerson?.nameExtension ?? ''}", + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500), + ), + subtitle: + const Text( + "fullname"), + ), + Row( + mainAxisSize: + MainAxisSize + .min, + children: [ + Checkbox( + visualDensity: const VisualDensity( + horizontal: + 0, + vertical: + -4), + value: father! + .incaseOfEmergency!, + onChanged: + (value) { + confirmAlertWithCancel(context, + () { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + + context.read().add(AddEmergencyEvent(requestType: "CHECKBOX", contactInfoId: father!.emergencyContact!.isNotEmpty ? father!.emergencyContact!.first.contactinfoid : null, numberMail: father!.emergencyContact!.isNotEmpty ? father!.emergencyContact!.first.numbermail : null, profileId: profileId!, relatedPersonId: father!.relatedPerson!.id!, token: token!)); + }, () {}, "Emergency Contact Information?", + father!.incaseOfEmergency == true ? "Remove as emergency contact information?" : "Add as emergency contact information?"); + }), + const Text( + incaseOfEmergency), + ////Add mobile icon + Container( + child: father!.incaseOfEmergency! && father!.emergencyContact!.isEmpty + ? IconButton( + visualDensity: const VisualDensity(horizontal: -4, vertical: -4), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: father!.emergencyContact!.isNotEmpty ? father!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: father!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }, + formKey: formKey); + }); + }, + icon: const Icon( + Entypo.plus_circled, + color: third, + size: 18, + )) + : Container()) + ], + ), + Visibility( + visible: + father! + .incaseOfEmergency!, + child: Container( + child: father!.emergencyContact!.isNotEmpty + ? Row( + children: [ + //// edit mobile + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + formKey: formKey, + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: father!.emergencyContact!.isNotEmpty ? father!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: father!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }); + }); + }, + child: Row( + children: [ + const SizedBox( + width: 16, + ), + Badge( + backgroundColor: third, + textColor: Colors.white, + label: Text(father!.emergencyContact!.first.numbermail!), + ), + ], + ), + ), + ], + ) + : Container())), + ]), + ), + ), + AppPopupMenu( + offset: const Offset( + -10, -10), + elevation: 3, + onSelected: (value) { + ////delete -= = = = = = = = =>> + if (value == 2) { + confirmAlert( + context, () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + context.read().add(DeleteFamily( + id: father! + .relatedPerson! + .id!, + profileId: + profileId!, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit eligibilty-= = = = = = = = =>> + showDialog( + context: + context, + builder: + (BuildContext + context) { + return FatherEditAlert( + familyBackground: + father!, + familyBloc: + familyBloc, + profileId: + profileId!, + token: + token!, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: + sexes); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: + Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons + .delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ) + : SizedBox( + width: screenWidth, + child: Text( + "Provide your father's primary information.",style:Theme.of(context).textTheme.bodySmall, + textAlign: + TextAlign.center, + ), + )) + ]), + ), + ], + ), + ), + + const SizedBox( + height: 8, + ), + + ////Mother----------------------------------------------------- + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + motherText.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: primary), + ), + ), + Container( + child: mother == null + ? IconButton( + onPressed: () { + ////Show Alert Dialog + showDialog( + context: context, + builder: + (BuildContext + context) { + return MotherAlert( + familyBloc: + familyBloc, + token: token!, + profileId: + profileId!, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: sexes); + }); + }, + icon: const Icon( + Entypo.plus, + color: second, + )) + : const SizedBox(), + ) + ], + ), + Container( + child: mother != null + ? Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisSize: + MainAxisSize + .min, + children: [ + ListTile( + dense: true, + visualDensity: + const VisualDensity( + horizontal: + -4, + vertical: + -4), + title: Text( + "${mother?.relatedPerson?.firstName} ${mother?.relatedPerson?.middleName ?? ''} ${mother?.relatedPerson?.lastName} ${mother?.relatedPerson?.nameExtension ?? ''}", + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500), + ), + subtitle: + const Text( + "fullname"), + ), + Row( + mainAxisSize: + MainAxisSize + .min, + children: [ + Checkbox( + visualDensity: const VisualDensity( + horizontal: + 0, + vertical: + -4), + value: mother! + .incaseOfEmergency!, + onChanged: + (value) { + confirmAlertWithCancel( + context, + () { + final progress = + ProgressHUD.of(context); + progress! + .showWithText("Loading..."); + + context.read().add(AddEmergencyEvent( + requestType: 'CHECKBOX', + contactInfoId: mother!.emergencyContact!.isNotEmpty ? mother!.emergencyContact!.first.contactinfoid : null, + numberMail: mother!.emergencyContact!.isNotEmpty ? mother!.emergencyContact!.first.numbermail : null, + profileId: profileId!, + relatedPersonId: mother!.relatedPerson!.id!, + token: token!)); + }, + () {}, + "Emergency Contact Information?", + mother!.incaseOfEmergency == true + ? "Remove as emergency contact information?" + : "Add as emergency contact information?"); + }), + const Text( + incaseOfEmergency), + Container( + child: mother!.incaseOfEmergency! && + mother!.emergencyContact!.isEmpty + ? IconButton( + visualDensity: const VisualDensity(horizontal: -4, vertical: -4), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: mother!.emergencyContact!.isNotEmpty ? mother!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: mother!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }, + formKey: formKey); + }); + }, + icon: const Icon( + Entypo.plus_circled, + color: third, + size: 18, + )) + : Container()) + ], + ), + Visibility( + visible: mother! + .incaseOfEmergency!, + child: Container( + child: mother!.emergencyContact!.isNotEmpty + ? Row( + children: [ + //// edit mobile + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + formKey: formKey, + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: mother!.emergencyContact!.isNotEmpty ? mother!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: mother!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }); + }); + }, + child: Row( + children: [ + const SizedBox( + width: 16, + ), + Badge( + backgroundColor: third, + textColor: Colors.white, + label: Text(mother!.emergencyContact!.first.numbermail!), + ), + ], + ), + ), + ], + ) + : Container())), + ]), + ), + AppPopupMenu( + offset: const Offset( + -10, -10), + elevation: 3, + onSelected: (value) { + ////delete -= = = = = = = = =>> + if (value == 2) { + confirmAlert( + context, () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + context + .read< + FamilyBloc>() + .add(DeleteFamily( + id: mother! + .relatedPerson! + .id!, + profileId: + profileId!, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit eligibilty-= = = = = = = = =>> + showDialog( + context: + context, + builder: + (BuildContext + context) { + return MotherEditAlert( + familyBackground: + mother!, + familyBloc: + familyBloc, + token: + token!, + profileId: + profileId!, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: + sexes); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: + Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ) + : SizedBox( + width: screenWidth, + child: Text( + "Provide your mother's primary information",style: Theme.of(context).textTheme.bodySmall, + textAlign: + TextAlign.center, + ), + )), + ], + ), + ), + ], + ), + ), + const SizedBox( + height: 8, + ), + ////Spouse --------------------------------------------------------- + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + spouseText.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: primary), + ), + ), + Container( + child: spouse == null + ? IconButton( + ////spouse + //// Show Dialog + onPressed: () async { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + try { + if (positions + .isEmpty) { + positions = + await ProfileUtilities + .instance + .getAgencyPosition(); + } + + if (agencices + .isEmpty) { + agencices = + await ProfileUtilities + .instance + .getAgecies(); + } + if (categories + .isEmpty) { + categories = + await ProfileUtilities + .instance + .agencyCategory(); + } + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + FamilyBloc>() + .add(CallErrorState( + message: e + .toString())); + } + progress.dismiss(); + showDialog( + context: NavigationService + .navigatorKey + .currentContext!, + builder: + (BuildContext + context) { + return SpouseAlert( + familyBloc: + familyBloc, + token: token!, + profileId: + profileId!, + positions: + positions, + agencies: + agencices, + category: + categories, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: sexes); + }); + }, + icon: const Icon( + Entypo.plus, + color: second, + )) + : const SizedBox(), + ) + ], + ), + Container( + child: spouse != null + ? Row( + children: [ + Expanded( + child: Column( + children: [ + const SizedBox( + height: 5, + ), + ListTile( + dense: true, + visualDensity: + const VisualDensity( + horizontal: + -4, + vertical: + -4), + title: Text( + "${spouse?.relatedPerson?.firstName} ${spouse?.relatedPerson?.middleName ?? ''} ${spouse?.relatedPerson!.lastName} ${spouse?.relatedPerson?.nameExtension ?? ''}", + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500), + ), + subtitle: + const Text( + "fullname"), + ), + Row( + children: [ + Checkbox( + visualDensity: const VisualDensity( + horizontal: + 0, + vertical: + -4), + value: spouse! + .incaseOfEmergency!, + onChanged: + (value) { + confirmAlertWithCancel( + context, + () { + final progress = + ProgressHUD.of(context); + progress! + .showWithText("Loading..."); + + context.read().add(AddEmergencyEvent( + contactInfoId: spouse!.emergencyContact!.isNotEmpty ? spouse!.emergencyContact!.first.contactinfoid : null, + numberMail: spouse!.emergencyContact!.isNotEmpty ? spouse!.emergencyContact!.first.numbermail : null, + profileId: profileId!, + relatedPersonId: spouse!.relatedPerson!.id!, + token: token!, + requestType: "CHECKBOX")); + }, + () {}, + "Emergency Contact Information?", + spouse!.incaseOfEmergency == true + ? "Remove as emergency contact information?" + : "Add as emergency contact information?"); + }), + const Text( + incaseOfEmergency), + ////Add mobile icon + Container( + child: spouse!.incaseOfEmergency! && + spouse!.emergencyContact!.isEmpty + ? IconButton( + visualDensity: const VisualDensity(horizontal: -4, vertical: -4), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: spouse!.emergencyContact!.isNotEmpty ? spouse!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: spouse!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }, + formKey: formKey); + }); + }, + icon: const Icon( + Entypo.plus_circled, + color: third, + size: 18, + )) + : Container()), + ], + ), + Visibility( + visible: spouse! + .incaseOfEmergency!, + child: Container( + child: spouse!.emergencyContact!.isNotEmpty + ? Row( + children: [ + //// edit mobile + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + formKey: formKey, + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: spouse!.emergencyContact!.isNotEmpty ? spouse!.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: spouse!.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }); + }); + }, + child: Row( + children: [ + const SizedBox( + width: 16, + ), + Badge( + backgroundColor: third, + textColor: Colors.white, + label: Text(spouse!.emergencyContact!.first.numbermail!), + ), + ], + ), + ), + ], + ) + : Container())), + Container( + padding: + const EdgeInsets + .only( + left: + 12), + alignment: + Alignment + .topLeft, + child: spouse + ?.position != + null + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox( + height: + 12, + ), + Text( + "OCCUPATION", + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 3, + ), + Text( + spouse!.position!.title!, + style: Theme.of(context).textTheme.titleMedium, + ), + Text( + spouse!.company!.name!, + style: Theme.of(context).textTheme.titleMedium, + ), + Text( + spouse!.companyAddress!, + style: Theme.of(context).textTheme.labelMedium, + ), + Text( + spouse!.companyContactNumber!, + style: Theme.of(context).textTheme.labelMedium, + ), + ], + ) + ], + ) + : const SizedBox(), + ) + ]), + ), + AppPopupMenu( + offset: const Offset( + -10, -10), + elevation: 3, + onSelected: + (value) async { + ////delete -= = = = = = = = =>> + if (value == 2) { + confirmAlert( + context, () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + context + .read< + FamilyBloc>() + .add(DeleteFamily( + id: spouse! + .relatedPerson! + .id!, + profileId: + profileId!, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit eligibilty-= = = = = = = = =>> + + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + if (positions + .isEmpty) { + positions = + await ProfileUtilities + .instance + .getAgencyPosition(); + } + + if (agencices + .isEmpty) { + agencices = + await ProfileUtilities + .instance + .getAgecies(); + } + if (categories + .isEmpty) { + categories = + await ProfileUtilities + .instance + .agencyCategory(); + } + progress.dismiss(); + showDialog( + context: NavigationService + .navigatorKey + .currentContext!, + builder: + (BuildContext + context) { + return SpouseEditAlert( + familyBackground: + spouse!, + familyBloc: + familyBloc, + token: + token!, + profileId: + profileId!, + positions: + positions, + agencies: + agencices, + category: + categories, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: + gender, + nameExtensions: + nameExtensions, + sexes: + sexes); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: + Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ) + : SizedBox( + width: screenWidth, + child: Padding( + padding: + const EdgeInsets.symmetric( + vertical: 8, + horizontal: 0), + child: Text( + "Provide your spouse's primary and employment information. Leave empty if not applicable.",style: Theme.of(context).textTheme.bodySmall, + textAlign: + TextAlign.center, + ), + ), + )), + ], + ), + ), + ], + ), + ), + + const SizedBox( + height: 8, + ), + //// Childrens ---------------------------------- + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + childrenText.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: primary), + ), + const Expanded(child: SizedBox()), + IconButton( + ////childrens + ////Show add dialog + onPressed: () { + showDialog( + context: context, + builder: (BuildContext + context) { + return ChildAlert( + familyBloc: + familyBloc, + token: token!, + profileId: + profileId!, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: gender, + nameExtensions: + nameExtensions, + sexes: sexes); + }); + }, + icon: const Icon( + Entypo.plus, + color: second, + )) + ], + ), + Container( + + child: children.isNotEmpty + ? Column( + mainAxisSize: + MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: + children.map((child) { + return Container( + padding: + const EdgeInsets + .symmetric( + horizontal: 12, + vertical: 0), + width: screenWidth, + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + const SizedBox( + height: 5, + ), + Row( + mainAxisSize: + MainAxisSize + .min, + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisSize: + MainAxisSize + .min, + children: [ + ListTile( + dense: + true, + visualDensity: const VisualDensity( + horizontal: -4, + vertical: -4), + title: Text( + "${child.relatedPerson?.firstName} ${child.relatedPerson?.middleName ?? ''} ${child.relatedPerson?.lastName} ${child.relatedPerson?.nameExtension ?? ''}", + style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500)), + subtitle: + const Text("fullname"), + ), + Row( + mainAxisSize: + MainAxisSize.min, + children: [ + Checkbox( + visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + value: child.incaseOfEmergency!, + onChanged: (value) { + confirmAlertWithCancel(context, () { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + + context.read().add(AddEmergencyEvent(contactInfoId: child.emergencyContact!.isNotEmpty ? child.emergencyContact!.first.contactinfoid : null, numberMail: child.emergencyContact!.isNotEmpty ? child.emergencyContact!.first.numbermail : null, profileId: profileId!, relatedPersonId: child.relatedPerson!.id!, token: token!, requestType: "CHECKBOX")); + }, () {}, "Emergency Contact Information?", child.incaseOfEmergency == true ? "Remove as emergency contact information?" : "Add as emergency contact information?"); + }), + const Text(incaseOfEmergency), + ////Add mobile icon + Container( + child: child.incaseOfEmergency! && child.emergencyContact!.isEmpty + ? IconButton( + visualDensity: const VisualDensity(horizontal: -4, vertical: -4), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: child.emergencyContact!.isNotEmpty ? child.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: child.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }, + formKey: formKey); + }); + }, + icon: const Icon( + Entypo.plus_circled, + color: third, + size: 18, + )) + : Container()) + ], + ), + //// child person add mobile number + Visibility( + visible: + child.incaseOfEmergency!, + child: Container( + child: child.emergencyContact!.isNotEmpty + ? Row( + children: [ + //// edit mobile + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + formKey: formKey, + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: child.emergencyContact!.isNotEmpty ? child.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: child.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }); + }); + }, + child: Row( + children: [ + const SizedBox( + width: 16, + ), + Badge( + backgroundColor: third, + textColor: Colors.white, + label: Text(child.emergencyContact!.first.numbermail!), + ), + ], + ), + ), + ], + ) + : Container())), + ]), + ), + AppPopupMenu< + int>( + offset: + const Offset( + -10, + -10), + elevation: 3, + onSelected: + (value) { + ////delete -= = = = = = = = =>> + if (value == + 2) { + confirmAlert( + context, + () { + final progress = + ProgressHUD.of(context); + progress! + .showWithText("Loading..."); + context.read().add(DeleteFamily( + id: child + .relatedPerson!.id!, + profileId: + profileId!, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == + 1) { + //// edit + showDialog( + context: + context, + builder: + (BuildContext context) { + return ChildEditAlert( + familyBackground: child, + familyBloc: familyBloc, + profileId: profileId!, + token: token!, + bloodType: bloodType, + civilStatus: civilStatus, + gender: gender, + nameExtensions: nameExtensions, + sexes: sexes); + }); + } + }, + menuItems: [ + popMenuItem( + text: + "Update", + value: + 1, + icon: Icons + .edit), + popMenuItem( + text: + "Remove", + value: + 2, + icon: Icons + .delete), + ], + icon: + const Icon( + Icons + .more_vert, + color: Colors + .grey, + ), + tooltip: + "Options", + ) + ], + ), + ], + ), + ); + }).toList()) + : SizedBox( + width: screenWidth, + child: Padding( + padding: + const EdgeInsets.symmetric( + vertical: 8, + horizontal: 0), + child: Text( + "Provide your child/children's primary information. Leave empty if not applicable.",style: Theme.of(context).textTheme.bodySmall, + textAlign: + TextAlign.center, + ), + ), + )), + ], + ), + ), + ], + ), + ), + const SizedBox( + height: 8, + ), + ////Other related person + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + otherRelatedText.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: primary), + ), + ), + IconButton( + ////other related + //// Show Alert Dialog + onPressed: () async { + final progress = + ProgressHUD.of(context); + progress!.showWithText( + "Loading..."); + List + relationshipTypes = + await ProfileUtilities + .instance + .getRelationshipType(); + progress.dismiss(); + showDialog( + context: NavigationService + .navigatorKey + .currentContext!, + builder: (BuildContext + context) { + return RelatedAlert( + token: token!, + profileId: + profileId!, + familyBloc: + familyBloc, + relationships: + relationshipTypes, + bloodType: + bloodType, + civilStatus: + civilStatus, + gender: gender, + nameExtensions: + nameExtensions, + sexes: sexes); + }); + }, + icon: const Icon( + Entypo.plus, + color: second, + )) + ], + ), + Container( + child: otherRelated.isNotEmpty + ? Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: otherRelated + .map((relative) { + return Container( + padding: + const EdgeInsets + .symmetric( + horizontal: 12, + vertical: 0), + width: screenWidth, + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + const SizedBox( + height: 5, + ), + Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisSize: + MainAxisSize + .min, + children: [ + ListTile( + dense: + true, + visualDensity: const VisualDensity( + horizontal: -4, + vertical: -4), + title: Text( + "${relative.relatedPerson?.firstName} ${relative.relatedPerson?.middleName ?? ""} ${relative.relatedPerson?.lastName} ${relative.relatedPerson?.nameExtension ?? ''}", + style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500)), + subtitle: + const Text("fullname"), + ), + Row( + mainAxisSize: + MainAxisSize.min, + children: [ + Checkbox( + visualDensity: const VisualDensity(horizontal: 0, vertical: -4), + value: relative.incaseOfEmergency!, + onChanged: (value) { + confirmAlertWithCancel(context, () { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + + context.read().add(AddEmergencyEvent(contactInfoId: relative.emergencyContact!.isNotEmpty ? relative.emergencyContact!.first.contactinfoid : null, numberMail: relative.emergencyContact!.isNotEmpty ? relative.emergencyContact!.first.numbermail : null, profileId: profileId!, relatedPersonId: relative.relatedPerson!.id!, token: token!, requestType: "CHECKBOX")); + }, () {}, "Emergency Contact Information?", relative.incaseOfEmergency == true ? "Remove as emergency contact information?" : "Add as emergency contact information?"); + }), + const Text(incaseOfEmergency), + Container( + child: relative.incaseOfEmergency! && relative.emergencyContact!.isEmpty + ? IconButton( + visualDensity: const VisualDensity(horizontal: -4, vertical: -4), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: relative.emergencyContact!.isNotEmpty ? relative.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: relative.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }, + formKey: formKey); + }); + }, + icon: const Icon( + Entypo.plus_circled, + color: third, + size: 18, + )) + : Container()) + ], + ), + //// other related person add mobile number + Visibility( + visible: + relative.incaseOfEmergency!, + child: Container( + child: relative.emergencyContact!.isNotEmpty + ? Row( + children: [ + //// edit mobile + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AddMobileNumber( + formKey: formKey, + onPressed: () { + Navigator.of(_scaffoldKey.currentContext!).pop(); + familyBloc.add(AddEmergencyEvent(contactInfoId: relative.emergencyContact!.isNotEmpty ? relative.emergencyContact!.first.contactinfoid : null, numberMail: formKey.currentState!.value['number_mail'], profileId: profileId!, relatedPersonId: relative.relatedPerson!.id!, token: token!, requestType: "CONTACT")); + }); + }); + }, + child: Row( + children: [ + const SizedBox( + width: 16, + ), + Badge( + backgroundColor: third, + textColor: Colors.white, + label: Text(relative.emergencyContact!.first.numbermail!), + ), + ], + ), + ), + ], + ) + : Container()), + ) + ]), + ), + AppPopupMenu< + int>( + offset: + const Offset( + -10, + -10), + elevation: 3, + onSelected: + (value) async { + ////delete -= = = = = = = = =>> + if (value == + 2) { + confirmAlert( + context, + () { + final progress = + ProgressHUD.of(context); + progress! + .showWithText("Loading..."); + context.read().add(DeleteFamily( + id: relative + .relatedPerson!.id!, + profileId: + profileId!, + token: + token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == + 1) { + ////edit eligibilty-= = = = = = = = =>> + await getRelationshiptypes( + context); + showDialog( + context: NavigationService + .navigatorKey + .currentContext!, + builder: + (BuildContext context) { + return RelatedEditAlert( + familyBackground: relative, + token: token!, + profileId: profileId!, + familyBloc: familyBloc, + relationships: relationshipTypes!, + bloodType: bloodType, + civilStatus: civilStatus, + gender: gender, + nameExtensions: nameExtensions, + sexes: sexes); + }); + } + }, + menuItems: [ + popMenuItem( + text: + "Update", + value: + 1, + icon: Icons + .edit), + popMenuItem( + text: + "Remove", + value: + 2, + icon: Icons + .delete), + ], + icon: + const Icon( + Icons + .more_vert, + color: Colors + .grey, + ), + tooltip: + "Options", + ) + ], + ), + ], + ), + ); + }).toList()) + : SizedBox( + width: screenWidth, + child: Padding( + padding: + const EdgeInsets.symmetric( + vertical: 8, + horizontal: 0), + child: Text( + "Provide the other related person's primary information. Leave empty if not applicable.",style: Theme.of(context).textTheme.bodySmall, + textAlign: + TextAlign.center, + ), + ), + )), + ], + ), + ), + ], + ), + ), + ]); + } + if (state is FamilyErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetFamilies( + profileId: profileId!, token: token!)); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + ), + ); + } + + getRelationshiptypes(BuildContext parentContext) async { + final progress = ProgressHUD.of(parentContext); + progress!.showWithText("Loading..."); + + relationshipTypes = await ProfileUtilities.instance.getRelationshipType(); + progress.dismiss(); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/learning_and_development_screen.dart b/lib/screens/profile/components/learning_and_development_screen.dart new file mode 100644 index 0000000..1fe52ba --- /dev/null +++ b/lib/screens/profile/components/learning_and_development_screen.dart @@ -0,0 +1,827 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; + +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/learning_development/edit_modal.dart'; +import 'package:unit2/screens/profile/components/learning_development/learning_development_view_attachment.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import '../../../model/profile/attachment.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../widgets/Leadings/close_leading.dart'; +import '../shared/multiple_attachment.dart'; +import '../shared/single_attachment.dart'; +import 'learning_development/add_modal.dart'; + +class LearningAndDevelopmentScreen extends StatelessWidget { + const LearningAndDevelopmentScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + String token; + int profileId; + BuildContext parent = context; + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + List? results = []; + AttachmentCategory? selectedAttachmentCategory; + List attachmentCategories = []; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state + is LearningDevelopmentAddingState + ? const FittedBox( + child: Text("Add $learningAndDevelopmentScreenTitle")) + : context.watch().state + is LearningDevelopmentUpdatingState + ? const FittedBox( + child: Text("Edit $learningAndDevelopmentScreenTitle")) + : const FittedBox( + child: Text(learningAndDevelopmentScreenTitle)), + centerTitle: true, + backgroundColor: primary, + actions: (context.watch().state + is LearningDevelopmentLoadedState) + ? [ + AddLeading(onPressed: () { + context + .read() + .add(ShowAddLearningDevelopmentForm()); + }) + ] + : (context.watch().state + is LearningDevelopmentAddingState || + context.watch().state + is LearningDevelopmentUpdatingState) + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(LoadLearniningDevelopment()); + }) + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token!; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is LearningDevelopmentLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is LearningDevelopmentLoadedState || + state is LearningDevelopmentErrorState || + state is LearningDevelopmentAddingState || + state is LearningDevelopmentAddedState || + state is LearningDevelopmentUpdatingState || + state is LearningDevelopmentUpdatedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + //// Added State + if (state is LearningDevelopmentAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } + } + ////Attachment Added State + if (state is LearningDevAttachmentAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } + } + ////Updated State + if (state is LearningDevelopmentUpdatedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } + } + ////Deleted State + if (state is DeleteLearningDevelopmentState) { + if (state.success) { + successAlert(context, "Deletion Successfull!", + "Learning Development Has Been Deleted Successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } + } + ////ATTACHMENT DELETED STATE + if (state is LearningDevAttachmentDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Attachment has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Attachment", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadLearniningDevelopment()); + }); + } + } + // TODO: implement listener + }, + builder: (context, state) { + if (state is LearningDevelopmentLoadedState) { + for (var cat in state.attachmentCategory) { + if (cat.subclass!.id == 2) { + attachmentCategories.add(cat); + } + } + if (state.learningsAndDevelopment.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: + state.learningsAndDevelopment.length, + itemBuilder: + (BuildContext context, int index) { + String training = state + .learningsAndDevelopment[index] + .conductedTraining! + .title! + .title!; + String provider = state + .learningsAndDevelopment[index] + .conductedTraining! + .conductedBy! + .name!; + String start = dteFormat2.format(state + .learningsAndDevelopment[index] + .conductedTraining! + .fromDate!); + String end = dteFormat2.format(state + .learningsAndDevelopment[index] + .conductedTraining! + .toDate!); + String type = state + .learningsAndDevelopment[index] + .conductedTraining! + .learningDevelopmentType! + .title!; + return Column( + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + width: screenWidth, + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + training, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w600, + color: + primary), + ), + const SizedBox( + height: 8, + ), + Text( + provider, + style: Theme.of( + context) + .textTheme + .titleSmall, + ), + const SizedBox( + height: 5, + ), + Text( + "$duration: $start to $end", + style: Theme.of( + context) + .textTheme + .labelMedium, + ), + const SizedBox( + height: 5, + ), + ]), + ), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete -= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, + () { + final progress = + ProgressHUD.of( + context); + progress! + .showWithText( + "Loading..."); + BlocProvider.of(context).add(DeleteLearningDevelopment( + trainingId: state + .learningsAndDevelopment[ + index] + .conductedTraining! + .id!, + hours: state + .learningsAndDevelopment[ + index] + .conductedTraining! + .totalHours!, + sponsorId: state + .learningsAndDevelopment[ + index] + .sponsoredBy + ?.id, + profileId: + profileId, + token: token)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + bool isOverseas; + ////edit = = = = = = = =>> + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + + if (state + .learningsAndDevelopment[ + index] + .conductedTraining + ?.venue + ?.cityMunicipality == + null) { + isOverseas = true; + } else { + isOverseas = false; + } + context + .read< + LearningDevelopmentBloc>() + .add(ShowEditLearningDevelopmentForm( + profileId: + profileId, + token: token, + learningDevelopment: + state.learningsAndDevelopment[ + index], + isOverseas: + isOverseas)); + } + if (value == 3) { + results.clear(); + showDialog( + context: context, + builder: + (BuildContext + context) { + return AlertDialog( + contentPadding: + const EdgeInsets + .all(0), + backgroundColor: + Colors.grey + .shade100, + icon: + const Icon( + Icons + .file_copy, + size: 32, + color: + primary, + ), + title: const Text( + "File Attachment:"), + content: StatefulBuilder( + builder: + (context, + setState) { + return Padding( + padding: const EdgeInsets + .all( + 16.0), + child: Column( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const Divider(), + Text( + training, + style: + Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary), + ), + const SizedBox( + height: + 5, + ), + Text( + provider, + style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: + 3, + ), + Text( + "$start TO $end", + style: Theme.of(context).textTheme.titleSmall), + const Divider(), + FormBuilderDropdown( + autovalidateMode: AutovalidateMode.always, + decoration: normalTextFieldStyle("attachment category", "attachment category"), + name: 'attachments_categorues', + validator: FormBuilderValidators.required(errorText: "This field is required"), + onChanged: (value) { + selectedAttachmentCategory = value; + }, + items: attachmentCategories.map((e) { + return DropdownMenuItem(value: e, child: Text(e.description!)); + }).toList()), + const SizedBox( + height: + 8, + ), + Text( + "You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.", + style: + Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black), + ), + const SizedBox( + height: + 5, + ), + Text( + "Acceptable Files: PDF, JPEG, PNG", + style: + Theme.of(context).textTheme.bodySmall, + ), + Text( + "Max File Size (per attachment): 1MB", + style: + Theme.of(context).textTheme.bodySmall, + ), + const Divider(), + ElevatedButton( + style: ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(Colors.white), + ), + onPressed: () async { + FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [ + 'jpg', + 'png', + 'jpeg', + 'pdf' + ]); + setState(() { + if (newResult != null) { + newResult.files.forEach((element) { + results.add(element); + }); + } + }); + }, + child: const Center( + child: Text( + "Select Files", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.black), + ))), + const Divider(), + SingleChildScrollView( + child: + SizedBox( + height: 100, + width: double.maxFinite, + child: results.isEmpty + ? const SizedBox() + : Expanded( + child: ListView.builder( + itemCount: results.length, + itemBuilder: (BuildContext context, index) { + final kb = results[index].size / 1024; + final mb = kb / 1024; + final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB'; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: double.infinity, + child: Row( + children: [ + Flexible( + flex: 1, + child: SizedBox( + child: results[index].extension!.toLowerCase() == 'pdf' + ? SvgPicture.asset( + 'assets/svgs/pdf.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'png' + ? SvgPicture.asset( + 'assets/svgs/png.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg' + ? SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : const SizedBox())), + const SizedBox( + width: 12, + ), + Flexible( + flex: 6, + child: Text( + results[index].name, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 2, + child: Text( + size, + style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey), + )), + Flexible( + flex: 1, + child: IconButton( + icon: const Icon( + Icons.close, + color: Colors.grey, + ), + onPressed: () { + setState(() { + results.removeAt(index); + }); + }, + )) + ], + )), + const Divider() + ], + ); + }), + ), + ), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: + double.maxFinite, + height: + 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + List paths = []; + + if (selectedAttachmentCategory != null && results.isNotEmpty) { + for (var res in results) { + paths.add(res.path!); + } + results.clear(); + Navigator.pop(context); + parent.read().add(AddALearningDevttachment(attachmentModule: state.learningsAndDevelopment[index].conductedTraining!.id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token, profileId: profileId.toString())); + } + }, + child: const Text("Submit")), + ) + ]), + ); + }), + ); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + popMenuItem( + text: "Attach", + value: 3, + icon: Icons + .attach_file), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + SizedBox( + child: state + .learningsAndDevelopment[ + index] + .attachments == + null || + state + .learningsAndDevelopment[ + index] + .attachments! + .isEmpty + ? const SizedBox() + : state + .learningsAndDevelopment[ + index] + .attachments != + null && + state + .learningsAndDevelopment[ + index] + .attachments! + .length == + 1 + ? + ////Single Attachment view + SingleAttachment( + view: (){ + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: LearningDevelopmentBloc()..add(LearningDevelopmentViewAttachmentEvent(source: state.learningsAndDevelopment[index].attachments!.first.source!,filename: state.learningsAndDevelopment[index].attachments!.first.filename!)), + child: const LearningDevelopmentViewAttachment(), + )))); + }, + onpressed: () { + confirmAlert( + context, + () { + parent.read().add(DeleteLearningDevAttachment( + attachment: state + .learningsAndDevelopment[ + index] + .attachments! + .first, + moduleId: state + .learningsAndDevelopment[ + index] + .conductedTraining! + .id!, + profileId: + profileId, + token: + token)); + }, "Delete?", + "Confirm Delete?"); + }, + attachment: state + .learningsAndDevelopment[ + index] + .attachments! + .first, + ) + ////Multiple Attachments View + : MultipleAttachments( + viewAttachment: + (source,filename) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => + BlocProvider.value( + value: LearningDevelopmentBloc()..add(LearningDevelopmentViewAttachmentEvent(source: source,filename: filename)), + child: const LearningDevelopmentViewAttachment(), + )))); + }, + profileId: + profileId, + token: token, + moduleId: state + .learningsAndDevelopment[ + index] + .conductedTraining! + .title! + .id!, + educationBloc: + null, + eligibilityBloc: + null, + learningDevelopmentBloc: + BlocProvider.of< + LearningDevelopmentBloc>( + context), + workHistoryBloc: + null, + blocId: 4, + eligibilityName: state + .learningsAndDevelopment[ + index] + .conductedTraining! + .title! + .title!, + attachments: state + .learningsAndDevelopment[ + index] + .attachments!, + )) + ], + ), + ), + const SizedBox( + height: 8, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any Learning and Development added. Please click + to add."); + } + } + if (state is LearningDevelopmentErrorState) { + return (SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetLearningDevelopments( + profileId: profileId, token: token)); + })); + } + if (state is LearningDevelopmentAddingState) { + return AddLearningAndDevelopmentScreen( + token: token, + profileId: profileId, + ); + } + if (state is LearningDevelopmentUpdatingState) { + return EditLearningAndDevelopmentScreen( + token: token, + profileId: profileId, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/learning_development/add_modal.dart b/lib/screens/profile/components/learning_development/add_modal.dart new file mode 100644 index 0000000..e3d1e7d --- /dev/null +++ b/lib/screens/profile/components/learning_development/add_modal.dart @@ -0,0 +1,1575 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:searchable_paginated_dropdown/searchable_paginated_dropdown.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import 'package:unit2/model/profile/learning_development.dart'; +import 'package:unit2/screens/profile/components/learning_development/display_details.dart'; +import 'package:unit2/screens/profile/components/learning_development/training_details.dart'; +import 'package:unit2/sevices/profile/learningDevelopment_service.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/utils/validators.dart'; +import '../../../../model/location/barangay.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../widgets/error_state.dart'; +import '../../shared/add_for_empty_search.dart'; + +class AddLearningAndDevelopmentScreen extends StatefulWidget { + final int profileId; + final String token; + const AddLearningAndDevelopmentScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _AddLearningAndDevelopmentScreenState(); +} + +class _AddLearningAndDevelopmentScreenState + extends State { + final formKey = GlobalKey(); + + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + + bool isPrivate = false; + + bool showSponsorByAgency = false; + bool showOtherInputs = false; + bool showTrainingDetails = false; + bool hasSponsor = false; + + LearningDevelopmentType? selectedLearningDevelopmentType; + final fromDateController = TextEditingController(); + final toDateController = TextEditingController(); +////Training + bool show = true; + final addTrainingController = TextEditingController(); + ConductedTraining? selectedConductedTraining; + LearningDevelopmentType? selectedTraining; + +////Topic + final topicFocusNode = FocusNode(); + final addTopicController = TextEditingController(); + LearningDevelopmentType? selectedTopic; + +////address + Barangay? selectedBarangay; + Country? selectedCountry; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + List? provinces; + List? citymuns; + List? barangays; + + ////Sponsor Agency Searchfield + Agency? selectedSponsorAgency; + Category? selectedSponsorAgencyCategory; + bool showSponsorCategoryAgency = false; + bool showSponsorAgencyPrivateRadio = false; + bool sponsorAgencyIsPrivate = false; + final addSponsorAgencyController = TextEditingController(); + final sponsorByFocusNode = FocusNode(); + final sponsorAgencyCategoryFocusNode = FocusNode(); + +////Conducted By + Agency? selectedConductedByAgency; + Category? selectedConductedByAgencyCategory; + bool showConductedByAgencyPrivateRadio = false; + final conductedByFocusNode = FocusNode(); + final conductedByAgencyCategoryFocusNode = FocusNode(); + final addConductedByController = TextEditingController(); + bool showConductedByAgencyCategory = false; + bool conductedByCategoryIsPrivate = false; + + final selectedTrainingController = TextEditingController(); + DateTime? from; + DateTime? to; + @override + void dispose() { + // fromDateController.dispose(); + // toDateController.dispose(); + // addTrainingController.dispose(); + // addTopicController.dispose(); + // topicFocusNode.dispose(); + + // addSponsorAgencyController.dispose(); + // sponsorByFocusNode.dispose(); + // sponsorAgencyCategoryFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is LearningDevelopmentAddingState) { + return FormBuilder( + key: formKey, + child: Padding( + padding: const EdgeInsets.all(24), + child: StatefulBuilder(builder: (context, setState) { + return ListView( + children: [ + ////Training SearchField + SizedBox( + child: show + ? SearchableDropdownFormField.paginated( + errorWidget: (value) { + return SomethingWentWrong( + message: value, + onpressed: () { + context + .read< + LearningDevelopmentBloc>() + .add( + GetLearningDevelopments( + profileId: widget + .profileId, + token: + widget.token)); + }); + }, + noRecordTex: SizedBox( + width: double.infinity, + height: 300, + child: EmptyWidget( + controller: addTrainingController, + onpressed: () { + setState(() { + show = false; + showOtherInputs = true; + selectedTrainingController + .text = + addTrainingController.text + .toUpperCase(); + selectedTraining = + LearningDevelopmentType( + id: null, + title: + selectedTrainingController + .text); + addTrainingController.text = + ""; + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }); + }, + title: "Add Training"), + ), + isDialogExpanded: false, + hintText: const Text('Search Training'), + margin: const EdgeInsets.all(15), + backgroundDecoration: (child) { + return SizedBox( + width: double.infinity, + child: Card( + child: Padding( + padding: + const EdgeInsets.all(16), + child: child), + ), + ); + }, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + paginatedRequest: (int page, + String? searchKey) async { + List + paginatedList=[]; + try { + paginatedList = + await LearningDevelopmentServices + .instance + .getConductedTrainings( + page: page, + key: searchKey ??= ""); + } catch (e) { + context + .read() + .add(CallErrorState( + message: e.toString())); + } + return paginatedList.map((e) { + return SearchableDropdownMenuItem( + value: e, + onTap: () {}, + label: e.title!.title!, + child: TrainingDisplayDetails( + ////not what you are looking for + notWhatYourLookingFor: () { + setState(() { + if (e.learningDevelopmentType + ?.id != + null) { + selectedTraining = + LearningDevelopmentType( + id: e.title!.id, + title: null); + } else { + selectedTraining = + LearningDevelopmentType( + id: null, + title: e.title! + .title); + } + show = false; + showOtherInputs = true; + + selectedTrainingController + .text = + e.title!.title!; + Navigator.of(context) + .pop(); + }); + }, + e: e, + )); + }).toList(); + }, + dropDownMaxHeight: 500, + requestItemCount: 5, + //// on chage + onChanged: (ConductedTraining? value) { + setState(() { + selectedConductedTraining = value; + selectedTrainingController.text = + selectedConductedTraining! + .title!.title!; + show = false; + showTrainingDetails = true; + }); + }, + ) + : const SizedBox(), + ), + const SizedBox( + height: 12, + ), + SizedBox( + ////Training selected Textfield + child: !show + ? FormBuilderTextField( + maxLines: 5, + readOnly: true, + controller: + selectedTrainingController, + name: "", + decoration: + normalTextFieldStyle("", "") + .copyWith( + labelText: "Training", + suffixIcon: IconButton( + onPressed: () { + setState(() { + selectedConductedTraining = + null; + selectedTrainingController + .text = ""; + show = true; + showTrainingDetails = + false; + showOtherInputs = + false; + selectedTraining = + null; + }); + }, + icon: const Icon( + Icons.close))), + ) + : const SizedBox()), + + ////ShowTraining Details + SizedBox( + child: showTrainingDetails + ? TrainingDetails( + trainingTitle: + selectedConductedTraining! + .learningDevelopmentType! + .title!, + totalHours: selectedConductedTraining! + .totalHours!, + trainingTopic: + selectedConductedTraining! + .topic!.title!, + toDate: selectedConductedTraining! + .toDate + .toString(), + fromDate: selectedConductedTraining! + .fromDate! + .toString(), + conductedBy: selectedConductedTraining! + .conductedBy!.name!) + : const SizedBox(), + ), + ///// end show training details + //// show other inputs + SizedBox( + child: showOtherInputs + ? SizedBox( + child: Column(children: [ + const SizedBox( + height: 12, + ), + ////learning development type + FormBuilderDropdown< + LearningDevelopmentType>( + decoration: normalTextFieldStyle( + "Learning Development Type *", + ""), + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + name: "types", + items: state.types + .map((e) => DropdownMenuItem< + LearningDevelopmentType>( + value: e, + child: Text(e.title!))) + .toList(), + onChanged: (value) { + selectedLearningDevelopmentType = + value; + }, + ), + + //// learning development topics + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context, setState) { + return SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + focusNode: topicFocusNode, + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: state.topics + .map((LearningDevelopmentType + topic) => + SearchFieldListItem( + topic.title!, + item: topic, + child: Padding( + padding: const EdgeInsets + .symmetric( + horizontal: + 10), + child: ListTile( + title: Text( + topic + .title!, + softWrap: + true, + ), + )))) + .toList(), + + searchInputDecoration: + normalTextFieldStyle( + "Topic *", "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + topicFocusNode.unfocus(); + }, + )), + onSuggestionTap: (topic) { + if (topic.item?.id != null) { + selectedTopic = + LearningDevelopmentType( + id: topic.item!.id, + title: null); + } else { + selectedTopic = + LearningDevelopmentType( + id: null, + title: topic + .item!.title); + } + setState(() { + topicFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Topic", + controller: + addTopicController, + onpressed: () { + setState(() { + LearningDevelopmentType + newTopic = + LearningDevelopmentType( + id: null, + title: addTopicController + .text + .toUpperCase()); + state.topics.insert( + 0, newTopic); + topicFocusNode + .unfocus(); + addTopicController + .text = ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: StatefulBuilder( + builder: (context, setState) { + return StatefulBuilder(builder: + (context, setState) { + return Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + use24HourFormat: + false, + icon: const Icon( + Icons + .date_range), + controller: + fromDateController, + firstDate: + DateTime(1990), + lastDate: + DateTime(2100), + + onChanged: (value) { + setState(() { + from = DateTime + .parse( + value); + }); + }, + initialDate: to == + null + ? DateTime.now() + : to!.subtract( + const Duration( + days: + 1)), + timeHintText: + "Date of Examination/Conferment", + decoration: normalTextFieldStyle( + "From *", + "From *") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: Colors + .black87, + )), + initialValue: null, + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: + toDateController, + firstDate: + DateTime(1990), + + onChanged: (value) { + setState(() { + to = DateTime + .parse(value); + }); + }, + initialDate: from == + null + ? DateTime.now() + : from!.add( + const Duration( + days: 1)), + lastDate: + DateTime(2100), + decoration: + normalTextFieldStyle( + "To *", + "To *") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: Colors + .black87, + ), + ), + initialValue: null, + ), + ), + ], + ); + }); + }), + ), + const SizedBox( + height: 12, + ), + //// total hours conducted + FormBuilderTextField( + validator: numericRequired, + name: "total_hours", + decoration: normalTextFieldStyle( + "Total Hours Conducted *", + "0"), + keyboardType: + TextInputType.number, + ), + const SizedBox( + height: 12, + ), + ////Address + StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + ////overseas textformfield + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: + normalTextFieldStyle( + "Overseas Address?", + ''), + name: 'overseas', + title: Text(overseas + ? "YES" + : "NO"), + ), + SizedBox( + height: overseas == true + ? 8 + : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + FormBuilderDropdown< + Region?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: (Region? + region) async { + if (selectedRegion != + region) { + setState( + () { + provinceCall = + true; + }); + selectedRegion = + region; + getProvinces(); + } + }, + initialValue: + null, + decoration: + normalTextFieldStyle( + "Region*", + "Region"), + name: 'region', + items: state.regions.map< + DropdownMenuItem< + Region>>((Region + region) { + return DropdownMenuItem< + Region>( + value: + region, + child: Text( + region + .description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors + .transparent, + inAsyncCall: + provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => value == null + ? 'required' + : null, + isExpanded: + true, + value: + selectedProvince, + onChanged: + (Province? + province) { + if (selectedProvince != + province) { + setState( + () { + cityCall = + true; + }); + selectedProvince = + province; + getCities(); + } + }, + items: provinces == + null + ? [] + : provinces!.map>((Province + province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province.description!), + )); + }).toList(), + decoration: normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors + .white, + inAsyncCall: + cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators.required( + errorText: + "This field is required"), + isExpanded: + true, + onChanged: + (CityMunicipality? + city) { + if (selectedMunicipality != + city) { + setState( + () { + barangayCall = + true; + }); + selectedMunicipality = + city; + getBarangays(); + } + }, + decoration: normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: + selectedMunicipality, + items: citymuns == + null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>((CityMunicipality + c) { + return DropdownMenuItem( + value: c, + child: Text(c.description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors + .white, + inAsyncCall: + barangayCall, + child: DropdownButtonFormField< + Barangay>( + isExpanded: + true, + onChanged: + (Barangay? + baragay) { + selectedBarangay = + baragay; + }, + decoration: normalTextFieldStyle( + "Barangay*", + "Barangay"), + value: + selectedBarangay, + items: barangays == + null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>((Barangay + barangay) { + return DropdownMenuItem( + value: barangay, + child: Text(barangay.description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: + FormBuilderDropdown< + Country>( + initialValue: + null, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + items: state + .countries + .map< + DropdownMenuItem< + Country>>((Country + country) { + return DropdownMenuItem< + Country>( + value: + country, + child: FittedBox( + child: Text( + country.name!))); + }).toList(), + name: 'country', + decoration: + normalTextFieldStyle( + "Country*", + "Country"), + onChanged: + (Country? + value) { + selectedCountry = + value; + }, + ), + ), + ), + ], + ); + }), + + ////Conducted By + StatefulBuilder( + builder: (context, setState) { + ////has sponsor switch + return Column( + children: [ + ////Add Conducted Agency============ + SizedBox( + child: SizedBox( + child: Column(children: [ + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 100, + focusNode: + conductedByFocusNode, + suggestions: state + .conductedBy + .map((Agency + agency) => + SearchFieldListItem( + agency + .name!, + item: + agency, + child: + ListTile( + title: + Text( + agency + .name!, + overflow: + TextOverflow.visible, + ), + subtitle: Text(agency.privateEntity == + true + ? "Private" + : agency.privateEntity == false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + " Conducted By *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons + .arrow_drop_down, + ), + onTap: () => + conductedByFocusNode + .unfocus(), + )), + ////SELETECTED + onSuggestionTap: + (agency) { + setState(() { + if (agency.item + ?.id != + null) { + selectedConductedByAgency = + Agency( + name: + null, + id: agency + .item! + .id); + } else { + selectedConductedByAgency = Agency( + id: null, + name: agency + .item! + .name); + } + + if (agency.item! + .privateEntity == + null) { + showConductedByAgencyCategory = + true; + showConductedByAgencyPrivateRadio = + true; + } else { + showConductedByAgencyCategory = + false; + showConductedByAgencyPrivateRadio = + false; + } + conductedByFocusNode + .unfocus(); + }); + }, + validator: (agency) { + if (agency! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ////conducter empty widget + emptyWidget: + EmptyWidget( + controller: + addConductedByController, + onpressed: + () { + setState( + () { + Agency newAgency = Agency( + id: + null, + name: addConductedByController + .text + .toUpperCase(), + category: + null, + privateEntity: + null); + state + .conductedBy + .insert( + 0, + newAgency); + + addConductedByController + .text = ""; + Navigator.pop( + context); + }); + }, + title: + "Add Conducted By Agency")), + SizedBox( + height: + showConductedByAgencyCategory + ? 12 + : 0, + ), + ////Sponsor Agency Category + SizedBox( + child: + showConductedByAgencyCategory + ? SearchField( + suggestionDirection: + SuggestionDirection + .up, + focusNode: + conductedByAgencyCategoryFocusNode, + itemHeight: + 70, + suggestions: state + .agencyCategory + .map((Category category) => SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text(category.name!), + subtitle: Text(category.industryClass!.name!), + ))) + .toList(), + emptyWidget: + Container( + height: + 100, + decoration: + box1(), + child: const Center( + child: + Text("No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState( + () { + selectedConductedByAgencyCategory = + agencyCategory.item; + selectedConductedByAgency = Agency( + id: selectedConductedByAgency + ?.id, + name: selectedConductedByAgency! + .name, + category: + selectedConductedByAgencyCategory, + privateEntity: + showConductedByAgencyPrivateRadio); + conductedByAgencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons + .arrow_drop_down), + onPressed: + () { + conductedByAgencyCategoryFocusNode + .unfocus(); + }, + )), + validator: + (value) { + if (value! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////Sponsor Agency Private Radio + SizedBox( + height: + showConductedByAgencyPrivateRadio + ? 12 + : 0), + SizedBox( + child: showConductedByAgencyPrivateRadio + ? FormBuilderSwitch( + initialValue: + conductedByCategoryIsPrivate, + title: Text( + conductedByCategoryIsPrivate + ? "YES" + : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: + (value) { + setState( + () { + conductedByCategoryIsPrivate = + value!; + selectedConductedByAgency = Agency( + category: selectedConductedByAgency + ?.category, + id: selectedConductedByAgency + ?.id, + name: selectedConductedByAgency! + .name, + privateEntity: + conductedByCategoryIsPrivate); + conductedByAgencyCategoryFocusNode + .unfocus(); + }); + }, + name: + 'sponsorAgencyPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + ]), + )), + ], + ); + }), + ]), + ) + : const SizedBox()), + const SizedBox( + height: 12, + ), + + ////Sponsor + StatefulBuilder(builder: (context, setState) { + ////has sponsor switch + return Column( + children: [ + FormBuilderSwitch( + initialValue: hasSponsor, + activeColor: second, + onChanged: (value) { + setState(() { + hasSponsor = value!; + }); + }, + decoration: normalTextFieldStyle( + "Has Sponsor?", ''), + name: 'sponsor', + title: Text(hasSponsor ? "YES" : "NO"), + ), + ////Add Sponsor Agency============ + SizedBox( + child: hasSponsor + ? SizedBox( + child: Column(children: [ + const SizedBox( + height: 12, + ), + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 110, + focusNode: + sponsorByFocusNode, + suggestions: state + .sponsorAgencies + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency + .name!, + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + " Sponsor Agency *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + sponsorByFocusNode + .unfocus(), + )), + ////SELETECTED + onSuggestionTap: (agency) { + setState(() { + if (agency.item?.id != + null) { + selectedSponsorAgency = + Agency( + name: null, + id: agency + .item! + .id); + } else { + selectedSponsorAgency = + Agency( + id: null, + name: agency + .item! + .name); + } + if (agency.item! + .privateEntity == + null) { + showSponsorCategoryAgency = + true; + showSponsorAgencyPrivateRadio = + true; + } else { + showSponsorCategoryAgency = + false; + showSponsorAgencyPrivateRadio = + false; + } + sponsorByFocusNode + .unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + ////sponsor empty widget + emptyWidget: EmptyWidget( + controller: + addSponsorAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addSponsorAgencyController + .text + .toUpperCase(), + category: null, + privateEntity: + null); + state + .sponsorAgencies + .insert(0, + newAgency); + + addSponsorAgencyController + .text = ""; + Navigator.pop( + context); + }); + }, + title: + "Add Sponsor Agency")), + SizedBox( + height: + showSponsorCategoryAgency + ? 12 + : 0, + ), + ////Sponsor Agency Category + SizedBox( + child: + showSponsorCategoryAgency + ? SearchField( + suggestionDirection: + SuggestionDirection + .up, + focusNode: + sponsorAgencyCategoryFocusNode, + itemHeight: 70, + suggestions: state + .agencyCategory + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: + Text(category.name!), + subtitle: + Text(category.industryClass!.name!), + ))) + .toList(), + emptyWidget: + Container( + height: 100, + decoration: + box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedSponsorAgencyCategory = + agencyCategory + .item; + selectedSponsorAgency = Agency( + id: selectedSponsorAgency + ?.id, + name: selectedSponsorAgency! + .name, + category: + selectedSponsorAgencyCategory, + privateEntity: + sponsorAgencyIsPrivate); + sponsorAgencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons + .arrow_drop_down), + onPressed: () { + sponsorAgencyCategoryFocusNode + .unfocus(); + }, + )), + validator: + (value) { + if (value! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////Sponsor Agency Private Radio + SizedBox( + height: + showSponsorAgencyPrivateRadio + ? 12 + : 0), + SizedBox( + child: + showSponsorAgencyPrivateRadio + ? FormBuilderSwitch( + initialValue: + sponsorAgencyIsPrivate, + title: Text( + sponsorAgencyIsPrivate + ? "YES" + : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: + (value) { + setState(() { + sponsorAgencyIsPrivate = + value!; + selectedSponsorAgency = Agency( + category: + selectedSponsorAgency + ?.category, + id: selectedSponsorAgency + ?.id, + name: selectedSponsorAgency! + .name, + privateEntity: + selectedSponsorAgency?.privateEntity); + sponsorAgencyCategoryFocusNode + .unfocus(); + }); + }, + + name: + 'sponsorAgencyPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + ]), + ) + : const SizedBox(), + ), + ], + ); + }), + + const SizedBox( + height: 12, + ), + FormBuilderTextField( + validator: numericRequired, + name: "total_hours_attended", + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle( + "Total Hours Attended *", + "Total Hours Attended *"), + ), + const SizedBox(height: 16,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + ConductedTraining? training; + Agency? sponsor; + Venue venue; + ////Address + if (overseas) { + venue = Venue( + id: null, + country: selectedCountry, + barangay: null, + category: null, + areaClass: null, + cityMunicipality: null); + } else { + venue = Venue( + id: null, + country: Country( + id: 175, + name: 'Philippines', + code: 'PH'), + barangay: selectedBarangay, + areaClass: null, + category: null, + cityMunicipality: selectedMunicipality); + } + if (showTrainingDetails) { + training = ConductedTraining( + locked: false, + id: selectedConductedTraining!.id, + venue: Venue( + country: selectedConductedTraining! + .venue!.country)); + } else { + training = ConductedTraining( + title: selectedTraining, + topic: selectedTopic, + id: null, + locked: false, + venue: venue, + toDate: + DateTime.parse(toDateController.text), + fromDate: DateTime.parse( + fromDateController.text), + totalHours: double.parse(formKey + .currentState!.value['total_hours']), + conductedBy: selectedConductedByAgency, + sessionsAttended: [], + learningDevelopmentType: + selectedLearningDevelopmentType); + } + if (hasSponsor) { + sponsor = selectedSponsorAgency; + } + LearningDevelopement learningDevelopement = + LearningDevelopement( + attachments: null, + sponsoredBy: sponsor, + conductedTraining: training, + totalHoursAttended: double.parse(formKey + .currentState! + .value['total_hours_attended'])); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + AddLearningAndDevelopment( + learningDevelopement: + learningDevelopement, + profileId: widget.profileId, + token: widget.token)); + } + }, + ), + ), + ], + ); + }), + )); + } + return const Center( + child: Text("ds"), + ); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + barangayCall = true; + getBarangays(); + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } + + Future getBarangays() async { + try { + List newBarangays = await LocationUtils.instance + .getBarangay(code: selectedMunicipality!.code.toString()); + barangays = newBarangays; + setState(() { + selectedBarangay = newBarangays[0]; + barangayCall = false; + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } +} diff --git a/lib/screens/profile/components/learning_development/display_details.dart b/lib/screens/profile/components/learning_development/display_details.dart new file mode 100644 index 0000000..b946a1d --- /dev/null +++ b/lib/screens/profile/components/learning_development/display_details.dart @@ -0,0 +1,150 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; + +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; + +class TrainingDetails extends StatelessWidget { + final String trainingTitle; + final double totalHours; + final String trainingTopic; + final String toDate; + final String fromDate; + final String conductedBy; + + const TrainingDetails({super.key, required this.trainingTitle, required this.totalHours, required this.trainingTopic, required this.toDate, required this.fromDate, required this.conductedBy}); + + @override + Widget build(BuildContext context) { + return SizedBox( + child: Column( + children: [ + const SizedBox( + height: 12, + ), + SizedBox( + child: Row( + children: [ + Flexible( + child: TextFormField( + enabled: false, + initialValue: trainingTitle, + decoration: + normalTextFieldStyle("", "") + .copyWith( + labelText: "Type", + fillColor: Colors + .grey.shade200, + filled: true)), + ), + const SizedBox( + width: 6, + ), + Flexible( + child: TextFormField( + enabled: false, + initialValue: totalHours + .toString(), + decoration: normalTextFieldStyle( + "", "") + .copyWith( + labelText: + "Total Hours Conducted", + fillColor: Colors + .grey.shade200, + filled: true))), + ], + ), + ), + const SizedBox( + height: 12, + ), + TextFormField( + enabled: false, + maxLines: 3, + initialValue: + trainingTopic, + decoration: normalTextFieldStyle("", "") + .copyWith( + labelText: "Topic", + fillColor: Colors.grey.shade200, + filled: true)), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + enabled: false, + firstDate: DateTime(1970), + lastDate: DateTime(2100), + initialValue:fromDate, + use24HourFormat: false, + icon: const Icon( + Icons.date_range), + timeHintText: + "Date of Examination/Conferment", + decoration: + normalTextFieldStyle( + "From", "From") + .copyWith( + fillColor: Colors + .grey.shade200, + filled: true, + prefixIcon: + const Icon( + Icons.date_range, + color: Colors + .black87, + )), + )), + const SizedBox( + width: 6, + ), + //// TO DATE + Flexible( + flex: 1, + child: DateTimePicker( + enabled: false, + initialValue:toDate, + firstDate: DateTime(1970), + lastDate: DateTime(2100), + decoration: normalTextFieldStyle( + "To", "To") + .copyWith( + fillColor: Colors.grey.shade200, + filled: true, + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + ), + ), + ), + ), + ], + ), + ), + const SizedBox( + height: 12, + ), + TextFormField( + enabled: false, + maxLines: 3, + initialValue:conductedBy, + decoration: normalTextFieldStyle("", "") + .copyWith( + labelText: "Conducted By", + fillColor: Colors.grey.shade200, + filled: true)), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/profile/components/learning_development/edit_modal.dart b/lib/screens/profile/components/learning_development/edit_modal.dart new file mode 100644 index 0000000..6937150 --- /dev/null +++ b/lib/screens/profile/components/learning_development/edit_modal.dart @@ -0,0 +1,1700 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import 'package:unit2/model/profile/learning_development.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/utils/validators.dart'; +import '../../../../model/location/barangay.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../shared/add_for_empty_search.dart'; + +class EditLearningAndDevelopmentScreen extends StatefulWidget { + final int profileId; + final String token; + const EditLearningAndDevelopmentScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditLearningAndDevelopmentScreenState(); +} + +class _EditLearningAndDevelopmentScreenState + extends State { + final formKey = GlobalKey(); + + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + + bool isPrivate = false; + + bool showSponsorByAgency = false; + bool showOtherInputs = false; + bool showTrainingDetails = false; + bool hasSponsor = false; + + LearningDevelopmentType? selectedLearningDevelopmentType; + final fromDateController = TextEditingController(); + final toDateController = TextEditingController(); +////Training + bool show = true; + final addTrainingController = TextEditingController(); + ConductedTraining? selectedConductedTraining; + LearningDevelopmentType? selectedTraining; + +////Topic + final topicFocusNode = FocusNode(); + final addTopicController = TextEditingController(); + LearningDevelopmentType? selectedTopic; + final currentTopicController = TextEditingController(); + +////address + Barangay? selectedBarangay; + Country? selectedCountry; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + List? provinces; + List? citymuns; + List? barangays; + + ////Sponsor Agency Searchfield + Agency? selectedSponsorAgency; + Category? selectedSponsorAgencyCategory; + bool showSponsorCategoryAgency = false; + bool showSponsorAgencyPrivateRadio = false; + bool sponsorAgencyIsPrivate = false; + final addSponsorAgencyController = TextEditingController(); + final sponsorByFocusNode = FocusNode(); + final sponsorAgencyCategoryFocusNode = FocusNode(); + final selectedSponsorAgencyController = TextEditingController(); + +////Conducted By + Agency? selectedConductedByAgency; + Category? selectedConductedByAgencyCategory; + bool showConductedByAgencyPrivateRadio = false; + final conductedByFocusNode = FocusNode(); + final conductedByAgencyCategoryFocusNode = FocusNode(); + final addConductedByController = TextEditingController(); + bool showConductedByAgencyCategory = false; + bool conductedByCategoryIsPrivate = false; + final selectedConductedByController = TextEditingController(); + + final selectedTrainingController = TextEditingController(); + DateTime? from; + DateTime? to; + @override + void dispose() { + fromDateController.dispose(); + toDateController.dispose(); + addTrainingController.dispose(); + topicFocusNode.dispose(); + addTopicController.dispose(); + currentTopicController.dispose(); + addSponsorAgencyController.dispose(); + sponsorByFocusNode.dispose(); + sponsorAgencyCategoryFocusNode.dispose(); + selectedSponsorAgencyController.dispose(); + conductedByFocusNode.dispose(); + conductedByAgencyCategoryFocusNode.dispose(); + addConductedByController.dispose(); + selectedConductedByController.dispose(); + + selectedTrainingController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is LearningDevelopmentUpdatingState) { + selectedTrainingController.text = + state.learningDevelopement.conductedTraining!.title!.title!; + selectedTraining = LearningDevelopmentType( + id: state.learningDevelopement.conductedTraining!.title!.id, + title: selectedTrainingController.text); + selectedConductedByAgency = Agency( + id: state.learningDevelopement.conductedTraining!.conductedBy!.id, + name: null); + selectedConductedByController.text = + state.learningDevelopement.conductedTraining!.conductedBy!.name!; + selectedLearningDevelopmentType = state.types.firstWhere((element) => + element.id == + state.learningDevelopement.conductedTraining! + .learningDevelopmentType!.id); + currentTopicController.text = + state.learningDevelopement.conductedTraining!.topic!.title!; + selectedTopic = LearningDevelopmentType( + id: state.learningDevelopement.conductedTraining!.topic!.id, + title: null); + fromDateController.text = + state.learningDevelopement.conductedTraining!.fromDate.toString(); + toDateController.text = + state.learningDevelopement.conductedTraining!.toDate.toString(); + overseas = state.overseas; + if (!overseas) { + selectedRegion = state.currentRegion; + provinces = state.provinces; + selectedProvince = state.currentProvince; + citymuns = state.cities; + selectedMunicipality = state.currentCity; + barangays = state.barangay; + selectedBarangay = state.currentBarangay; + } else { + selectedCountry = state.currentCountry; + } + hasSponsor = state.learningDevelopement.sponsoredBy != null; + if (hasSponsor) { + selectedSponsorAgency = Agency( + id: state.learningDevelopement.sponsoredBy!.id, name: null); + selectedSponsorAgencyController.text = + state.learningDevelopement.sponsoredBy!.name!; + } + bool enabled; + if (state.learningDevelopement.conductedTraining?.locked != null && + state.learningDevelopement.conductedTraining!.locked == true) { + enabled = false; + } else { + enabled = true; + } + from = state.learningDevelopement.conductedTraining?.fromDate; + to = state.learningDevelopement.conductedTraining?.toDate; + return FormBuilder( + key: formKey, + child: Padding( + padding: const EdgeInsets.all(24), + child: ListView( + children: [ + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + const SizedBox( + height: 10, + ), + SizedBox( + ////Training selected Textfield + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + onChanged: (value) { + selectedTraining = + LearningDevelopmentType( + id: null, + title: selectedTrainingController + .text); + }, + enabled: enabled, + maxLines: 5, + controller: selectedTrainingController, + name: "", + decoration: normalTextFieldStyle("", "") + .copyWith( + labelText: "Training", + filled: !enabled, + fillColor: Colors.grey.shade300), + )), + SizedBox( + child: SizedBox( + child: Column(children: [ + const SizedBox( + height: 12, + ), + ////learning development type + FormBuilderDropdown< + LearningDevelopmentType>( + enabled: enabled, + name: "types", + decoration: normalTextFieldStyle( + "Learning Development Type *", + "") + .copyWith( + filled: !enabled, + fillColor: + Colors.grey.shade300), + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.types + .map((e) => DropdownMenuItem< + LearningDevelopmentType>( + value: e, + child: Text(e.title!))) + .toList(), + onChanged: (value) { + selectedLearningDevelopmentType = + value; + }, + initialValue: + selectedLearningDevelopmentType, + ), + + //// learning development topics + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context, setState) { + return SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + + enabled: enabled, + controller: currentTopicController, + focusNode: topicFocusNode, + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: state.topics + .map((LearningDevelopmentType + topic) => + SearchFieldListItem( + topic.title!, + item: topic, + child: Padding( + padding: + const EdgeInsets + .symmetric( + horizontal: + 10), + child: ListTile( + title: Text( + topic.title!, + softWrap: true, + ), + )))) + .toList(), + + searchInputDecoration: + normalTextFieldStyle("Topic *", + "") + .copyWith( + filled: !enabled, + fillColor: + Colors.grey.shade300, + suffixIcon: IconButton( + icon: const Icon(Icons + .arrow_drop_down), + onPressed: () { + topicFocusNode + .unfocus(); + }, + )), + onSuggestionTap: (topic) { + if (topic.item?.id != null) { + selectedTopic = + LearningDevelopmentType( + id: topic.item!.id, + title: null); + } else { + selectedTopic = + LearningDevelopmentType( + id: null, + title: topic.item!.title); + } + setState(() { + topicFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Topic", + controller: addTopicController, + onpressed: () { + setState(() { + LearningDevelopmentType + newTopic = + LearningDevelopmentType( + id: null, + title: + addTopicController + .text + .toUpperCase()); + state.topics + .insert(0, newTopic); + topicFocusNode.unfocus(); + addTopicController.text = ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + use24HourFormat: false, + icon: const Icon( + Icons.date_range), + controller: + fromDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + selectableDayPredicate: + (date) { + if (to != null && + to!.microsecondsSinceEpoch < + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + from = + DateTime.tryParse(value); + }); + }, + initialDate: to??=DateTime.now(), + timeHintText: + "Date of Examination/Conferment", + decoration: + normalTextFieldStyle( + "From *", "From *") + .copyWith( + filled: !enabled, + fillColor: Colors + .grey + .shade300, + prefixIcon: + const Icon( + Icons + .date_range, + color: Colors + .black87, + )), + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: toDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + decoration: + normalTextFieldStyle( + "To *", "To *") + .copyWith( + filled: !enabled, + fillColor: + Colors.grey.shade300, + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + ), + ), + selectableDayPredicate: (date) { + if (from != null && + from!.microsecondsSinceEpoch > + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + to = DateTime.tryParse(value); + }); + }, + initialDate: from??=DateTime.now() + ), + ), + ], + ), + ), + const SizedBox( + height: 12, + ), + //// total hours conducted + FormBuilderTextField( + initialValue: state.learningDevelopement + .conductedTraining!.totalHours + .toString(), + validator: numericRequired, + name: "total_hours", + decoration: normalTextFieldStyle( + "Total Hours Conducted *", + "0", + ).copyWith( + filled: !enabled, + fillColor: Colors.grey.shade300), + keyboardType: TextInputType.number, + ), + const SizedBox( + height: 12, + ), + ////Address + + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: + Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 8 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + FormBuilderDropdown< + Region?>( + enabled: !enabled + ? overseas + : true, + name: "region", + isExpanded: true, + initialValue: + selectedRegion, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: (Region? + region) async { + if (selectedRegion != + region) { + setState(() { + provinceCall = + true; + }); + selectedRegion = + region; + //// GET PROVINCES + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: selectedRegion! + .code + .toString()); + } catch (e) { + context + .read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedProvince = + provinces![0]; + setState(() { + provinceCall = + false; + cityCall = true; + }); + //// GET CITIES + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = + false; + barangayCall = + true; + }); + //// GET BARANGAY + try { + barangays = await LocationUtils + .instance + .getBarangay( + code: selectedMunicipality! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = + false; + }); + ////GET CITY MUNICIPALITY + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = + false; + barangayCall = + true; + }); + //// GET BARANGAYS + try { + barangays = await LocationUtils + .instance + .getBarangay( + code: selectedMunicipality! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = + false; + }); + } + }, + decoration: normalTextFieldStyle( + "Region*", + "Region") + .copyWith( + filled: !enabled + ? !overseas + : false, + fillColor: Colors + .grey + .shade300), + items: state.regions.map< + DropdownMenuItem< + Region>>((Region + region) { + return DropdownMenuItem< + Region>( + value: region, + child: Text(region + .description!)); + }).toList(), + ), + const SizedBox( + height: 8, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors + .transparent, + inAsyncCall: + provinceCall, + child: + DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => value == null + ? 'required' + : null, + isExpanded: + true, + value: + selectedProvince, + onChanged: + (Province? + province) async { + if (selectedProvince != + province) { + selectedProvince = + province; + setState( + () { + cityCall = + true; + }); + + //// GET CITIES + try { + citymuns = await LocationUtils + .instance + .getCities(code: selectedProvince!.code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read() + .add(CallErrorState(message: e.toString())); + } + selectedMunicipality = + citymuns![0]; + setState( + () { + cityCall = + false; + barangayCall = + true; + }); + //// GET BARANGAY + try { + barangays = await LocationUtils + .instance + .getBarangay(code: selectedMunicipality!.code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read() + .add(CallErrorState(message: e.toString())); + } + selectedBarangay = + barangays![0]; + setState( + () { + barangayCall = + false; + }); + } + }, + items: provinces == + null + ? [] + : provinces!.map>((Province + province) { + return DropdownMenuItem( + enabled: !enabled ? overseas : true, + value: province, + child: FittedBox( + child: Text(province.description!), + )); + }).toList(), + decoration: normalTextFieldStyle("Province*", "Province").copyWith( + filled: !enabled + ? !overseas + : false, + fillColor: Colors + .grey + .shade300)), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors.white, + inAsyncCall: + cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? + city) async { + if (selectedMunicipality != + city) { + setState(() { + barangayCall = + true; + }); + selectedMunicipality = + city; + + //// GET BARANGAYS + try { + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality!.code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + LearningDevelopmentBloc>() + .add(CallErrorState( + message: + e.toString())); + } + selectedBarangay = + barangays![ + 0]; + setState(() { + barangayCall = + false; + }); + } + }, + decoration: normalTextFieldStyle( + "Municipality*", + "Municipality") + .copyWith( + filled: !enabled + ? !overseas + : false, + fillColor: Colors + .grey + .shade300), + value: + selectedMunicipality, + items: citymuns == + null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality + c) { + return DropdownMenuItem( + enabled: !enabled + ? overseas + : true, + value: + c, + child: + Text(c.description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: + ModalProgressHUD( + color: Colors.white, + inAsyncCall: + barangayCall, + child: + DropdownButtonFormField< + Barangay>( + isExpanded: true, + onChanged: + (Barangay? + baragay) { + selectedBarangay = + baragay; + }, + decoration: normalTextFieldStyle( + "Barangay*", + "Barangay") + .copyWith( + filled: !enabled + ? !overseas + : false, + fillColor: Colors + .grey + .shade300), + value: + selectedBarangay, + items: barangays == + null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>((Barangay + barangay) { + return DropdownMenuItem( + enabled: !enabled + ? overseas + : true, + value: + barangay, + child: + Text(barangay.description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: + FormBuilderDropdown< + Country>( + enabled: overseas, + initialValue: + selectedCountry + ?.id == + 175 + ? null + : selectedCountry, + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + items: state.countries.map< + DropdownMenuItem< + Country>>( + (Country country) { + return DropdownMenuItem< + Country>( + value: country, + child: FittedBox( + child: Text( + country + .name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", + "Country") + .copyWith( + filled: + !overseas, + fillColor: Colors + .grey + .shade300), + onChanged: + (Country? value) { + selectedCountry = + value; + }, + ), + ), + ), + ], + ); + }), + + ////Conducted By + StatefulBuilder( + builder: (context, setState) { + ////has sponsor switch + return Column( + children: [ + ////Add Conducted Agency============ + SizedBox( + child: SizedBox( + child: Column(children: [ + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + enabled: enabled, + controller: + selectedConductedByController, + itemHeight: 100, + focusNode: + conductedByFocusNode, + suggestions: state + .conductedBy + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency + .name!, + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + " Conducted By *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: + const Icon( + Icons + .arrow_drop_down, + ), + onTap: () => + conductedByFocusNode + .unfocus(), + ), + filled: + !enabled, + fillColor: Colors + .grey + .shade300), + ////SELETECTED + onSuggestionTap: (agency) { + setState(() { + if (agency.item?.id != + null) { + selectedConductedByAgency = + Agency( + name: null, + id: agency + .item! + .id); + } else { + selectedConductedByAgency = + Agency( + id: null, + name: agency + .item! + .name); + } + + if (agency.item! + .privateEntity == + null) { + showConductedByAgencyCategory = + true; + showConductedByAgencyPrivateRadio = + true; + } else { + showConductedByAgencyCategory = + false; + showConductedByAgencyPrivateRadio = + false; + } + conductedByFocusNode + .unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + ////conducter empty widget + emptyWidget: EmptyWidget( + controller: + addConductedByController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addConductedByController + .text + .toUpperCase(), + category: null, + privateEntity: + null); + state.conductedBy + .insert(0, + newAgency); + + addConductedByController + .text = ""; + Navigator.pop( + context); + }); + }, + title: + "Add Conducted By Agency")), + SizedBox( + height: + showConductedByAgencyCategory + ? 12 + : 0, + ), + ////Conducted By Agency Category + SizedBox( + child: + showConductedByAgencyCategory + ? SearchField( + focusNode: + conductedByAgencyCategoryFocusNode, + itemHeight: 70, + suggestions: state + .agencyCategory + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: + Text(category.name!), + subtitle: + Text(category.industryClass!.name!), + ))) + .toList(), + emptyWidget: + Container( + height: 100, + decoration: + box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedConductedByAgencyCategory = + agencyCategory + .item; + selectedConductedByAgency = Agency( + id: selectedConductedByAgency + ?.id, + name: selectedConductedByAgency! + .name, + category: + selectedConductedByAgencyCategory, + privateEntity: + showConductedByAgencyPrivateRadio); + conductedByAgencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons + .arrow_drop_down), + onPressed: () { + conductedByAgencyCategoryFocusNode + .unfocus(); + }, + )), + validator: + (value) { + if (value! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////Sponsor Agency Private Radio + SizedBox( + height: + showConductedByAgencyPrivateRadio + ? 12 + : 0), + SizedBox( + child: + showConductedByAgencyPrivateRadio + ? FormBuilderSwitch( + initialValue: + conductedByCategoryIsPrivate, + title: Text( + conductedByCategoryIsPrivate + ? "YES" + : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: + (value) { + setState(() { + conductedByCategoryIsPrivate = + value!; + selectedConductedByAgency = Agency( + category: + selectedConductedByAgency + ?.category, + id: selectedConductedByAgency + ?.id, + name: selectedConductedByAgency! + .name, + privateEntity: + conductedByCategoryIsPrivate); + conductedByAgencyCategoryFocusNode + .unfocus(); + }); + }, + name: + 'sponsorAgencyPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + ]), + )), + ], + ); + }), + ]), + )), + const SizedBox( + height: 12, + ), + + ////Sponsor + StatefulBuilder(builder: (context, setState) { + ////has sponsor switch + return Column( + children: [ + FormBuilderSwitch( + initialValue: hasSponsor, + activeColor: second, + onChanged: (value) { + setState(() { + hasSponsor = value!; + }); + }, + decoration: normalTextFieldStyle( + "Has Sponsor?", ''), + name: 'sponsor', + title: + Text(hasSponsor ? "YES" : "NO"), + ), + ////Add Sponsor Agency============ + SizedBox( + child: hasSponsor + ? SizedBox( + child: Column(children: [ + const SizedBox( + height: 12, + ), + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: + selectedSponsorAgencyController, + itemHeight: 70, + focusNode: + sponsorByFocusNode, + suggestions: state + .sponsorAgencies + .map((Agency + agency) => + SearchFieldListItem( + agency + .name!, + item: + agency, + child: + ListTile( + title: + Text( + agency + .name!, + overflow: + TextOverflow.ellipsis, + ), + subtitle: Text(agency.privateEntity == + true + ? "Private" + : agency.privateEntity == false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle( + " Sponsor Agency *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons + .arrow_drop_down, + ), + onTap: () => + sponsorByFocusNode + .unfocus(), + )), + ////SELETECTED + onSuggestionTap: + (agency) { + setState(() { + if (agency + .item?.id != + null) { + selectedSponsorAgency = + Agency( + name: + null, + id: agency + .item! + .id); + } else { + selectedSponsorAgency = + Agency( + id: null, + name: agency + .item! + .name); + } + if (agency.item! + .privateEntity == + null) { + showSponsorCategoryAgency = + true; + showSponsorAgencyPrivateRadio = + true; + } else { + showSponsorCategoryAgency = + false; + showSponsorAgencyPrivateRadio = + false; + } + sponsorByFocusNode + .unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + ////sponsor empty widget + emptyWidget: + EmptyWidget( + controller: + addSponsorAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: + null, + name: addSponsorAgencyController + .text + .toUpperCase(), + category: + null, + privateEntity: + null); + state + .sponsorAgencies + .insert( + 0, + newAgency); + + addSponsorAgencyController + .text = ""; + Navigator.pop( + context); + }); + }, + title: + "Add Sponsor Agency")), + SizedBox( + height: + showSponsorCategoryAgency + ? 12 + : 0, + ), + ////Sponsor Agency Category + SizedBox( + child: + showSponsorCategoryAgency + ? SearchField( + suggestionDirection: + SuggestionDirection + .up, + focusNode: + sponsorAgencyCategoryFocusNode, + itemHeight: + 70, + suggestions: state + .agencyCategory + .map((Category category) => SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: + Text(category.name!), + subtitle: + Text(category.industryClass!.name!), + ))) + .toList(), + emptyWidget: + Container( + height: 100, + decoration: + box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: + (agencyCategory) { + setState( + () { + selectedSponsorAgencyCategory = + agencyCategory + .item; + selectedSponsorAgency = Agency( + id: selectedSponsorAgency + ?.id, + name: selectedSponsorAgency! + .name, + category: + selectedSponsorAgencyCategory, + privateEntity: + sponsorAgencyIsPrivate); + sponsorAgencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + IconButton( + icon: const Icon( + Icons + .arrow_drop_down), + onPressed: + () { + sponsorAgencyCategoryFocusNode + .unfocus(); + }, + )), + validator: + (value) { + if (value! + .isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////Sponsor Agency Private Radio + SizedBox( + height: + showSponsorAgencyPrivateRadio + ? 12 + : 0), + SizedBox( + child: showSponsorAgencyPrivateRadio + ? FormBuilderSwitch( + initialValue: + sponsorAgencyIsPrivate, + title: Text( + sponsorAgencyIsPrivate + ? "YES" + : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: + (value) { + setState(() { + sponsorAgencyIsPrivate = + value!; + selectedSponsorAgency = Agency( + category: + selectedSponsorAgency + ?.category, + id: selectedSponsorAgency + ?.id, + name: selectedSponsorAgency! + .name, + privateEntity: + selectedSponsorAgency?.privateEntity); + sponsorAgencyCategoryFocusNode + .unfocus(); + }); + }, + + name: + 'sponsorAgencyPrivate', + validator: + FormBuilderValidators + .required(), + ) + : const SizedBox()), + ]), + ) + : const SizedBox(), + ), + ], + ); + }), + const SizedBox( + height: 12, + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + initialValue: state + .learningDevelopement.totalHoursAttended + .toString(), + validator: numericRequired, + name: "total_hours_attended", + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle( + "Total Hours Attended *", + "Total Hours Attended *"), + ), + ], + ); + }), + const SizedBox(height: 16,), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + ConductedTraining? training; + Agency? sponsor; + Venue venue; + ////Address + if (overseas) { + venue = Venue( + id: state.learningDevelopement + .conductedTraining!.venue!.id, + country: selectedCountry, + barangay: null, + category: null, + areaClass: null, + cityMunicipality: null); + } else { + venue = Venue( + id: state.learningDevelopement + .conductedTraining!.venue!.id, + country: Country( + id: 175, + name: 'Philippines', + code: 'PH'), + barangay: selectedBarangay, + areaClass: null, + category: null, + cityMunicipality: selectedMunicipality); + } + + training = ConductedTraining( + title: selectedTraining, + topic: selectedTopic, + id: state.learningDevelopement + .conductedTraining!.id, + locked: state.learningDevelopement + .conductedTraining?.locked, + venue: venue, + toDate: DateTime.parse(toDateController.text), + fromDate: + DateTime.parse(fromDateController.text), + totalHours: double.parse(formKey + .currentState!.value['total_hours']), + conductedBy: selectedConductedByAgency, + sessionsAttended: [], + learningDevelopmentType: + selectedLearningDevelopmentType); + + if (hasSponsor) { + sponsor = selectedSponsorAgency; + } + LearningDevelopement learningDevelopement = + LearningDevelopement( + attachments: null, + sponsoredBy: sponsor, + conductedTraining: training, + totalHoursAttended: double.parse(formKey + .currentState! + .value['total_hours_attended'])); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + UpdateLearningDevelopment( + learningDevelopement: + learningDevelopement, + profileId: widget.profileId, + token: widget.token)); + } + }, + ), + ) + ], + ), + )); + } + return const Center( + child: Text("ds"), + ); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + barangayCall = true; + getBarangays(); + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } + + Future getBarangays() async { + try { + List newBarangays = await LocationUtils.instance + .getBarangay(code: selectedMunicipality!.code.toString()); + barangays = newBarangays; + setState(() { + selectedBarangay = newBarangays[0]; + barangayCall = false; + }); + } catch (e) { + context + .read() + .add(CallErrorState(message: e.toString())); + } + } +} diff --git a/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart b/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart new file mode 100644 index 0000000..e86086a --- /dev/null +++ b/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart @@ -0,0 +1,107 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/url_launcher_file_downloader.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class LearningDevelopmentViewAttachment extends StatefulWidget { + const LearningDevelopmentViewAttachment({super.key}); + + @override + State createState() => + _LearningDevelopmentViewAttachmentState(); +} + +class _LearningDevelopmentViewAttachmentState + extends State { + @override + Widget build(BuildContext context) { + String? fileUrl; + String? filename; + + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () async { + await launchInBrowser(fileUrl!); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: context.watch().state is LearningAndDevelopmentAttachmentViewState ? [ + IconButton(onPressed: () { + context.read().add(ShareAttachment(fileName: filename!, source: fileUrl!)); + }, icon: const Icon(Icons.share)), + ]:[] + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: + BlocConsumer( + builder: (context, state) { + if (state is LearningAndDevelopmentAttachmentViewState) { + fileUrl = state.fileUrl; + filename = state.filename; + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' + ? true + : false; + return SizedBox( + child: isPDF + ? SfPdfViewer.network( + + state.fileUrl, + onDocumentLoadFailed: (details) { + Center( + child: Text(details.description), + ); + }, + ) + : Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator( + color: primary, + )); + }, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + return Container(); + }, + listener: (context, state) { + + if (state is LearningDevelopmentLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is LearningAndDevelopmentAttachmentViewState || + state is LearningDevelopmentErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + ), + )); + } +} diff --git a/lib/screens/profile/components/learning_development/search_field_widget.dart b/lib/screens/profile/components/learning_development/search_field_widget.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/screens/profile/components/learning_development/training_details.dart b/lib/screens/profile/components/learning_development/training_details.dart new file mode 100644 index 0000000..4b216ef --- /dev/null +++ b/lib/screens/profile/components/learning_development/training_details.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:intl/intl.dart'; + +import '../../../../model/profile/learning_development.dart'; + +class TrainingDisplayDetails extends StatelessWidget { + final ConductedTraining e; + final Function() notWhatYourLookingFor; + const TrainingDisplayDetails({super.key, required this.e, required this.notWhatYourLookingFor}); + + @override + Widget build(BuildContext context) { + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + return Card( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + e.title!.title!.toUpperCase(), + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 6, + ), + Text( + "CONDUCTED BY:", + style: + Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 8), + ), + Text(e.conductedBy!.name!, style: const TextStyle(fontSize: 12)), + const SizedBox( + height: 6, + ), + Row( + children: [ + Flexible( + child: Text( + dteFormat2.format(e.fromDate!), + style: Theme.of(context).textTheme.labelSmall, + )), + const Text(" - "), + Flexible( + child: Text( + dteFormat2.format(e.toDate!), + style: Theme.of(context).textTheme.labelSmall, + )) + ], + ), + Text("Total (hours): ${e.totalHours}", + style: Theme.of(context).textTheme.labelSmall), + Align( + alignment: Alignment.centerRight, + child: GestureDetector( + onTap: notWhatYourLookingFor, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Text( + "NOT WHAT LOOKING FOR?", + style: TextStyle(fontSize: 10, color: Colors.black), + ), + ), + )), + ], + ), + ), + ); + } +} diff --git a/lib/screens/profile/components/loading_screen.dart b/lib/screens/profile/components/loading_screen.dart new file mode 100644 index 0000000..fbb1b21 --- /dev/null +++ b/lib/screens/profile/components/loading_screen.dart @@ -0,0 +1,161 @@ +import 'package:expandable_group/expandable_group_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttericon/brandico_icons.dart'; +import 'package:fluttericon/elusive_icons.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttericon/modern_pictograms_icons.dart'; +import 'package:unit2/screens/profile/components/main_menu.dart'; +import 'package:unit2/screens/profile/components/submenu.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import '../../../theme-data.dart/colors.dart'; + +class LoadingScreen extends StatelessWidget { + const LoadingScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Container( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 12), + child: ListView( + children: [ + const Text( + "View and Update your Profile Information", + textAlign: TextAlign.center, + ), + ExpandableGroup( + collapsedIcon: const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + Elusive.address_book, + color: primary, + ), + title: Text( + "Basic Information", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu(Icons.person, "Primary", () {}), + subMenu(Icons.home, "Home Addresses", () {}), + subMenu(Icons.contact_mail, "Identifications", () {}), + subMenu(Icons.contact_phone, "Contact Info", () {}), + subMenu(Icons.flag, "Citizenships", () {}), + ]), + const Divider(), + MainMenu( + icon: Elusive.group, + title: "Family", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.graduation_cap, + title: "Education", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: Icons.stars, + title: "Eligibility", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.shopping_bag, + title: "Work History", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.walking, + title: "Voluntary Work & Civic Services", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: Elusive.lightbulb, + title: "Learning & Development", + onTap: () {}, + ), + const Divider(), + MainMenu( + icon: Brandico.codepen, + title: "Personal References", + onTap: () {}, + ), + ExpandableGroup( + collapsedIcon: const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + Icons.info, + color: primary, + ), + title: Text( + "Other Information", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu(Icons.fitness_center, "Skills & Hobbies", () {}), + subMenu(FontAwesome5.certificate, + "Organization Memberships", () {}), + subMenu( + Entypo.doc_text, "Non-Academic Recognitions", () {}), + ]), + ExpandableGroup( + collapsedIcon: const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + FontAwesome5.laptop_house, + color: primary, + ), + title: Text( + "Assets", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu(ModernPictograms.home, "Real Property Tax", () {}), + ]), + ], + ), + ), + Container( + width: screenWidth, + height: screenHeight, + color: Colors.white70, + ), + Center( + child: Container( + height: 120, + width: 120, + decoration: const BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: const [ + SpinKitFadingCircle(size: 42, color: Colors.white), + SizedBox( + height: 12, + ), + Text( + "Please wait..", + style: TextStyle(color: Colors.white), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/screens/profile/components/main_menu.dart b/lib/screens/profile/components/main_menu.dart new file mode 100644 index 0000000..cdc5c26 --- /dev/null +++ b/lib/screens/profile/components/main_menu.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class MainMenu extends StatelessWidget { + final IconData icon; + final String title; + final Function() onTap; + const MainMenu({ + required this.icon, + required this.title, + required this.onTap, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Icon( + icon, + color: primary, + ), + title: Text( + title, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + trailing: const Icon(Icons.keyboard_arrow_right), + onTap: onTap, + ); + } +} diff --git a/lib/screens/profile/components/other_information/non_academic/add_modal.dart b/lib/screens/profile/components/other_information/non_academic/add_modal.dart new file mode 100644 index 0000000..163b5de --- /dev/null +++ b/lib/screens/profile/components/other_information/non_academic/add_modal.dart @@ -0,0 +1,426 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/other_information/non_acedimic_recognition.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/formatters.dart'; +import 'package:unit2/utils/global.dart'; + +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../utils/text_container.dart'; + +class AddNonAcademicRecognitionScreen extends StatefulWidget { + const AddNonAcademicRecognitionScreen({super.key}); + + @override + State createState() => + _AddNonAcademicRecognitionScreenState(); +} + +class _AddNonAcademicRecognitionScreenState + extends State { + bool showAgencyCategory = false; + final agencyFocusNode = FocusNode(); + + final agencyCategoryFocusNode = FocusNode(); + final addAgencyController = TextEditingController(); + Agency? selectedAgency; + Category? selectedCategory; + Agency? newAgency; + bool showIsPrivateRadio = false; + bool? isPrivate = false; + NonAcademicRecognition? nonAcademicRecognition; + final _formKey = GlobalKey(); + int? profileId; + String? token; + @override + void dispose() { + agencyFocusNode.dispose(); + agencyCategoryFocusNode.dispose(); + addAgencyController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocBuilder( + builder: (context, state) { + if (state is AddNonAcademeRecognitionState) { + return SizedBox( + height: blockSizeVertical * 90, + child: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 32, horizontal: 24), + child: Column( + children: [ + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: 'title', + decoration: normalTextFieldStyle( + "Recognition / Award Title *", + "Recognition / Award Title"), + validator: + FormBuilderValidators.required( + errorText: + "this field is required"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context, setState) { + //// AGENCY SEARCHFIELD + return Column( + children: [ + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + itemHeight: 100, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name! + .toUpperCase(), + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + focusNode: agencyFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Agency *", "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyFocusNode.unfocus(), + )), + ////agency suggestion tap + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + agencyFocusNode.unfocus(); + if (selectedAgency + ?.category == + null) { + showAgencyCategory = true; + showIsPrivateRadio = true; + } else { + showAgencyCategory = false; + showIsPrivateRadio = false; + } + }); + }, + emptyWidget: Container( + decoration: box1(), + height: 100, + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + const SizedBox( + height: 20, + ), + const Text( + "No result found..."), + const SizedBox( + height: 10, + ), + TextButton( + //// Add agency onpressed + onPressed: () { + showDialog( + context: + context, + builder: + (BuildContext + context) { + return AlertDialog( + title: const Text( + "Add Agency?"), + content: + SizedBox( + height: + 130, + child: + Column( + children: [ + TextFormField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: + addAgencyController, + decoration: + normalTextFieldStyle("", ""), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + //// onpressed + onPressed: () { + setState(() { + newAgency = Agency(id: null, name: addAgencyController.text.toUpperCase(), category: null, privateEntity: null); + state.agencies.insert(0, newAgency!); + addAgencyController.clear(); + Navigator.pop(context); + }); + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }, + child: const Text( + "Add Agency")) + ]), + ), + ), + const SizedBox( + height: 8, + ), + SizedBox( + child: showAgencyCategory + ? SearchField( + focusNode: + agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state + .agencyCategories + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text( + category + .name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + ////agency controller suggestion tap + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedCategory = + agencyCategory + .item; + + agencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyCategoryFocusNode + .unfocus(), + )), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ) + : const SizedBox(), + ), + + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderRadioGroup( + decoration: + InputDecoration( + border: + InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of( + context) + .textTheme + .headlineSmall! + .copyWith( + fontSize: + 24), + ), + const Icon(FontAwesome + .help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + setState(() { + if (value + .toString() == + "YES") { + isPrivate = true; + } else { + isPrivate = false; + } + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption( + value: + lang)) + .toList( + growable: + false), + ) + : const SizedBox()), + ], + ); + }), + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle(primary, + Colors.transparent, second), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + String title = _formKey + .currentState! + .value['title']; + + if (selectedAgency + ?.privateEntity != + null) { + newAgency = selectedAgency; + } else { + newAgency = Agency( + id: selectedAgency?.id, + name: + selectedAgency!.name, + category: + selectedCategory, + privateEntity: isPrivate); + } + nonAcademicRecognition = + NonAcademicRecognition( + id: null, + title: title, + presenter: newAgency); + context + .read< + NonAcademicRecognitionBloc>() + .add(AddNonAcademeRecognition( + nonAcademicRecognition: + nonAcademicRecognition!, + profileId: profileId!, + token: token!)); + } + }, + child: const Text(submit)), + ) + ], + ), + )), + )); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/other_information/non_academic/edit_modal.dart b/lib/screens/profile/components/other_information/non_academic/edit_modal.dart new file mode 100644 index 0000000..87610a8 --- /dev/null +++ b/lib/screens/profile/components/other_information/non_academic/edit_modal.dart @@ -0,0 +1,438 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/other_information/non_acedimic_recognition.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; + +import '../../../../../model/utils/agency.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../utils/formatters.dart'; +import '../../../../../utils/text_container.dart'; + +class EditNonAcademicRecognitionScreen extends StatefulWidget { + const EditNonAcademicRecognitionScreen({super.key}); + + @override + State createState() => + _EditNonAcademicRecognitionScreenState(); +} + +class _EditNonAcademicRecognitionScreenState + extends State { + bool showAgencyCategory = false; + final agencyFocusNode = FocusNode(); + + final agencyCategoryFocusNode = FocusNode(); + final addAgencyController = TextEditingController(); + Agency? selectedAgency; + Category? selectedCategory; + Agency? newAgency; + bool showIsPrivateRadio = false; + bool? isPrivate = false; + NonAcademicRecognition? nonAcademicRecognition; + final oldAgencyController = TextEditingController(); + final _formKey = GlobalKey(); + int? profileId; + String? token; + + @override + void dispose() { + agencyFocusNode.dispose(); + agencyCategoryFocusNode.dispose(); + addAgencyController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocBuilder( + builder: (context, state) { + if (state is EditNonAcademeRecognitionState) { + oldAgencyController.text = + state.nonAcademicRecognition.presenter!.name!; + selectedAgency = state.nonAcademicRecognition.presenter; + selectedCategory = + state.nonAcademicRecognition.presenter!.category; + return SizedBox( + height: blockSizeVertical * 90, + child: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 25, horizontal: 18), + child: Column( + children: [ + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + name: 'title', + initialValue: + state.nonAcademicRecognition.title, + decoration: normalTextFieldStyle( + "Recognition / Award Title *", + "Recognition / Award Title"), + validator: + FormBuilderValidators.required( + errorText: + "this field is required"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder( + builder: (context, setState) { + //// AGENCY SEARCHFIELD + return Column( + children: [ + SearchField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: oldAgencyController, + itemHeight: 100, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem( + agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name! + .toUpperCase(), + overflow: + TextOverflow + .visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + focusNode: agencyFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Agency *", "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyCategoryFocusNode + .unfocus(), + )), + ////agency suggestion tap + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + agencyFocusNode.unfocus(); + if (selectedAgency + ?.category == + null) { + showAgencyCategory = true; + showIsPrivateRadio = true; + } else { + showAgencyCategory = false; + showIsPrivateRadio = false; + } + }); + }, + emptyWidget: Container( + decoration: box1(), + height: 100, + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + const SizedBox( + height: 20, + ), + const Text( + "No result found..."), + const SizedBox( + height: 10, + ), + TextButton( + //// Add agency onpressed + onPressed: () { + showDialog( + context: + context, + builder: + (BuildContext + context) { + return AlertDialog( + title: const Text( + "Add Agency?"), + content: + SizedBox( + height: + 130, + child: + Column( + children: [ + TextFormField( + inputFormatters: [UpperCaseTextFormatter()], + controller: + addAgencyController, + decoration: + normalTextFieldStyle("", ""), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + //// onpressed + onPressed: () { + setState(() { + newAgency = Agency(id: null, name: addAgencyController.text.toUpperCase(), category: null, privateEntity: null); + state.agencies.insert(0, newAgency!); + addAgencyController.clear(); + Navigator.pop(context); + }); + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }, + child: const Text( + "Add position")) + ]), + ), + ), + const SizedBox( + height: 8, + ), + SizedBox( + child: showAgencyCategory + ? SearchField( + focusNode: + agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state + .agencyCategories + .map((Category + category) => + SearchFieldListItem( + category + .name!, + item: + category, + child: + ListTile( + title: Text( + category + .name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + ////agency controller suggestion tap + onSuggestionTap: + (agencyCategory) { + setState(() { + selectedCategory = + agencyCategory + .item; + + agencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", + "") + .copyWith( + suffixIcon: + GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyCategoryFocusNode + .unfocus(), + )), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ) + : const SizedBox(), + ), + + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderRadioGroup( + decoration: + InputDecoration( + border: + InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of( + context) + .textTheme + .headlineSmall! + .copyWith( + fontSize: + 24), + ), + const Icon(FontAwesome + .help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + setState(() { + if (value + .toString() == + "YES") { + isPrivate = true; + } else { + isPrivate = false; + } + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption( + value: + lang)) + .toList( + growable: + false), + ) + : const SizedBox()), + ], + ); + }), + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle(primary, + Colors.transparent, second), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + String title = _formKey + .currentState! + .value['title']; + + if (selectedAgency + ?.privateEntity != + null) { + newAgency = selectedAgency; + } else { + newAgency = Agency( + id: selectedAgency?.id, + name: + selectedAgency!.name, + category: + selectedCategory, + privateEntity: isPrivate); + } + nonAcademicRecognition = + NonAcademicRecognition( + id: state + .nonAcademicRecognition + .id, + title: title, + presenter: newAgency); + context + .read< + NonAcademicRecognitionBloc>() + .add(EditNonAcademeRecognition( + nonAcademicRecognition: + nonAcademicRecognition!, + profileId: profileId!, + token: token!)); + } + }, + child: const Text(submit)), + ) + ], + ), + )), + )); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/other_information/non_academic_recognition_screen.dart b/lib/screens/profile/components/other_information/non_academic_recognition_screen.dart new file mode 100644 index 0000000..26eb9af --- /dev/null +++ b/lib/screens/profile/components/other_information/non_academic_recognition_screen.dart @@ -0,0 +1,316 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/other_information/non_academic/add_modal.dart'; +import 'package:unit2/screens/profile/components/other_information/non_academic/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../widgets/Leadings/close_leading.dart'; + +class NonAcademicRecognitionScreen extends StatelessWidget { + const NonAcademicRecognitionScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: context.watch().state + is AddNonAcademeRecognitionState + ? const FittedBox(child: Text("Add $nonAcademicRecTitle")) + : context.watch().state + is EditNonAcademeRecognitionState + ? const FittedBox( + child: Text("Edit $nonAcademicRecTitle"), + ) + : const FittedBox(child: Text(nonAcademicRecTitle)), + centerTitle: true, + backgroundColor: primary, + actions: (context.watch().state + is NonAcademicRecognitionLoadedState) + ? [ + AddLeading(onPressed: () { + context + .read() + .add(ShowAddNonAcademeRecognitionForm()); + }) + ] + : (context.watch().state + is AddNonAcademeRecognitionState || + context.watch().state + is EditNonAcademeRecognitionState) + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(const LoadNonAcademeRecognition()); + }) + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is NonAcademicRecognitionLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is NonAcademicRecognitionLoadedState || + state is NonAcademicRecognitionErrorState || + state is AddNonAcademeRecognitionState || + state is EditNonAcademeRecognitionState || + state is NonAcademeRecognitionEditedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////ADDED STATE + if (state is NonAcademeRecognitionAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const GetNonAcademicRecognition()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(const GetNonAcademicRecognition()); + }); + } + } + ////DELETED STATE + if (state is NonAcademeRecognitionDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Non Academic Recognition has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadNonAcademeRecognition()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Non Academic Recognition", () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadNonAcademeRecognition()); + }); + } + } + ////EDITED STATE + if (state is NonAcademeRecognitionEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadNonAcademeRecognition()); + }); + } else { + errorAlert(context, "Update Failed", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(const LoadNonAcademeRecognition()); + }); + } + } + }, + builder: (context, state) { + if (state is NonAcademicRecognitionLoadedState) { + if (state.nonAcademicRecognition.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: + state.nonAcademicRecognition.length, + itemBuilder: + (BuildContext context, int index) { + String award = state + .nonAcademicRecognition[index].title!; + String presenter = state + .nonAcademicRecognition[index] + .presenter! + .name!; + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + award, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500, + color: primary), + ), + const SizedBox( + height: 8, + ), + Text(presenter), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete non academic recognition-= = = = = = = = =>> + if (value == 1) { + confirmAlert(context, () { + context + .read< + NonAcademicRecognitionBloc>() + .add(DeleteNonAcademeRecognition( + nonAcademicRecognition: + state + .nonAcademicRecognition[ + index], + profileId: + profileId!, + nonAcademicRecognitions: + state + .nonAcademicRecognition, + token: token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 2) { + context + .read< + NonAcademicRecognitionBloc>() + .add(ShowEditNonAcademicRecognitionForm( + nonAcademicRecognition: + state.nonAcademicRecognition[ + index])); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 2, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any Non Academic Recognition added. Please click + to add"); + } + } + if (state is NonAcademicRecognitionErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context + .read() + .add(GetNonAcademicRecognition( + profileId: profileId, token: token)); + }); + } + if (state is AddNonAcademeRecognitionState) { + return const AddNonAcademicRecognitionScreen(); + } + if (state is EditNonAcademeRecognitionState) { + return const EditNonAcademicRecognitionScreen(); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} + +PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); +} diff --git a/lib/screens/profile/components/other_information/org_membership/add_modal.dart b/lib/screens/profile/components/other_information/org_membership/add_modal.dart new file mode 100644 index 0000000..144164f --- /dev/null +++ b/lib/screens/profile/components/other_information/org_membership/add_modal.dart @@ -0,0 +1,342 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/other_information/org_membership/organization_membership_bloc.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../../../model/utils/category.dart'; +import '../../../../../theme-data.dart/box_shadow.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../theme-data.dart/form-style.dart'; +import '../../../../../utils/formatters.dart'; + +class AddOrgMemberShipScreen extends StatefulWidget { + final int profileId; + final String token; + final List agencies; + final List agencyCategories; + final Bloc bloc; + const AddOrgMemberShipScreen( + {super.key, required this.profileId, required this.token, required this.agencies, required this.agencyCategories, required this.bloc}); + + @override + State createState() => _AddOrgMemberShipScreenState(); +} + +bool showAgencyCategory = false; +final agencyFocusNode = FocusNode(); + +final agencyCategoryFocusNode = FocusNode(); +final addAgencyController = TextEditingController(); +Agency? selectedAgency; +Category? selectedCategory; +Agency? newAgency; +bool showIsPrivateRadio = false; +bool? isPrivate = false; +final _formKey = GlobalKey(); + +class _AddOrgMemberShipScreenState extends State { + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return FormBuilder( + key: _formKey, + child: Container( + padding: + const EdgeInsets.symmetric(vertical:24, horizontal: 24), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + + StatefulBuilder(builder: (context, setState) { + //// AGENCY SEARCHFIELD + return Column( + children: [ + SearchField( + inputFormatters: [UpperCaseTextFormatter()], + + itemHeight: 100, + suggestions: widget.agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: AutoSizeText( + + agency.name!.toUpperCase(), + minFontSize: 12, + + + ), + subtitle: Text( + agency.privateEntity == true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + focusNode: agencyFocusNode, + searchInputDecoration: + normalTextFieldStyle("Agency *", "") + .copyWith( + suffixIcon: GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => agencyFocusNode.unfocus(), + )), + ////agency suggestion tap + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + agencyFocusNode.unfocus(); + if (selectedAgency?.category == null) { + showAgencyCategory = true; + showIsPrivateRadio = true; + } else { + showAgencyCategory = false; + showIsPrivateRadio = false; + } + }); + }, + emptyWidget: Container( + decoration: box1(), + height: 100, + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + const SizedBox( + height: 20, + ), + const Text("No result found..."), + const SizedBox( + height: 10, + ), + TextButton( + //// Add agency onpressed + onPressed: () { + showDialog( + context: context, + builder: + (BuildContext context) { + return AlertDialog( + title: const Text( + "Add Agency?"), + content: SizedBox( + height: 130, + child: Column( + children: [ + TextFormField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: + addAgencyController, + decoration: + normalTextFieldStyle( + "", ""), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double + .infinity, + height: 50, + child: + ElevatedButton( + style: mainBtnStyle( + primary, + Colors + .transparent, + second), + //// onpressed + onPressed: + () { + setState( + () { + newAgency = Agency( + id: null, + name: addAgencyController.text.toUpperCase(), + category: null, + privateEntity: null); + widget.agencies.insert(0, + newAgency!); + addAgencyController.clear(); + Navigator.pop(context); + }); + }, + child: const Text( + "Add"))), + ], + ), + ), + ); + }); + }, + child: const Text("Add position")) + ]), + ), + ), + const SizedBox( + height: 8, + ), + SizedBox( + child: showAgencyCategory + ? SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 70, + suggestions: widget.agencyCategories + .map((Category category) => + SearchFieldListItem( + category.name!, + item: category, + child: ListTile( + title: + Text(category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: + Text("No result found ...")), + ), + ////agency controller suggestion tap + onSuggestionTap: (agencyCategory) { + setState(() { + selectedCategory = + agencyCategory.item; + + agencyCategoryFocusNode.unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", "") + .copyWith( + suffixIcon: GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => + agencyCategoryFocusNode.unfocus(), + )), + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + ) + : const SizedBox(), + ), + + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderRadioGroup( + decoration: InputDecoration( + border: InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 24), + ), + const Icon( + FontAwesome.help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + setState(() { + if (value.toString() == "YES") { + isPrivate = true; + } else { + isPrivate = false; + } + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption( + value: lang)) + .toList(growable: false), + ) + : const SizedBox()), + ], + ); + }), + ////SHOW CATEGORY AGENCY + + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + if (selectedAgency?.privateEntity != null) { + newAgency = selectedAgency; + } else { + newAgency = Agency( + id: selectedAgency?.id, + name: selectedAgency!.name, + category: selectedCategory, + privateEntity: isPrivate); + } + Navigator.of(context).pop(); + widget.bloc + .add(AddOrgMembership( + agency: newAgency!, + profileId: widget.profileId, + token: widget.token)); + setState(() { + showAgencyCategory = false; + showIsPrivateRadio = false; + }); + } + }, + child: const Text(submit)), + ) + ]), + )); + } +} diff --git a/lib/screens/profile/components/other_information/org_membership_screen.dart b/lib/screens/profile/components/other_information/org_membership_screen.dart new file mode 100644 index 0000000..c4f1663 --- /dev/null +++ b/lib/screens/profile/components/other_information/org_membership_screen.dart @@ -0,0 +1,282 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/screens/profile/components/other_information/org_membership/add_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../bloc/profile/other_information/org_membership/organization_membership_bloc.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../utils/global.dart'; + +class OrgMembershipsScreen extends StatelessWidget { + const OrgMembershipsScreen({super.key}); + + @override + Widget build(BuildContext context) { + String? token; + int? profileId; + List agencies = []; + List agencyCategory = []; + final orgBloc = BlocProvider.of(context); + return Scaffold( + appBar: AppBar( + title: context.watch().state + is AddOrgMembershipState + ? const FittedBox(child: Text("Add $orgMembershipTitle")) + : const FittedBox(child: Text(" $orgMembershipTitle")), + backgroundColor: primary, + centerTitle: true, + actions: context.watch().state + is OrganizationMembershipLoaded + ? [ + AddLeading(onPressed: () { + showDialog(context: (context),builder: (BuildContext context){ + return AlertDialog( + title: const Text("Add Organization Membership"), + content: AddOrgMemberShipScreen(profileId: profileId!, token: token!,agencies: agencies,agencyCategories: agencyCategory,bloc: orgBloc,), + ); + }); + }) + ] + : context.watch().state + is AddOrgMembershipState + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(const GetOrganizationMembership()); + }) + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is OrgmembershipLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is OrganizationMembershipLoaded || + state is OrganizationMembershipErrorState || + state is AddOrgMembershipState || + state is OrgMembershipDeletedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////ADDED STATE + if (state is OrgMembershipAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadOrganizationMemberships()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadOrganizationMemberships()); + }); + } + } + ////DELETED STATE + if (state is OrgMembershipDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Organization Membership has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadOrganizationMemberships()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Organization Membership", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadOrganizationMemberships()); + }); + } + } + }, + builder: (context, state) { + if (state is OrganizationMembershipLoaded) { + agencies = state.agencies; + agencyCategory = state.agencyCategory; + if (state.orgMemberships.isNotEmpty) { + return ListView.builder( + itemCount: state.orgMemberships.length, + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemBuilder: + (BuildContext context, int index) { + String entity = state.orgMemberships[index] + .agency!.privateEntity == + false + ? governmentText.toUpperCase() + : privateText.toUpperCase(); + String agencyName = state + .orgMemberships[index].agency!.name!; + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row(children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + agencyName, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500, + color: primary), + ), + const SizedBox( + height: 8, + ), + Text( + entity, + style: Theme.of(context) + .textTheme + .labelMedium, + ), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete orgmembership-= = = = = = = = =>> + if (value == 1) { + confirmAlert(context, () { + final progress = + ProgressHUD.of(context); + progress!.showWithText( + "Loading..."); + context + .read< + OrganizationMembershipBloc>() + .add(DeleteOrgMemberShip( + profileId: + profileId!, + token: token!, + org: state + .orgMemberships[ + index])); + }, "Delete?", + "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Delete", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ]), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any Orgazational Membership added. Please click + to add"); + } + } + + if (state is OrganizationMembershipErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context + .read() + .add(GetOrganizationMembership( + token: token, profileId: profileId)); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} + +PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); +} + + +// const EmptyData(message: "You don't have any Organization Membership added. Please click + to add."), diff --git a/lib/screens/profile/components/other_information/skills_and_hobbies_screen.dart b/lib/screens/profile/components/other_information/skills_and_hobbies_screen.dart new file mode 100644 index 0000000..aaccdbd --- /dev/null +++ b/lib/screens/profile/components/other_information/skills_and_hobbies_screen.dart @@ -0,0 +1,288 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:simple_chips_input/simple_chips_input.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/other_information/skills_and_hobbies.dart'; +import 'package:unit2/screens/profile/components/other_information/skills_hobbies/add_modal.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../bloc/profile/other_information/hobbies/hoobies_bloc.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../utils/alerts.dart'; + +class SkillHobbiesScreen extends StatefulWidget { + const SkillHobbiesScreen({super.key}); + + @override + State createState() => _SkillHobbiesScreenState(); +} + +class _SkillHobbiesScreenState extends State { + @override + Widget build(BuildContext context) { + String token; + int profileId; + final bloc = BlocProvider.of(context); + String output = ''; + String? deletedChip, deletedChipIndex; + final keySimpleChipsInput = GlobalKey(); + final FocusNode focusNode = FocusNode(); + return Scaffold( + appBar: AppBar( + title:context.watch().state is AddHobbySkillState? const Text("Add $skillAndHobbiesTitle"):const Text(skillAndHobbiesTitle), + backgroundColor: primary, + centerTitle: true, + actions: context.watch().state is AddHobbySkillState + ? [ + AddLeading(onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add Skills and Hobbies"), + content: SimpleChipsInput( + separatorCharacter: ",", + createCharacter: ",", + focusNode: focusNode, + validateInput: true, + autoFocus: true, + formKey: keySimpleChipsInput, + onSubmitted: (p0) { + setState(() { + output = p0; + }); + }, + onChipDeleted: (p0, p1) { + setState(() { + deletedChip = p0; + deletedChipIndex = p1.toString(); + }); + }, + onSaved: ((p0) { + setState(() { + output = p0; + }); + }), + chipTextStyle: const TextStyle( + color: Colors.white, + fontSize: 16, + ), + deleteIcon: const Icon( + Icons.delete, + size: 14.0, + color: second, + ), + widgetContainerDecoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16.0), + border: Border.all(color: Colors.blue[100]!), + ), + chipContainerDecoration: BoxDecoration( + color: second, + borderRadius: BorderRadius.circular(50), + ), + placeChipsSectionAbove: false, + ), + actions: [ + ElevatedButton( + onPressed: () { + keySimpleChipsInput.currentState!.save(); + Navigator.of(context, rootNavigator: true) + .pop('dialog'); + bloc.add(GetAddedHobbiesSkills( + addedHobbiesSkills: output)); + }, + style: mainBtnStyle( + primary, Colors.transparent, second), + child: const Text(submit), + ) + ], + ); + }); + }) + ] + : [ + AddLeading(onPressed: () { + bloc.add(const ShowHobbySkillAddForm()); + }) + ]), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + buildWhen: (previous, current) => false, + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token!; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is HobbiesLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is HobbiesLoadedState || + state is HobbiesErrorState || + state is AddHobbySkillState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////ADDED STATE + if (state is HobbiesAndSkillsAddedState) { + if (state.status['success']) { + successAlert(context, "Adding Successfull!", + state.status['message'], () { + Navigator.of(context).pop(); + context.read().add( + LoadHobbiesSkills( + skillsHobbies: + state.mySkillsAndHobbies)); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context.read().add( + LoadHobbiesSkills( + skillsHobbies: + state.mySkillsAndHobbies)); + }); + } + } + //// DELETED STATE + + if (state is HobbiesAndSkillsDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Skill/Hobby Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add( + LoadHobbiesSkills( + skillsHobbies: state.skillsHobbies)); + }); + } else { + errorAlert(context, "Deletion Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context.read().add( + LoadHobbiesSkills( + skillsHobbies: state.skillsHobbies)); + }); + } + } + }, + builder: (context, state) { + if (state is HobbiesLoadedState) { + if (state.skillsAndHobbies.isNotEmpty) { + return Padding( + padding: const EdgeInsets.all(12), + child: Wrap( + spacing: 8, + runSpacing: 8, + alignment: WrapAlignment.start, + clipBehavior: Clip.none, + verticalDirection: VerticalDirection.up, + crossAxisAlignment: + WrapCrossAlignment.start, + direction: Axis.horizontal, + children: state.skillsAndHobbies + .map((SkillsHobbies sh) { + return Wrap( + children: [ + Container( + padding: + const EdgeInsets.only(left: 6), + child: Wrap( + clipBehavior: Clip.antiAlias, + alignment: WrapAlignment.center, + crossAxisAlignment: + WrapCrossAlignment.center, + runAlignment: + WrapAlignment.center, + children: [ + Text( + sh.name!, + style: Theme.of(context) + .textTheme + .labelMedium, + ), + IconButton( + onPressed: () { + confirmAlert( + context, + () => context + .read< + HoobiesBloc>() + .add(DeleteSkillHobbies( + profileId: + profileId, + skillsHobbies: [ + sh + ], + token: + token)), + "Delete", + "Confirm Delete"); + }, + icon: const Icon( + Icons.delete, + size: 16, + color: second, + )) + ]), + ) + ], + ); + }).toList()), + ); + } else { + return const EmptyData( + message: + "You don't have any Skills and Hobbies added. Please click + to add"); + } + } + if (state is AddHobbySkillState) { + return AddHobbiesAndSkillsScreen( + profileId: profileId, + token: token, + ); + } + if (state is HobbiesErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetSkillsHobbies( + profileId: profileId, token: token)); + }); + } + // if (state is ShowAddModalState) { + // return AddModal(bloc: bloc); + // } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} diff --git a/lib/screens/profile/components/other_information/skills_hobbies/add_modal.dart b/lib/screens/profile/components/other_information/skills_hobbies/add_modal.dart new file mode 100644 index 0000000..a296125 --- /dev/null +++ b/lib/screens/profile/components/other_information/skills_hobbies/add_modal.dart @@ -0,0 +1,70 @@ + +import 'package:filter_list/filter_list.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/profile/other_information/hobbies/hoobies_bloc.dart'; +import 'package:unit2/model/profile/other_information/skills_and_hobbies.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class AddHobbiesAndSkillsScreen extends StatefulWidget { +final int profileId; +final String token; + const AddHobbiesAndSkillsScreen({super.key,required this.profileId, required this.token}); + + @override + State createState() => + _AddHobbiesAndSkillsScreenState(); +} + +class _AddHobbiesAndSkillsScreenState extends State { + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if(state is AddHobbySkillState){ + final List selectedList= state.mySkillsAndHobbiesString.map((var element){ + return state.allSkillsAndHobbies.firstWhere((var data) => data.name == element ); + }).toList(); + return FilterListWidget( + themeData: FilterListThemeData(context,choiceChipTheme: const ChoiceChipThemeData(selectedBackgroundColor: primary)), + hideSelectedTextCount: true, + listData: state.allSkillsAndHobbies, + selectedListData: selectedList, + onApplyButtonClick: (list) { + // Navigator.pop(context, list); + context.read().add(AddHobbyAndSkills(profileId: widget.profileId, token: widget.token, skillsHobbies: list!)); + }, + choiceChipLabel: (item) { + + return item!.name; + }, + // choiceChipBuilder: (context, item, isSelected) { + // return Container( + // padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), + // margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10), + // decoration: BoxDecoration( + // border: Border.all( + // color: isSelected! ? Colors.blue[300]! : Colors.grey[300]!, + // )), + // child: Text(item.name), + // ); + // }, + validateSelectedItem: (list, val) { + /// identify if item is selected or not + return list!.contains(val); + }, + onItemSearch: (user, query) { + /// When search query change in search bar then this method will be called + /// + /// Check if items contains query + return user.name!.toLowerCase().contains(query.toLowerCase()); + }, + + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/reference/add_modal.dart b/lib/screens/profile/components/reference/add_modal.dart new file mode 100644 index 0000000..25508a8 --- /dev/null +++ b/lib/screens/profile/components/reference/add_modal.dart @@ -0,0 +1,485 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/references/references_bloc.dart'; +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/profile/references.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/text_container.dart'; + +class AddReferenceScreen extends StatefulWidget { + final int profileId; + final String token; + const AddReferenceScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _AddReferenceScreenState(); +} + +class _AddReferenceScreenState extends State { + final formKey = GlobalKey(); + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + bool overseas = false; + List? provinces; + List? citymuns; + List? barangays; + List category = ['Permanent', "Residential", "Birthplace"]; + ////seletected + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Barangay? selectedBarangay; + Country? selectedCountry; + AddressCategory? selectedCategory; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is AddReferenceState) { + return FormBuilder( + key: formKey, + child: Padding( + padding: const EdgeInsets.all(28), + child: ListView( + children: [ + + Row( + children: [ + ////LAST NAME + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + decoration: normalTextFieldStyle( + "Last name *", "Last name *"), + name: "lastname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + const SizedBox( + width: 8, + ), + ////FIRST NAME + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + decoration: normalTextFieldStyle( + "First name *", "First name *"), + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + ], + ), + const SizedBox( + height: 12, + ), + Row( + children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [ + UpperCaseTextFormatter() + ], + decoration: normalTextFieldStyle( + "Middle name ", ""), + name: "middlename", + + ), + ), + const SizedBox( + width: 8, + ), + ////Mobile + Flexible( + flex: 1, + child: FormBuilderTextField( + keyboardType: TextInputType.number, + inputFormatters: [mobileFormatter], + name: "mobile", + decoration: normalTextFieldStyle( + "Mobile *", + "+63 (9xx) xxx - xxxx"), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + ], + ), + const SizedBox( + height: 12, + ), + FormBuilderDropdown( + name: 'category', + validator: + FormBuilderValidators.required(errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Address Category", "Address Category"), + items: state.categories + .map>( + (AddressCategory cat) { + return DropdownMenuItem( + value: cat, + child: Text(cat.name!), + ); + }).toList(), + onChanged: (value) { + setState(() { + selectedCategory = value; + }); + }, + ), + const SizedBox( + height: 12, + ), + ////OVERSEAS ADDRESS + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Overseas Address?"), + ), + SizedBox( + height: overseas == true ? 12 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + FormBuilderDropdown( + autovalidateMode: + AutovalidateMode.onUserInteraction, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + onChanged: (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + getProvinces(); + } + }, + initialValue: null, + decoration: normalTextFieldStyle( + "Region*", "Region"), + name: 'region', + items: state.regions + .map>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text(region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'This field is required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: (Province? province) { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = province; + getCities(); + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province province) { + return DropdownMenuItem( + value: province, + child: FittedBox( + child: Text(province + .description!), + )); + }).toList(), + decoration: normalTextFieldStyle( + "Province*", "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? city) { + if (selectedMunicipality != + city) { + setState(() { + barangayCall = true; + }); + selectedMunicipality = city; + getBarangays(); + } + }, + decoration: normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text( + c.description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: barangayCall, + child: + DropdownButtonFormField( + isExpanded: true, + onChanged: (Barangay? baragay) { + selectedBarangay = baragay; + }, + decoration: normalTextFieldStyle( + "Barangay*", "Barangay"), + value: selectedBarangay, + items: barangays == null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>( + (Barangay barangay) { + return DropdownMenuItem( + value: barangay, + child: Text(barangay + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: FormBuilderDropdown( + initialValue: null, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + const SizedBox(height: 16,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + PersonalReference? personalReference; + if (formKey.currentState!.saveAndValidate()) { + String lastname = + formKey.currentState!.value['lastname']; + String firstname = + formKey.currentState!.value['firstname']; + String? middlename = + formKey.currentState?.value['middlename']; + String mobile = + formKey.currentState!.value['mobile']; + + Region? region = selectedRegion; + Province? province = Province( + code: selectedProvince?.code, + description: + selectedProvince?.description, + region: region, + psgcCode: selectedProvince?.psgcCode, + shortname: selectedProvince?.shortname); + CityMunicipality? city = CityMunicipality( + code: selectedMunicipality?.code, + description: + selectedMunicipality?.description, + province: province, + psgcCode: selectedMunicipality?.psgcCode, + zipcode: selectedMunicipality?.zipcode); + + Address address = Address( + id: null, + addressCategory: selectedCategory, + country: selectedCountry, + barangay: selectedBarangay, + addressClass: null, + cityMunicipality: city); + + if (selectedCountry != null) { + personalReference = PersonalReference( + id: null, + address: Address( + id: null, + addressCategory: selectedCategory, + country: selectedCountry, + barangay: null, + cityMunicipality: null, + addressClass: null), + lastName: lastname, + contactNo: mobile, + firstName: firstname, + middleName: middlename); + } else { + personalReference = PersonalReference( + id: null, + address: address, + lastName: lastname, + contactNo: mobile, + firstName: firstname, + middleName: middlename); + } + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + context.read().add( + AddReference( + profileId: widget.profileId, + reference: personalReference, + token: widget.token)); + } + }, + ), + ), + + + ], + ), + )); + } + return Container(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + barangayCall = true; + getBarangays(); + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } + + Future getBarangays() async { + try { + List newBarangays = await LocationUtils.instance + .getBarangay(code: selectedMunicipality!.code.toString()); + barangays = newBarangays; + setState(() { + selectedBarangay = newBarangays[0]; + barangayCall = false; + }); + } catch (e) { + context.read().add(CallErrorState()); + } + } +} diff --git a/lib/screens/profile/components/reference/edit_modal.dart b/lib/screens/profile/components/reference/edit_modal.dart new file mode 100644 index 0000000..658db44 --- /dev/null +++ b/lib/screens/profile/components/reference/edit_modal.dart @@ -0,0 +1,615 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/utils/global_context.dart'; +import '../../../../bloc/profile/references/references_bloc.dart'; +import '../../../../model/location/address_category.dart'; +import '../../../../model/location/barangay.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/profile/references.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/text_container.dart'; + +class EditReferenceScreen extends StatefulWidget { + final String token; + final int profileId; + const EditReferenceScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _EditReferenceScreenState(); +} + +class _EditReferenceScreenState extends State { + final formKey = GlobalKey(); + bool provinceCall = false; + bool cityCall = false; + bool barangayCall = false; + bool overseas = false; + List? provinces; + List? citymuns; + List? barangays; + ////seletected + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Barangay? selectedBarangay; + Country? selectedCountry; + AddressCategory? selectedCategory; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) => false, + builder: (context, state) { + if (state is EditReferenceState) { + overseas = state.isOverseas; + selectedCategory = state.selectedCategory; + ////if not overseas address + //// set initial values + if (!overseas) { + selectedRegion = state.selectedRegion; + provinces = state.provinces; + selectedProvince = state.selectedProvince; + citymuns = state.cities; + selectedMunicipality = state.selectedCity; + barangays = state.barangays; + selectedBarangay = state.selectedBarangay; + } else { + selectedCountry = state.selectedCountry; + } + + return FormBuilder( + key: formKey, + child: Padding( + padding: const EdgeInsets.all(28), + child: ListView( + children: [ + Row( + children: [ + ////LAST NAME + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter(),mobileFormatter], + initialValue: state.ref.lastName, + decoration: normalTextFieldStyle( + "Last name *", "Last name *"), + name: "lastname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + const SizedBox( + width: 8, + ), + ////FIRST NAME + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: state.ref.firstName, + decoration: normalTextFieldStyle( + "First name *", "First name *"), + name: "firstname", + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + ], + ), + const SizedBox( + height: 12, + ), + Row( + children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + initialValue: state.ref.middleName, + decoration: normalTextFieldStyle( + "Middle name *", "Midlle name *"), + name: "middlename", + ), + ), + const SizedBox( + width: 8, + ), + ////CATEGORY + Flexible( + flex: 1, + child: FormBuilderTextField( + initialValue: state.ref.contactNo, + name: "mobile", + decoration: normalTextFieldStyle( + "Tel./Mobile *", "Tel./Mobile"), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + ), + ], + ), + const SizedBox( + height: 12, + ), + FormBuilderDropdown( + name: 'category', + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Address Category", "Address Category"), + items: state.categories + .map>( + (AddressCategory cat) { + return DropdownMenuItem( + value: cat, + child: Text(cat.name!), + ); + }).toList(), + initialValue: selectedCategory, + onChanged: (value) { + selectedCategory = value; + }, + ), + const SizedBox( + height: 12, + ), + ////OVERSEAS ADDRESS + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Overseas Address?"), + ), + SizedBox( + height: overseas == true ? 12 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + DropdownButtonFormField( + isExpanded: true, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: + (Region? region) async { + setState(() { + provinceCall = true; + + selectedRegion = region; + }); + //// GET PROVINCES + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion! + .code + .toString()); + } catch (e) { + context + .read() + .add(CallErrorState()); + } + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + ////GET CITY MUNICIPALITY + try { + citymuns = await LocationUtils + .instance + .getCities( + code: + selectedProvince! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read() + .add(CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAYS + try { + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + selectedBarangay = + barangays![0]; + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read() + .add(CallErrorState()); + } + setState(() { + barangayCall = false; + }); + }, + value: selectedRegion, + decoration: + normalTextFieldStyle( + "Region*", "Region"), + items: state.regions.map< + DropdownMenuItem< + Region>>( + (Region region) { + return DropdownMenuItem< + Region>( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + onChanged: (Province? + province) async { + selectedProvince = + province; + setState(() { + cityCall = true; + }); + //// GET CITIES + try { + citymuns = + await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + ReferencesBloc>() + .add( + CallErrorState()); + } + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAY + try { + barangays = + await LocationUtils + .instance + .getBarangay( + code: selectedMunicipality! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + ReferencesBloc>() + .add( + CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + }, + value: selectedProvince, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province + province) { + return DropdownMenuItem( + value: + province, + child: + FittedBox( + child: Text( + province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: + DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? + city) async { + setState(() { + barangayCall = true; + }); + selectedMunicipality = + city; + //// GET BARANGAYS + try { + barangays = + await LocationUtils + .instance + .getBarangay( + code: selectedMunicipality! + .code!); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + ReferencesBloc>() + .add( + CallErrorState()); + } + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality + c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + //// BARANGAY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: barangayCall, + child: + DropdownButtonFormField< + Barangay>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (Barangay? baragay) { + selectedBarangay = + baragay; + }, + decoration: + normalTextFieldStyle( + "Barangay*", + "Barangay"), + value: selectedBarangay, + items: barangays == null + ? [] + : barangays!.map< + DropdownMenuItem< + Barangay>>( + (Barangay + barangay) { + return DropdownMenuItem( + value: barangay, + child: Text(barangay + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: DropdownButtonFormField< + Country>( + isExpanded: true, + value: selectedCountry?.id == 175 + ? null + : selectedCountry, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + items: state.countries.map< + DropdownMenuItem< + Country>>( + (Country country) { + return DropdownMenuItem< + Country>( + value: country, + child: FittedBox( + child: Text( + country.name!))); + }).toList(), + + decoration: normalTextFieldStyle( + "Country*", "Country"), + //// country dropdown + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + const SizedBox(height: 16,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + PersonalReference? personalReference; + if (formKey.currentState!.saveAndValidate()) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + String lastname = + formKey.currentState!.value['lastname']; + String firstname = + formKey.currentState!.value['firstname']; + String? middlename = + formKey.currentState?.value['middlename']; + String mobile = + formKey.currentState!.value['mobile']; + + Region? region = selectedRegion; + Province? province = Province( + code: selectedProvince?.code, + description: selectedProvince?.description, + region: region, + psgcCode: selectedProvince?.psgcCode, + shortname: selectedProvince?.shortname); + CityMunicipality? city = CityMunicipality( + code: selectedMunicipality?.code, + description: + selectedMunicipality?.description, + province: province, + psgcCode: selectedMunicipality?.psgcCode, + zipcode: selectedMunicipality?.zipcode); + + ////IF IS OVERSEAS + if (overseas) { + personalReference = PersonalReference( + id: state.ref.id, + address: Address( + id: state.ref.address!.id, + addressCategory: selectedCategory, + country: selectedCountry, + barangay: null, + cityMunicipality: null, + addressClass: null), + lastName: lastname, + contactNo: mobile, + firstName: firstname, + middleName: middlename); + } else { + //// IF NOT OVERSEAS + personalReference = PersonalReference( + id: state.ref.id, + address: Address( + id: state.ref.address!.id, + addressCategory: selectedCategory, + country: Country( + id: 175, code: null, name: null), + barangay: selectedBarangay, + cityMunicipality: city, + addressClass: + state.ref.address?.addressClass), + lastName: lastname, + contactNo: mobile, + firstName: firstname, + middleName: middlename); + } + + context.read().add(EditReference( + profileId: widget.profileId, + reference: personalReference, + token: widget.token)); + } + }, + ), + ), + ], + ), + )); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/references_screen.dart b/lib/screens/profile/components/references_screen.dart new file mode 100644 index 0000000..a9731fe --- /dev/null +++ b/lib/screens/profile/components/references_screen.dart @@ -0,0 +1,353 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/reference/add_modal.dart'; +import 'package:unit2/screens/profile/components/reference/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/references/references_bloc.dart'; +import '../../../utils/alerts.dart'; +class ReferencesScreen extends StatelessWidget { + const ReferencesScreen({super.key}); + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is AddReferenceState + ? const Text("Add Personal Reference") + : context.watch().state is EditReferenceState + ? const Text("Edit Personal Reference") + : const Text("Personal References"), + centerTitle: true, + backgroundColor: primary, + ////if state is adding or editing state show close button + actions: (context.watch().state + is AddReferenceState || + context.watch().state is EditReferenceState) + ? [ + //// close button + CloseLeading(onPressed: () { + context.read().add( + LoadReferences()); + }), + ] + : + //// if state is loaded state show add button + context.watch().state is ReferencesLoadedState + ? [ + AddLeading(onPressed: () { + context + .read() + .add(ShowAddReferenceForm()); + }), + ] + : []), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + //userbloc + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + //profilebloc + if (state is ProfileLoaded) { + return BlocConsumer( + //listener + listener: (context, state) { + print(state); + if (state is ReferencesLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ReferencesLoadedState || + state is AddReferenceState || + state is ReferencesErrorState || + state is DeleteReferenceState || + state is ReferencesAddedState || + state is EditReferenceState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////ADDED STATE + if (state is ReferencesAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } + } + ////EDIT REFERENCE STATE + if (state is ReferenceEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } + } + + ////DELETED STATE + if (state is DeleteReferenceState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Personal reference has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error Deleting Personal reference", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadReferences()); + }); + } + } + }, + //builder + builder: (context, state) { + //references bloc + if (state is ReferencesLoadedState) { + if (state.references.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.references.length, + itemBuilder: + (BuildContext context, int index) { + String? middlename = state.references[index].middleName ?? ""; + String fullname = + "${state.references[index].firstName} $middlename ${state.references[index].lastName}"; + String addres = state.references[index] + .address!.country?.id != + 175 + ? "COUNTRY: ${state.references[index].address!.country!.name!.toUpperCase()}" + : "${state.references[index].address?.cityMunicipality?.description}, ${state.references[index].address?.cityMunicipality?.province?.description}, ${state.references[index].address?.cityMunicipality?.province?.region?.description}"; + + String mobile = state + .references[index].contactNo + .toString(); + return Column( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + decoration: box1(), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text(fullname.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w500, + color: + primary)), + const SizedBox( + height: 8, + ), + Text(addres, + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith( + fontWeight: + FontWeight + .w500)), + const SizedBox( + height: 8, + ), + Text( + "${mobileOrPhone.toUpperCase()} : $mobile", + style: Theme.of(context) + .textTheme + .labelMedium!), + ], + ), + ), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete eligibilty-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Please wait..."); + context + .read< + ReferencesBloc>() + .add(DeleteReference( + profileId: + profileId!, + refId: state + .references[ + index] + .id!, + references: state + .references, + token: token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit reference-= = = = = = = = =>> + final progress = + ProgressHUD.of(context); + progress!.showWithText( + "Please wait..."); + context + .read() + .add(ShowEditReferenceForm( + personalReference: + state.references[ + index])); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + popMenuItem( + text: "Attach", + value: 2, + icon: Icons.attach_file), + + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + }else{ + return const EmptyData(message: "You don't have any references added. Please click + to add."); + } + } + if (state is AddReferenceState) { + return AddReferenceScreen( + profileId: profileId!, + token: token!, + ); + } + if (state is EditReferenceState) { + return EditReferenceScreen( + profileId: profileId!, + token: token!, + ); + } + if (state is ReferencesErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetReferences( + profileId: profileId!, + token: token!)); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/submenu.dart b/lib/screens/profile/components/submenu.dart new file mode 100644 index 0000000..c412a36 --- /dev/null +++ b/lib/screens/profile/components/submenu.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +ListTile subMenu(IconData icon, String title,Function() onTap) { + return ListTile( + leading: Container( + margin: const EdgeInsets.only(left: 20), + child: Icon( + icon, + size: 20, + color: primary, + )), + title: Text( + title, + style: const TextStyle(), + ), + trailing: const Icon(Icons.keyboard_arrow_right), + onTap: onTap, + ); +} diff --git a/lib/screens/profile/components/voluntary_works/add_modal.dart b/lib/screens/profile/components/voluntary_works/add_modal.dart new file mode 100644 index 0000000..ffea1bf --- /dev/null +++ b/lib/screens/profile/components/voluntary_works/add_modal.dart @@ -0,0 +1,770 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/voluntary_works/voluntary_work_bloc.dart'; +import 'package:unit2/utils/global.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/profile/voluntary_works.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../model/utils/position.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/text_container.dart'; +import '../../shared/add_for_empty_search.dart'; + +class AddVoluntaryWorkScreen extends StatefulWidget { + final int profileId; + final String token; + const AddVoluntaryWorkScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _AddVoluntaryWorkScreenState(); +} + +class _AddVoluntaryWorkScreenState extends State { + final formKey = GlobalKey(); + ////controllers + final addPositionController = TextEditingController(); + final addAgencyController = TextEditingController(); + final toDateController = TextEditingController(); + final fromDateController = TextEditingController(); + ////focus nodes + final positionFocusNode = FocusNode(); + final agencyFocusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + ////booleans + bool showAgency = false; + bool showIsPrivateRadio = false; + bool currentlyInvolved = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool isPrivate = false; + ////Lists + List? provinces; + List? citymuns; + ////Selected + PositionTitle? selectedPosition; + Agency? selectedAgency; + Category? selectedCategoty; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + DateTime? from; + DateTime? to; + @override + void dispose() { + addPositionController.dispose(); + addAgencyController.dispose(); + toDateController.dispose(); + fromDateController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is AddVoluntaryWorkState) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 28), + child: FormBuilder( + key: formKey, + child: ListView( + children: [ + ////POSITIONS + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.positions + .map((PositionTitle position) => + SearchFieldListItem(position.title!, + item: position, + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + position.title!, + overflow: + TextOverflow.visible, + ), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle("Position *", "") + .copyWith( + suffixIcon: GestureDetector( + child: const Icon(Icons.arrow_drop_down), + onTap: () => positionFocusNode.unfocus(), + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + positionFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Position", + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = PositionTitle( + id: null, + title: addPositionController.text + .toUpperCase()); + + state.positions + .insert(0, newAgencyPosition); + + addPositionController.text = ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 12, + ), + ////AGENCY + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow.visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle("Agency *", "") + .copyWith( + suffixIcon: GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => agencyFocusNode.unfocus(), + )), + ////SELETECTED + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + if (selectedAgency!.privateEntity == + null) { + showAgency = true; + showIsPrivateRadio = true; + } else { + showAgency = false; + showIsPrivateRadio = false; + } + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController.text + .toUpperCase(), + category: null, + privateEntity: null); + state.agencies.insert(0, newAgency); + + addAgencyController.text = ""; + Navigator.pop(context); + }); + }, + title: "Add Agency")), + + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state.agencyCategory + .map((Category category) => + SearchFieldListItem( + category.name!, + item: category, + child: ListTile( + title: Text( + category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + setState(() { + selectedCategoty = + agencyCategory.item; + agencyCategoryFocusNode.unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode.unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + SizedBox( + height: showIsPrivateRadio ? 12 : 0, + ), + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderSwitch( + initialValue: false, + title: + Text(isPrivate ? "YES" : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: (value) { + setState(() { + isPrivate = value!; + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: FormBuilderValidators + .required(), + ) + : const SizedBox()), + const SizedBox( + height: 12, + ), + //// total hours + FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This Field is required"), + name: "total_hours", + keyboardType: TextInputType.number, + decoration: + normalTextFieldStyle("Total Hours*", "0"), + ), + const SizedBox( + height: 12, + ), + ////Currently Involved + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: currentlyInvolved, + activeColor: second, + onChanged: (value) { + setState(() { + currentlyInvolved = value!; + }); + }, + decoration: normalTextFieldStyle( + "Currently Involved?", + 'Graduated?'), + name: 'currently_involved', + title: Text( + currentlyInvolved ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: StatefulBuilder( + builder: (context, setState) { + return Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + use24HourFormat: false, + icon: const Icon( + Icons.date_range), + controller: + fromDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + // selectableDayPredicate: + // (date) { + // if (to != null && + // to!.microsecondsSinceEpoch >= + // date.microsecondsSinceEpoch) { + // return false; + // } + // return true; + // }, + onChanged: (value) { + setState(() { + from = DateTime.parse( + value); + }); + }, + initialDate: to == null + ? DateTime.now() + : to!.subtract( + const Duration( + days: 1)), + timeHintText: + "Date of Examination/Conferment", + decoration: + normalTextFieldStyle( + "From *", + "From *") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialValue: null, + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: currentlyInvolved + ? TextFormField( + enabled: false, + initialValue: "PRESENT", + style: const TextStyle( + color: + Colors.black45), + decoration: + normalTextFieldStyle( + "", "") + .copyWith(), + ) + : DateTimePicker( + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: + toDateController, + // selectableDayPredicate: + // (date) { + // if (from != null && + // from!.microsecondsSinceEpoch > + // date.microsecondsSinceEpoch) { + // return false; + // } + // return true; + // }, + onChanged: (value) { + setState(() { + to = DateTime.parse( + value); + }); + }, + initialDate: from == + null + ? DateTime.now() + : from!.add( + const Duration( + days: 1)), + firstDate: + DateTime(1990), + lastDate: + DateTime(2100), + decoration: normalTextFieldStyle( + "To *", "To *") + .copyWith( + prefixIcon: + const Icon( + Icons + .date_range, + color: Colors + .black87, + ), + prefixText: + currentlyInvolved + ? "PRESENT" + : ""), + initialValue: null, + ), + ), + ], + ); + }), + ), + ], + ); + }), + ], + ); + }), + const SizedBox( + height: 12, + ), + //// OVERSEAS + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 12 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + FormBuilderDropdown( + autovalidateMode: AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: + (Region? region) async { + if (selectedRegion != region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + getProvinces(); + } + }, + initialValue: null, + decoration: normalTextFieldStyle( + "Region*", "Region"), + name: 'region', + items: state.regions.map< + DropdownMenuItem>( + (Region region) { + return DropdownMenuItem( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: + (Province? province) { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + getCities(); + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province + province) { + return DropdownMenuItem( + value: province, + child: + FittedBox( + child: Text( + province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? city) { + if (selectedMunicipality != + city) { + selectedMunicipality = + city; + } + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: FormBuilderDropdown( + initialValue: null, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + items: state.countries + .map>( + (Country country) { + return DropdownMenuItem( + value: country, + child: FittedBox( + child: + Text(country.name!))); + }).toList(), + name: 'country', + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + const SizedBox(height: 16,), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + Country country = selectedCountry ??= Country( + id: 175, name: 'Philippines', code: 'PH'); + Address address = Address( + barangay: null, + id: null, + addressCategory: null, + addressClass: null, + cityMunicipality: selectedMunicipality, + country: country); + if (selectedCategoty != null) { + selectedAgency = Agency( + id: selectedAgency?.id, + name: selectedAgency!.name, + category: selectedCategoty, + privateEntity: isPrivate); + } + VoluntaryWork work = VoluntaryWork( + ////address + address: address, + //// agency + agency: selectedAgency, + //// + position: selectedPosition, + ////total hours + totalHours: double.parse( + formKey.currentState!.value["total_hours"]), + ////to date + toDate: toDateController.text.isEmpty || + toDateController.text.toUpperCase() == + "PRESENT" + ? null + : DateTime.parse(toDateController.text), + ////from date + fromDate: + DateTime.parse(fromDateController.text), + ); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + AddVoluntaryWork( + profileId: widget.profileId, + token: widget.token, + work: work)); + } + }, + child: const Text(submit)), + ) + ], + )), + ); + } + return const Placeholder(); + }, + ); + } + + Future getProvinces() async { + try { + List newProvinces = await LocationUtils.instance + .getProvinces(regionCode: selectedRegion!.code.toString()); + setState(() { + provinces = newProvinces; + selectedProvince = provinces![0]; + provinceCall = false; + cityCall = true; + getCities(); + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } + + Future getCities() async { + try { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + }); + } catch (e) { + context + .read() + .add(ShowErrorState(message: e.toString())); + } + } +} diff --git a/lib/screens/profile/components/voluntary_works/edit_modal.dart b/lib/screens/profile/components/voluntary_works/edit_modal.dart new file mode 100644 index 0000000..29b420c --- /dev/null +++ b/lib/screens/profile/components/voluntary_works/edit_modal.dart @@ -0,0 +1,869 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/voluntary_works/voluntary_work_bloc.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/global_context.dart'; +import '../../../../model/location/city.dart'; +import '../../../../model/location/country.dart'; +import '../../../../model/location/provinces.dart'; +import '../../../../model/location/region.dart'; +import '../../../../model/profile/voluntary_works.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../model/utils/position.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/location_utilities.dart'; +import '../../../../utils/text_container.dart'; +import '../../shared/add_for_empty_search.dart'; + +class EditVoluntaryWorkScreen extends StatefulWidget { + final int profileId; + final String token; + const EditVoluntaryWorkScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditVoluntaryWorkScreenState(); +} + +class _EditVoluntaryWorkScreenState extends State { + final formKey = GlobalKey(); + ////controllers + final addPositionController = TextEditingController(); + final addAgencyController = TextEditingController(); + final toDateController = TextEditingController(); + final fromDateController = TextEditingController(); + final positionController = TextEditingController(); + final agencyController = TextEditingController(); + ////focus nodes + final positionFocusNode = FocusNode(); + final agencyFocusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + ////booleans + bool showAgency = false; + bool showIsPrivateRadio = false; + bool currentlyInvolved = false; + bool overseas = false; + bool provinceCall = false; + bool cityCall = false; + bool isPrivate = false; + DateTime? from; + DateTime? to; + ////Lists + List? provinces; + List? citymuns; + + ////Selected + PositionTitle? selectedPosition; + Agency? selectedAgency; + Category? selectedCategoty; + Region? selectedRegion; + Province? selectedProvince; + CityMunicipality? selectedMunicipality; + Country? selectedCountry; + @override + void dispose() { + addPositionController.dispose(); + addAgencyController.dispose(); + toDateController.dispose(); + fromDateController.dispose(); + positionController.dispose(); + agencyController.dispose(); + positionFocusNode.dispose(); + agencyFocusNode.dispose(); + agencyCategoryFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) { + return false; + }, + builder: (context, state) { + if (state is EditVoluntaryWorks) { + ////config + String? todate = state.work.toDate?.toString(); + provinces = state.provinces; + citymuns = state.cities; + positionController.text = state.currentPosition.title!; + agencyController.text = state.currentAgency.name!; + fromDateController.text = state.work.fromDate.toString(); + toDateController.text = todate ??= ""; + currentlyInvolved = todate.isEmpty || todate == "null" ? true : false; + overseas = state.overseas; + selectedCountry = state.currentCountry; + selectedPosition = state.currentPosition; + selectedAgency = state.currentAgency; + selectedRegion = state.currentRegion; + selectedProvince = state.currentProvince; + selectedMunicipality = state.currentCity; + from = state.work.fromDate; + to = state.work.toDate; + return Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: FormBuilder( + key: formKey, + child: Column( + children: [ + Flexible( + child: ListView( + children: [ + ////POSITIONS + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [UpperCaseTextFormatter()], + controller: positionController, + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.positions + .map((PositionTitle position) => + SearchFieldListItem(position.title!, + item: position, + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + position.title!, + overflow: + TextOverflow.visible, + ), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle("Position *", "") + .copyWith( + suffixIcon: GestureDetector( + child: const Icon(Icons.arrow_drop_down), + onTap: () => positionFocusNode.unfocus(), + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + print(selectedPosition!.title); + positionFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Position", + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = PositionTitle( + id: null, + title: addPositionController.text + .toUpperCase()); + + state.positions + .insert(0, newAgencyPosition); + + addPositionController.text = ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 12, + ), + ////AGENCY + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + SearchField( + + enabled: false, + inputFormatters: [ + UpperCaseTextFormatter() + ], + controller: agencyController, + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow.visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle("Agency *", "") + .copyWith( + filled: true, + fillColor: Colors.grey.shade300, + suffixIcon: GestureDetector( + child: const Icon( + Icons.arrow_drop_down, + ), + onTap: () => agencyFocusNode.unfocus(), + )), + ////SELETECTED + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + if (selectedAgency!.privateEntity == + null) { + showAgency = true; + showIsPrivateRadio = true; + } else { + showAgency = false; + showIsPrivateRadio = false; + } + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController.text + .toUpperCase(), + category: null, + privateEntity: null); + state.agencies + .insert(0, newAgency); + + addAgencyController.text = ""; + Navigator.pop(context); + }); + }, + title: "Add Agency")), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("You cannot change agency on update mode",style: Theme.of(context).textTheme.bodySmall,), + ), + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state.agencyCategory + .map((Category category) => + SearchFieldListItem( + category.name!, + item: category, + child: ListTile( + title: Text( + category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + setState(() { + selectedCategoty = + agencyCategory.item; + agencyCategoryFocusNode + .unfocus(); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode + .unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + SizedBox( + height: showIsPrivateRadio ? 12 : 0, + ), + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderSwitch( + initialValue: false, + title: Text( + isPrivate ? "YES" : "NO"), + decoration: normalTextFieldStyle( + "Private Entity?", + 'Private Entity?'), + + ////onvhange private sector + onChanged: (value) { + setState(() { + isPrivate = value!; + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: FormBuilderValidators + .required(), + ) + : const SizedBox()), + const SizedBox( + height: 12, + ), + //// total hours + FormBuilderTextField( + initialValue: + state.work.totalHours.toString(), + validator: FormBuilderValidators.required( + errorText: "This Field is required"), + name: "total_hours", + keyboardType: TextInputType.number, + decoration: normalTextFieldStyle( + "Total Hours*", "0"), + ), + const SizedBox( + height: 12, + ), + ////Currently Involved + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: currentlyInvolved, + activeColor: second, + onChanged: (value) { + setState(() { + currentlyInvolved = value!; + }); + }, + decoration: normalTextFieldStyle( + "Currently Involved?", + 'Graduated?'), + name: 'currently_involved', + title: Text( + currentlyInvolved ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + use24HourFormat: false, + icon: const Icon( + Icons.date_range), + controller: + fromDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: + "Date of Examination/Conferment", + decoration: + normalTextFieldStyle( + "From *", + "From *") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: Colors.black87, + )), + + onChanged: (value) { + setState(() { + from = DateTime.parse( + value); + }); + }, + initialDate: to == null + ? DateTime.now() + : to!.subtract( + const Duration( + days: 1)), + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: currentlyInvolved + ? TextFormField( + enabled: false, + initialValue: "PRESENT", + style: const TextStyle( + color: + Colors.black45), + decoration: + normalTextFieldStyle( + "", "") + .copyWith(), + ) + : DateTimePicker( + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: + toDateController, + firstDate: + DateTime(1990), + lastDate: + DateTime(2100), + + onChanged: (value) { + setState(() { + to = DateTime.parse( + value); + }); + }, + initialDate: from == + null + ? DateTime.now() + : from!.add( + const Duration( + days: 1)), + decoration: normalTextFieldStyle( + "To *", "To *") + .copyWith( + prefixIcon: + const Icon( + Icons + .date_range, + color: Colors + .black87, + ), + prefixText: + currentlyInvolved + ? "PRESENT" + : ""), + initialValue: null, + ), + ), + ], + ), + ), + ], + ); + }), + ], + ); + }), + + const SizedBox( + height: 12, + ), + //// OVERSEAS + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + FormBuilderSwitch( + initialValue: overseas, + activeColor: second, + onChanged: (value) { + setState(() { + overseas = value!; + }); + }, + decoration: normalTextFieldStyle( + "Overseas Address?", ''), + name: 'overseas', + title: Text(overseas ? "YES" : "NO"), + ), + SizedBox( + height: overseas == true ? 12 : 0, + ), + SizedBox( + child: overseas == false + ? Column( + children: [ + const SizedBox( + height: 12, + ), + ////REGION DROPDOWN + DropdownButtonFormField( + isExpanded: true, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + onChanged: + (Region? region) async { + if (selectedRegion != + region) { + setState(() { + provinceCall = true; + }); + selectedRegion = region; + try { + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion! + .code + .toString()); + }catch(e){ + context + .read() + .add(ShowErrorState(message: e.toString())); + } + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + NavigationService + .navigatorKey + .currentContext + ?.read< + VoluntaryWorkBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + + } + }, + value: selectedRegion, + decoration: + normalTextFieldStyle( + "Region*", "Region"), + items: state.regions.map< + DropdownMenuItem< + Region>>( + (Region region) { + return DropdownMenuItem< + Region>( + value: region, + child: Text( + region.description!)); + }).toList(), + ), + const SizedBox( + height: 12, + ), + //// PROVINCE DROPDOWN + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: provinceCall, + child: DropdownButtonFormField< + Province?>( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null + ? 'required' + : null, + isExpanded: true, + value: selectedProvince, + onChanged: (Province? + province) async { + if (selectedProvince != + province) { + setState(() { + cityCall = true; + }); + selectedProvince = + province; + try { + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code + .toString()); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + }); + } catch (e) { + context + .read< + VoluntaryWorkBloc>() + .add(ShowErrorState( + message: e + .toString())); + } + } + }, + items: provinces == null + ? [] + : provinces!.map< + DropdownMenuItem< + Province>>( + (Province + province) { + return DropdownMenuItem( + value: + province, + child: + FittedBox( + child: Text( + province + .description!), + )); + }).toList(), + decoration: + normalTextFieldStyle( + "Province*", + "Province")), + ), + ), + ////CITY MUNICIPALITY + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.white, + inAsyncCall: cityCall, + child: + DropdownButtonFormField< + CityMunicipality>( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + isExpanded: true, + onChanged: + (CityMunicipality? + city) { + if (selectedMunicipality != + city) { + selectedMunicipality = + city; + } + }, + decoration: + normalTextFieldStyle( + "Municipality*", + "Municipality"), + value: selectedMunicipality, + items: citymuns == null + ? [] + : citymuns!.map< + DropdownMenuItem< + CityMunicipality>>( + (CityMunicipality + c) { + return DropdownMenuItem( + value: c, + child: Text(c + .description!)); + }).toList(), + ), + ), + ), + ], + ) + //// COUNTRY DROPDOWN + : SizedBox( + height: 60, + child: DropdownButtonFormField< + Country>( + isExpanded: true, + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + items: state.countries.map< + DropdownMenuItem< + Country>>( + (Country country) { + return DropdownMenuItem< + Country>( + value: country, + child: FittedBox( + child: Text( + country.name!))); + }).toList(), + value: selectedCountry!.id == 175 + ? null + : selectedCountry, + decoration: normalTextFieldStyle( + "Country*", "Country"), + onChanged: (Country? value) { + selectedCountry = value; + }, + ), + ), + ), + ], + ); + }), + ], + ), + ), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + Address address; + //// if not overseas + if (!overseas) { + address = Address( + barangay: null, + id: state.work.address?.id, + addressCategory: + state.work.address?.addressCategory, + addressClass: + state.work.address?.addressClass, + cityMunicipality: selectedMunicipality, + country: Country( + code: "PH", + id: 175, + name: "PHILIPPINES")); + } else { + ////if overseas + address = Address( + barangay: null, + id: state.work.address?.id, + addressCategory: + state.work.address?.addressCategory, + addressClass: + state.work.address?.addressClass, + cityMunicipality: null, + country: selectedCountry); + } + + if (selectedCategoty != null) { + selectedAgency = Agency( + id: selectedAgency?.id, + name: selectedAgency!.name, + category: selectedCategoty, + privateEntity: isPrivate); + } + VoluntaryWork work = VoluntaryWork( + ////address + address: address, + //// agency + agency: selectedAgency, + //// + position: selectedPosition, + ////total hours + totalHours: double.parse(formKey + .currentState!.value["total_hours"]), + ////to date + toDate: toDateController.text.isEmpty || + toDateController.text.toUpperCase() == + "PRESENT" + ? null + : DateTime.parse(toDateController.text), + ////from date + fromDate: + DateTime.parse(fromDateController.text), + ); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + UpdateVolunataryWork( + oldAgencyId: state.work.agency!.id!, + oldFromDate: + state.work.fromDate.toString(), + oldPosId: state.work.position!.id!, + profileId: widget.profileId, + token: widget.token, + work: work)); + } + }, + child: const Text(submit)), + ) + ], + )), + ), + ); + } + return const Placeholder(); + }, + ); + } +} diff --git a/lib/screens/profile/components/voluntary_works_screen.dart b/lib/screens/profile/components/voluntary_works_screen.dart new file mode 100644 index 0000000..5e92815 --- /dev/null +++ b/lib/screens/profile/components/voluntary_works_screen.dart @@ -0,0 +1,347 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/voluntary_works/add_modal.dart'; +import 'package:unit2/screens/profile/components/voluntary_works/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../bloc/profile/voluntary_works/voluntary_work_bloc.dart'; +import '../../../utils/alerts.dart'; +import '../../../widgets/Leadings/close_leading.dart'; + +class VolunataryWorkScreen extends StatelessWidget { + const VolunataryWorkScreen({super.key}); + + @override + Widget build(BuildContext context) { + String? token; + int? profileId; + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title:context.watch().state is AddVoluntaryWorkState? const FittedBox(child: Text("Add $voluntaryScreenTitle"),) :context.watch().state is EditVoluntaryWorks? const FittedBox(child: Text("Edit $voluntaryScreenTitle"),): const FittedBox(child: Text(voluntaryScreenTitle)), + backgroundColor: primary, + actions: (context.watch().state is VoluntaryWorkLoadedState)?[ + AddLeading(onPressed: () { + context.read().add(ShowAddVoluntaryWorks()); + }) + ]:(context.watch().state is AddVoluntaryWorkState || context.watch().state is EditVoluntaryWorks)?[ + CloseLeading(onPressed:() { + context.read().add(LoadVoluntaryWorks()); + }) + ]:[] + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId; + return BlocBuilder( + builder: (context, state) { + if (state is ProfileLoaded) { + return BlocConsumer( + listener: (context, state) { + if (state is VoluntaryWorkLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is VoluntaryWorkLoadedState || + state is VoluntaryWorkErrorState || + state is AddVoluntaryWorkState || + state is VoluntaryWorkAddedState || + state is VoluntaryWorkDeletedState || + state is EditVoluntaryWorks) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + //// Added State + if (state is VoluntaryWorkAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } + } + //// Updated State + + if (state is VoluntaryWorkEditedState) { + if (state.response['success']) { + successAlert(context, "Updated Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } + } + ////Deleted State + if (state is VoluntaryWorkDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull!", + "Voluntary Work Has Been Deleted Successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadVoluntaryWorks()); + }); + } + } + }, + builder: (context, state) { + if (state is VoluntaryWorkLoadedState) { + if (state.voluntaryWorks.isNotEmpty) { + return ListView.builder( + itemCount: state.voluntaryWorks.length, + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemBuilder: + (BuildContext context, int index) { + String position = state + .voluntaryWorks[index].position!.title!; + String agency = state + .voluntaryWorks[index].agency!.name!; + String from = dteFormat2.format( + state.voluntaryWorks[index].fromDate!); + String hours = state + .voluntaryWorks[index].totalHours + .toString(); + String? to = + state.voluntaryWorks[index].toDate == + null + ? "Present" + : dteFormat2.format(state + .voluntaryWorks[index].toDate!); + return Column( + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + position, + style: Theme.of(context) + .textTheme + .titleMedium!.copyWith(color: primary,fontWeight: FontWeight.w600), + ), + const SizedBox( + height: 5, + ), + Text( + agency, + style: Theme.of(context) + .textTheme + .titleSmall + ), + + const SizedBox( + height: 8, + ), + Text( + "$duration : $from to $to",style: Theme.of(context).textTheme.labelMedium!.copyWith(fontWeight: FontWeight.w500),), + const SizedBox( + height: 5, + ), + Text( + "$numberOfHours : $hours hours",style: Theme.of(context).textTheme.labelMedium!.copyWith(fontWeight: FontWeight.w500)), + ]), + ), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete eligibilty-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + BlocProvider.of< + VoluntaryWorkBloc>( + context) + .add(DeleteVoluntaryWork( + work: state + .voluntaryWorks[ + index], + profileId: + profileId!, + token: token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + bool isOverseas; + ////edit voluntary work-= = = = = = = = =>> + final progress = + ProgressHUD.of(context); + progress!.showWithText( + "Loading..."); + + if (state + .voluntaryWorks[ + index] + .address?.cityMunicipality == null + ) { + isOverseas = true; + }else{ + isOverseas = false; + } + + + context + .read< + VoluntaryWorkBloc>() + .add(ShowEditVoluntaryWorks( + profileId: + profileId!, + token: token!, + work: state + .voluntaryWorks[ + index], + isOverseas: + isOverseas)); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete) + + + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any Voluntary Works added. Please click + to add."); + } + } + if (state is AddVoluntaryWorkState) { + return AddVoluntaryWorkScreen( + profileId: profileId!, + token: token!, + ); + } + if (state is VoluntaryWorkErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetVoluntarWorks(profileId: profileId!, token: token!)); + }); + } + if (state is EditVoluntaryWorks) { + return EditVoluntaryWorkScreen( + profileId: profileId!, + token: token!, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + )), + ); + } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } +} diff --git a/lib/screens/profile/components/work_history/add_modal.dart b/lib/screens/profile/components/work_history/add_modal.dart new file mode 100644 index 0000000..5c353b4 --- /dev/null +++ b/lib/screens/profile/components/work_history/add_modal.dart @@ -0,0 +1,805 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart'; +import 'package:unit2/model/profile/work_history.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/agency_position.dart'; +import 'package:unit2/model/utils/category.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/utils/validators.dart'; +import '../../../../model/utils/position.dart'; +import '../../../../utils/formatters.dart'; +import '../../shared/add_for_empty_search.dart'; + +class AddWorkHistoryScreen extends StatefulWidget { + final int profileId; + final String token; + const AddWorkHistoryScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _AddWorkHistoryScreenState(); +} + +class _AddWorkHistoryScreenState extends State { + final addAgencyController = TextEditingController(); + final addPositionController = TextEditingController(); + final toDateController = TextEditingController(); + final fromDateController = TextEditingController(); + final _formKey = GlobalKey(); + PositionTitle? selectedPosition; + Agency? selectedAgency; + AppoinemtStatus? selectedStatus; + Category? selectedAgencyCategory; + String? salary; + String? salaryGrade; + String? salaryGradeStep; + String? accomplishment; + String? duties; + String? sFname; + String? sLname; + String? sMname; + String? sOffice; + bool showAgency = false; + bool showSalaryGradeAndSalaryStep = false; + bool? isPrivate = false; + bool showIsPrivateRadio = false; + bool currentlyEmployed = false; + final agencyFocusNode = FocusNode(); + final positionFocusNode = FocusNode(); + final appointmentStatusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + DateTime? from; + DateTime? to; + @override + void dispose() { + addPositionController.dispose(); + addAgencyController.dispose(); + toDateController.dispose(); + fromDateController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + + return BlocConsumer( + + listener: (context, state) { + if (state is AddWorkHistoryState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, builder: (context, state) { + if (state is AddWorkHistoryState) { + return FormBuilder( + key: _formKey, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 28), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + + + ////POSITIONS + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 70, + suggestionsDecoration: box1(), + suggestions: state.agencyPositions + .map((PositionTitle position) => + SearchFieldListItem(position.title!, + item: position, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + position.title!, + overflow: TextOverflow.visible, + ), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle("Position *", "").copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + positionFocusNode.unfocus(); + }, + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + positionFocusNode.unfocus(); + }); + }, + ////EMPTY WIDGET + emptyWidget: EmptyWidget( + title: "Add Position", + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = + PositionTitle( + id: null, + title: addPositionController.text + .toUpperCase()); + + state.agencyPositions + .insert(0, newAgencyPosition); + selectedPosition = newAgencyPosition; + addPositionController.text = ""; + Navigator.pop(context); + }); + }), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 12, + ), + ////APPOINTMENT STATUS' + SearchField( + inputFormatters: [UpperCaseTextFormatter()], + suggestions: state.appointmentStatus + .map((AppoinemtStatus status) => + SearchFieldListItem(status.label, + item: status, + child: Padding( + padding: const EdgeInsets.all(8), + child: Text(status.label)))) + .toList(), + focusNode: appointmentStatusNode, + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + onSuggestionTap: (status) { + selectedStatus = status.item; + + appointmentStatusNode.unfocus(); + }, + searchInputDecoration: + normalTextFieldStyle("Appointment Status", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + appointmentStatusNode.unfocus(); + }, + ))), + + const SizedBox( + height: 12, + ), + ////AGENCY + StatefulBuilder(builder: (context, setState) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow.visible, + ), + subtitle: Text(agency + .privateEntity == + true + ? "Private" + : agency.privateEntity == + false + ? "Government" + : ""), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle("Agency *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyFocusNode.unfocus(); + }, + )), + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + + if (selectedAgency!.privateEntity == + null) { + showIsPrivateRadio = true; + } else { + showIsPrivateRadio = false; + } + if (selectedAgency!.privateEntity == + true) { + showSalaryGradeAndSalaryStep = false; + } + if (selectedAgency!.privateEntity == + false) { + showSalaryGradeAndSalaryStep = true; + } + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController.text + .toUpperCase(), + category: null, + privateEntity: null); + + state.agencies.insert(0, newAgency); + selectedAgency = newAgency; + addAgencyController.text = ""; + showAgency = true; + + showIsPrivateRadio = true; + + Navigator.pop(context); + }); + }, + title: "Add Agency")), + + SizedBox( + height: showAgency ? 12 : 0, + ), + ////SHOW CATEGORY AGENCY + SizedBox( + child: showAgency + ? SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state.agencyCategory + .map((Category category) => + SearchFieldListItem( + category.name!, + item: category, + child: ListTile( + title: + Text(category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: + Text("No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + setState(() { + selectedAgencyCategory = + agencyCategory.item; + agencyCategoryFocusNode.unfocus(); + selectedAgency = Agency( + id: null, + name: selectedAgency!.name, + category: + selectedAgencyCategory, + privateEntity: null); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: + const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode.unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderRadioGroup( + decoration: InputDecoration( + border: InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 24), + ), + const Icon( + FontAwesome.help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + setState(() { + if (value.toString() == "YES") { + isPrivate = true; + showSalaryGradeAndSalaryStep = + false; + } else { + isPrivate = false; + showSalaryGradeAndSalaryStep = + true; + } + selectedAgency = Agency( + id: null, + name: selectedAgency!.name, + category: + selectedAgencyCategory, + privateEntity: value == "YES" + ? true + : false); + agencyFocusNode.unfocus(); + agencyCategoryFocusNode.unfocus(); + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators.required(), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption( + value: lang)) + .toList(growable: false), + ) + : const SizedBox()), + SizedBox( + height: showSalaryGradeAndSalaryStep ? 12 : 0, + ), + ////SALARY GRADE AND SALARY GRADE STEP + SizedBox( + child: showSalaryGradeAndSalaryStep + ? Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Flexible( + flex: 1, + child: FormBuilderTextField( + name: 'salary_grade', + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "Salary Grade (SG)", + "0"), + onChanged: (value) { + salaryGrade = value; + }, + validator: + FormBuilderValidators + .compose([ + FormBuilderValidators.integer( + radix: 10, + errorText: + "Please enter a number"), + FormBuilderValidators.numeric( + errorText: + "Please enter a number") + ]), + autovalidateMode: + AutovalidateMode + .onUserInteraction, + ), + ), + const SizedBox( + width: 12, + ), + Flexible( + flex: 1, + child: FormBuilderTextField( + name: 'salary_step', + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "SG Step (SG)", + "0"), + validator: + FormBuilderValidators + .compose([ + FormBuilderValidators.integer( + radix: 10, + errorText: + "Please enter a number"), + FormBuilderValidators.numeric( + errorText: + "Please enter a number") + ]), + autovalidateMode: + AutovalidateMode + .onUserInteraction, + onChanged: (value) { + setState(() { + salaryGradeStep = value; + }); + }, + ), + ) + ], + ) + ], + ) + : null), + ], + ); + }), + + const SizedBox( + height: 12, + ), + + ////MONTHLY SALARY + StatefulBuilder(builder: (context, setState) { + return FormBuilderTextField( + keyboardType: TextInputType.number, + onChanged: (value) { + setState(() { + salary = value; + }); + }, + validator: numericRequired, + name: "salary", + decoration: + normalTextFieldStyle("Monthly Salary *", "") + .copyWith(prefix: const Text("₱ ")), + ); + }), + const SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Immediate SuperVisor",textAlign: TextAlign.start, style: Theme.of(context).textTheme.titleMedium,), + ), + const SizedBox( + height: 12, + ), + ////IMMEDIATE SUPERVISOR + FormBuilderTextField( + onChanged: (value){ + sFname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_firstname', + decoration: + normalTextFieldStyle("First name", "First Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + onChanged: (value){ + sMname = value; + }, + name: 'supervisor_middlename', + decoration: normalTextFieldStyle( + "Middle name", "Middle Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + onChanged: (value){ + sLname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_lastname', + decoration: + normalTextFieldStyle("Last name", "Last Name"), + ), + const SizedBox( + height: 12, + ), + //// NAME OF OFFICE UNIT + FormBuilderTextField( + onChanged: (value){ + sOffice = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'office', + decoration: normalTextFieldStyle( + "Name of Office/Unit", "Name of Office/Unit"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ////CURRENTLY EMPLOYED + FormBuilderSwitch( + initialValue: currentlyEmployed, + activeColor: second, + onChanged: (value) { + setState(() { + if (value == true) { + currentlyEmployed = true; + toDateController.text = "PRESENT"; + } else { + currentlyEmployed = false; + toDateController.text = ""; + } + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Currently Employed?"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + use24HourFormat: false, + icon: const Icon(Icons.date_range), + controller: fromDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + selectableDayPredicate: (date) { + if (to != null && + to!.microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + timeHintText: + "Date of Examination/Conferment", + decoration: normalTextFieldStyle( + "From *", "From *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + onChanged: (value) { + setState(() { + from = DateTime.parse(value); + }); + }, + initialDate: to == null + ? DateTime.now() + : to!.subtract( + const Duration(days: 1)), + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: currentlyEmployed + ? TextFormField( + enabled: false, + initialValue: "PRESENT", + style: const TextStyle( + color: Colors.black45), + decoration: + normalTextFieldStyle("", "") + .copyWith(), + ) + : DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: toDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + selectableDayPredicate: (date) { + if (from != null && + from!.microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + to = DateTime.parse(value); + }); + }, + initialDate: from == null + ? DateTime.now() + : from!.add( + const Duration(days: 1)), + decoration: normalTextFieldStyle( + "To *", "To *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + ), + prefixText: + currentlyEmployed + ? "PRESENT" + : ""), + ), + ), + ], + ), + ), + ], + ); + }), + const SizedBox( + height: 8, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Work Experience",style: Theme.of(context).textTheme.titleMedium,), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + maxLines: 3, + onChanged: (value){ + accomplishment = value; + }, + name: "accomplishment", + decoration: normalTextFieldStyle( + "List of Accomplishment and Contribution", + "", + ), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + maxLines: 3, + onChanged: (value){ + duties = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "summary", + decoration: normalTextFieldStyle( + "Summary of Actual Duties", + "", + ), + ), + + + const SizedBox( + height: 20, + ), + ////SUBMIT BUTTON + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + + + if (_formKey.currentState!.validate()) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + + WorkHistory workHistory = WorkHistory( + accomplishment: null, + actualDuties: null, + agencydepid: null, + supervisor: Supervisor( + agencyId: selectedAgency?.id, + id: null, + lastname: sLname, + firstname: sFname, + middlename: sMname, + stationName: sOffice), + position: selectedPosition, + id: null, + agency: selectedAgency, + fromDate: fromDateController.text.isEmpty + ? null + : DateTime.parse(fromDateController.text), + toDate: toDateController.text.isEmpty || + toDateController.text.toUpperCase() == + "PRESENT" + ? null + : DateTime.parse(toDateController.text), + salarygrade: salaryGrade == null + ? null + : int.parse(salaryGrade!), + sgstep: salaryGradeStep == null + ? null + : int.parse(salaryGradeStep!), + monthlysalary: double.parse(salary!), + statusAppointment: selectedStatus!.value); + context.read().add(AddWorkHostory( + accomplishment: accomplishment, + actualDuties: duties, + workHistory: workHistory, + profileId: widget.profileId, + token: widget.token, + isPrivate: selectedAgency!.privateEntity!)); + } + }, + child: const Text(submit)), + ), + ], + ), + ), + ), + ); + } + return Container(); + }); + } +} diff --git a/lib/screens/profile/components/work_history/edit_modal.dart b/lib/screens/profile/components/work_history/edit_modal.dart new file mode 100644 index 0000000..5e8eafd --- /dev/null +++ b/lib/screens/profile/components/work_history/edit_modal.dart @@ -0,0 +1,839 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/screens/profile/shared/add_for_empty_search.dart'; +import '../../../../bloc/profile/workHistory/workHistory_bloc.dart'; +import '../../../../model/profile/work_history.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../model/utils/agency_position.dart'; +import '../../../../model/utils/category.dart'; +import '../../../../model/utils/position.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/formatters.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/text_container.dart'; +import '../../../../utils/validators.dart'; + +class EditWorkHistoryScreen extends StatefulWidget { + final int profileId; + final String token; + const EditWorkHistoryScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => _EditWorkHistoryScreenState(); +} + +class _EditWorkHistoryScreenState extends State { + final addAgencyController = TextEditingController(); + final addPositionController = TextEditingController(); + final toDateController = TextEditingController(); + final fromDateController = TextEditingController(); + final oldPositionController = TextEditingController(); + final oldAppointmentStatusController = TextEditingController(); + final oldAgencyController = TextEditingController(); + final _formKey = GlobalKey(); + PositionTitle? selectedPosition; + Agency? selectedAgency; + AppoinemtStatus? selectedStatus; + Category? selectedAgencyCategory; + String? salary; + String? salaryGrade; + String? salaryGradeStep; + String? accomplishments; + String? duties; + String? sFname; + String? sMname; + String? sLname; + String? sOffice; + //show agency category is a variable to show adding of agency category if you add agency manually + bool showAgencyCategory = false; + //showSalaryGadeAndSalaryStep is a variable that will show salary + //and salary step if selected agency is government + bool showSalaryGradeAndSalaryStep = false; + //isPrivate is the value of the isPrivate radion button + bool? isPrivate = false; + //showIsPrivateRadion is a variable that will show isPrivate radio if you + //add agency manually + bool showIsPrivateRadio = false; + bool currentlyEmployed = false; + final agencyFocusNode = FocusNode(); + final positionFocusNode = FocusNode(); + final appointmentStatusNode = FocusNode(); + final agencyCategoryFocusNode = FocusNode(); + DateTime? from; + DateTime? to; + @override + void dispose() { + addPositionController.dispose(); + addAgencyController.dispose(); + toDateController.dispose(); + fromDateController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is EditWorkHistoryState) { + oldPositionController.text = state.workHistory.position!.title!; + oldAppointmentStatusController.text = + state.workHistory.statusAppointment!; + oldAgencyController.text = state.workHistory.agency!.name!; + currentlyEmployed = state.workHistory.toDate == null ? true : false; + showSalaryGradeAndSalaryStep = + !state.workHistory.agency!.privateEntity!; + fromDateController.text = state.workHistory.fromDate.toString(); + toDateController.text = state.workHistory.toDate.toString(); + currentlyEmployed = state.workHistory.toDate == null ? true : false; + from = state.workHistory.fromDate; + to = state.workHistory.toDate; + accomplishments = state.workHistory.accomplishment == null?null:state.workHistory.accomplishment!.first.accomplishment!; + duties = state.workHistory.actualDuties == null? null:state.workHistory.actualDuties!.first.description; + sFname = state.workHistory.supervisor?.firstname; + sMname = state.workHistory.supervisor?.middlename; + sLname = state.workHistory.supervisor?.lastname; + sOffice = state.workHistory.supervisor?.stationName; + return FormBuilder( + key: _formKey, + child: SizedBox( + height: blockSizeVertical * 90, + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 32, horizontal: 28), + child: Column( + children: [ + Flexible( + child: ListView( + children: [ + ////POSITIONS + StatefulBuilder(builder: (context, setState) { + return SearchField( + inputFormatters: [UpperCaseTextFormatter()], + controller: oldPositionController, + itemHeight: 100, + suggestionsDecoration: box1(), + suggestions: state.agencyPositions + .map((PositionTitle position) => + SearchFieldListItem(position.title!, + item: position, + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + position.title!, + overflow: + TextOverflow.visible, + ), + )))) + .toList(), + focusNode: positionFocusNode, + searchInputDecoration: + normalTextFieldStyle("Position *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + positionFocusNode.unfocus(); + }, + )), + onSuggestionTap: (position) { + setState(() { + selectedPosition = position.item; + positionFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + controller: addPositionController, + onpressed: () { + setState(() { + PositionTitle newAgencyPosition = + PositionTitle( + id: null, + title: addPositionController.text + .toUpperCase()); + state.agencyPositions + .insert(0, newAgencyPosition); + selectedPosition = newAgencyPosition; + addPositionController.text = ""; + Navigator.pop(context); + }); + }, + title: "Add Position"), + validator: (position) { + if (position!.isEmpty) { + return "This field is required"; + } + return null; + }, + ); + }), + const SizedBox( + height: 12, + ), + ////APPOINTMENT STATUS' + SearchField( + inputFormatters: [UpperCaseTextFormatter()], + controller: oldAppointmentStatusController, + suggestions: state.appointmentStatus + .map((AppoinemtStatus status) => + SearchFieldListItem(status.label, + item: status, + child: Padding( + padding: const EdgeInsets.all(8), + child: Text(status.label)))) + .toList(), + focusNode: appointmentStatusNode, + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + onSuggestionTap: (status) { + selectedStatus = status.item; + appointmentStatusNode.unfocus(); + }, + searchInputDecoration: + normalTextFieldStyle("Appointment Status", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + appointmentStatusNode.unfocus(); + }, + ))), + + const SizedBox( + height: 12, + ), + + ////AGENCY + StatefulBuilder(builder: (context, setState) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SearchField( + enabled: false, + inputFormatters: [UpperCaseTextFormatter()], + controller: oldAgencyController, + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: state.agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: + TextOverflow.visible, + ), + subtitle: Text( + agency.privateEntity == + true + ? "Private" + : "Government"), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle("Agency *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyFocusNode.unfocus(); + }, + )), + onSuggestionTap: (agency) { + setState(() { + selectedAgency = agency.item; + if (selectedAgency!.privateEntity == + null) { + showIsPrivateRadio = true; + } else { + showIsPrivateRadio = false; + } + if (selectedAgency!.privateEntity == + true) { + showSalaryGradeAndSalaryStep = false; + } + if (selectedAgency!.privateEntity == + false) { + showSalaryGradeAndSalaryStep = true; + } + agencyFocusNode.unfocus(); + }); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: EmptyWidget( + controller: addAgencyController, + onpressed: () { + setState(() { + Agency newAgency = Agency( + id: null, + name: addAgencyController.text + .toUpperCase(), + category: null, + privateEntity: null); + state.agencies.insert(0, newAgency); + selectedAgency = newAgency; + addAgencyController.text = ""; + showAgencyCategory = true; + + showIsPrivateRadio = true; + + Navigator.pop(context); + }); + }, + title: "Add Agency")), + Text("You cannot change agency on update mode",textAlign: TextAlign.start,style: Theme.of(context).textTheme.bodySmall,), + + SizedBox( + height: showAgencyCategory ? 12 : 0, + ), + ////SHOW AGENCY CATEGORY + SizedBox( + child: showAgencyCategory + ? SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 70, + suggestions: state.agencyCategory + .map((Category category) => + SearchFieldListItem( + category.name!, + item: category, + child: ListTile( + title: Text( + category.name!), + subtitle: Text(category + .industryClass! + .name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text( + "No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + setState(() { + selectedAgencyCategory = + agencyCategory.item; + agencyCategoryFocusNode.unfocus(); + selectedAgency = Agency( + id: null, + name: selectedAgency!.name, + category: + selectedAgencyCategory, + privateEntity: null); + }); + }, + searchInputDecoration: + normalTextFieldStyle( + "Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode.unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ) + : const SizedBox(), + ), + + ////PRVIATE SECTOR + SizedBox( + child: showIsPrivateRadio + ? FormBuilderRadioGroup( + decoration: InputDecoration( + border: InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 24), + ), + const Icon( + FontAwesome.help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + setState(() { + if (value.toString() == "YES") { + isPrivate = true; + showSalaryGradeAndSalaryStep = + false; + } else { + isPrivate = false; + showSalaryGradeAndSalaryStep = + true; + } + selectedAgency = Agency( + id: null, + name: selectedAgency!.name, + category: + selectedAgencyCategory, + privateEntity: + value == "YES" + ? true + : false); + agencyFocusNode.unfocus(); + agencyCategoryFocusNode + .unfocus(); + }); + }, + + name: 'isPrivate', + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption( + value: lang)) + .toList(growable: false), + ) + : const SizedBox()), + SizedBox( + height: showSalaryGradeAndSalaryStep ? 12 : 0, + ), + ////SALARY GRADE AND SALARY GRADE STEP + SizedBox( + child: showSalaryGradeAndSalaryStep + ? Column( + children: [ + Row( + children: [ + ////SALARY GRADE + Flexible( + flex: 1, + child: FormBuilderTextField( + initialValue: state + .workHistory + .salarygrade + ?.toString(), + name: 'salary_grade', + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "Salary Grade (SG)", + "0"), + validator: + integerAndNumeric, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + ), + ), + const SizedBox( + width: 12, + ), + //// SALARY STEP + Flexible( + flex: 1, + child: FormBuilderTextField( + initialValue: state + .workHistory.sgstep + ?.toString(), + name: 'salary_step', + keyboardType: + TextInputType.number, + decoration: + normalTextFieldStyle( + "SG Step (SG)", + "0"), + validator: + integerAndNumeric, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + ), + ) + ], + ) + ], + ) + : null), + ], + ); + }), + + const SizedBox( + height: 12, + ), + ////MONTHLY SALARY + FormBuilderTextField( + initialValue: + state.workHistory.monthlysalary.toString(), + onChanged: (value) { + setState(() { + salary = value; + }); + }, + validator: numericRequired, + name: "salary", + decoration: + normalTextFieldStyle("Monthly Salary *", "") + .copyWith(prefix: const Text("₱ ")), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Immediate SuperVisor",style: Theme.of(context).textTheme.titleMedium,), + ), + const SizedBox( + height: 12, + ), + ////IMMEDIATE SUPERVISOR + FormBuilderTextField( + initialValue: sFname, + onChanged: (value) { + sFname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_firstname', + decoration: normalTextFieldStyle( + "First name", "First Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + initialValue: sMname, + onChanged: (value) { + sMname = value; + }, + name: 'supervisor_middlename', + decoration: normalTextFieldStyle( + "Middle name", "Middle Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + initialValue: sLname, + onChanged: (value) { + sLname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_lastname', + decoration: + normalTextFieldStyle("Last name", "Last Name"), + ), + + const SizedBox( + height: 12, + ), + //// NAME OF OFFICE UNIT + FormBuilderTextField( + initialValue: + sOffice, + onChanged: (value) { + sOffice = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'office', + decoration: normalTextFieldStyle( + "Name of Office/Unit", "Name of Office/Unit"), + ), + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return Column( + children: [ + ////CURRENTLY EMPLOYED + FormBuilderSwitch( + initialValue: currentlyEmployed, + activeColor: second, + onChanged: (value) { + setState(() { + if (value == true) { + currentlyEmployed = true; + toDateController.text = "PRESENT"; + } else { + currentlyEmployed = false; + toDateController.text = ""; + } + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Currently Employed?"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: screenWidth, + child: StatefulBuilder( + builder: (context, setState) { + return Row( + children: [ + //// FROM DATE + Flexible( + flex: 1, + child: DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + use24HourFormat: false, + icon: + const Icon(Icons.date_range), + controller: fromDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + timeHintText: + "Date of Examination/Conferment", + decoration: normalTextFieldStyle( + "From *", "From *") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + selectableDayPredicate: (date) { + if (to != null && + to!.microsecondsSinceEpoch <= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + from = DateTime.parse(value); + }); + }, + initialDate: to == null + ? DateTime.now() + : to!.subtract( + const Duration(days: 1)), + )), + const SizedBox( + width: 12, + ), + //// TO DATE + Flexible( + flex: 1, + child: currentlyEmployed + ? TextFormField( + enabled: false, + initialValue: "PRESENT", + style: const TextStyle( + color: Colors.black45), + decoration: + normalTextFieldStyle( + "", "") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: Colors.black45, + )), + ) + : DateTimePicker( + validator: FormBuilderValidators + .required( + errorText: + "This field is required"), + controller: toDateController, + firstDate: DateTime(1990), + lastDate: DateTime(2100), + selectableDayPredicate: + (date) { + if (from != null && + from!.microsecondsSinceEpoch >= + date.microsecondsSinceEpoch) { + return false; + } + return true; + }, + onChanged: (value) { + setState(() { + to = + DateTime.parse(value); + }); + }, + initialDate: from == null + ? DateTime.now() + : from!.add( + const Duration( + days: 1)), + decoration: normalTextFieldStyle( + "To *", "To *") + .copyWith( + prefixIcon: + const Icon( + Icons.date_range, + color: + Colors.black87, + ), + prefixText: + currentlyEmployed + ? "PRESENT" + : ""), + initialValue: null, + ), + ), + ], + ); + }), + ), + const SizedBox( + height: 8, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Work Experience",textAlign: TextAlign.start, style: Theme.of(context).textTheme.titleMedium,), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: accomplishments, + maxLines: 3, + onChanged: (value){ + accomplishments = value; + }, + name: "accomplishment", + decoration: normalTextFieldStyle( + "List of Accomplishment and Contribution", + "", + ), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + initialValue: duties, + maxLines: 3, + onChanged: (value){ + duties = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "summary", + decoration: normalTextFieldStyle( + "Summary of Actual Duties", + "", + ), + ), + ], + ); + }), + ], + ), + ), + const SizedBox(height: 25,), + ////SUBMIT BUTTON + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: + mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + if (_formKey.currentState!.saveAndValidate()) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + salary = _formKey.currentState!.value['salary']; + selectedPosition ??= state.workHistory.position; + salaryGrade = + _formKey.currentState!.value['salary_grade']; + salaryGradeStep = + _formKey.currentState!.value['salary_step']; + selectedAgency ??= state.workHistory.agency; + + selectedStatus ??= AppoinemtStatus( + value: state.workHistory.statusAppointment!, + label: state.workHistory.statusAppointment!); + WorkHistory newWorkHistory = WorkHistory( + accomplishment: accomplishments == null?null: [Accomplishment(id: state.workHistory.accomplishment!.first.id, workExperienceId: state.workHistory.id, accomplishment: accomplishments)], + actualDuties: duties == null? null: [ActualDuty(id: state.workHistory.actualDuties!.first.id, workExperienceId: state.workHistory.id, description: duties!)], + agencydepid: state.workHistory.agency!.id, + supervisor: Supervisor(agencyId: state.workHistory.agencydepid,id: state.workHistory.supervisor!.id,firstname: sFname,middlename: sMname,lastname: sLname,stationName: sOffice), + id: state.workHistory.id, + position: selectedPosition, + agency: selectedAgency, + fromDate: fromDateController.text.isEmpty + ? null + : DateTime.parse(fromDateController.text), + toDate: toDateController.text.isEmpty || + toDateController.text.toUpperCase() == + "PRESENT" || + toDateController.text.toLowerCase() == + 'null' + ? null + : DateTime.parse(toDateController.text), + monthlysalary: double.parse(salary!), + statusAppointment: selectedStatus!.value, + salarygrade: salaryGrade == null + ? null + : int.parse(salaryGrade!), + sgstep: salaryGradeStep == null + ? null + : int.parse(salaryGradeStep!), + ); + context.read().add( + UpdateWorkHistory( + + isPrivate: state.workHistory.agency!.privateEntity!, + profileId: widget.profileId, + token: widget.token, + workHistory: newWorkHistory)); + } + }, + child: const Text(submit)), + ), + ], + ), + ), + ), + ); + } + return const Center( + child: Text("Add Work History"), + ); + }, + ); + } +} diff --git a/lib/screens/profile/components/work_history_screen.dart b/lib/screens/profile/components/work_history_screen.dart new file mode 100644 index 0000000..63822ad --- /dev/null +++ b/lib/screens/profile/components/work_history_screen.dart @@ -0,0 +1,776 @@ +import 'dart:io'; +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/work_history/add_modal.dart'; +import 'package:unit2/screens/profile/components/work_history/edit_modal.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/Leadings/close_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/profile/workHistory/workHistory_bloc.dart'; +import '../../../model/profile/attachment.dart'; +import '../../../model/profile/work_history.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../shared/multiple_attachment.dart'; +import '../shared/single_attachment.dart'; + +class WorkHistoryScreen extends StatelessWidget { + const WorkHistoryScreen({super.key}); + + @override + Widget build(BuildContext context) { + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + + BuildContext parent = context; + String? token; + int? profileId; + List? results = []; + AttachmentCategory? selectedAttachmentCategory; + List attachmentCategories = []; + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: context.watch().state is AddWorkHistoryState + ? const FittedBox(child: Text("Add Work History")) + : context.watch().state is EditWorkHistoryState + ? const FittedBox( + child: Text("Edit Work History"), + ) + : const Text(workHistoryScreenTitle), + backgroundColor: primary, + centerTitle: true, + actions: context.watch().state is WorkHistoryLoaded + ? [ + AddLeading(onPressed: () { + context + .read() + .add(ShowAddWorkHistoryForm()); + }) + ] + : (context.watch().state + is AddWorkHistoryState || + context.watch().state + is EditWorkHistoryState) + ? [ + CloseLeading(onPressed: () { + context + .read() + .add(LoadWorkHistories()); + }) + ] + : [], + ), + body: + //UserBloc + ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId!; + return BlocBuilder( + builder: (context, state) { + //ProfileBloc + if (state is ProfileLoaded) { + //WorkHistoryBloc + return BlocConsumer( + listener: (context, state) { + if (state is WorkHistoryLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is WorkHistoryLoaded || + state is WorkHistoryErrorState || + state is AddWorkHistoryState || + state is WorkHistoryAddedState || + state is EditWorkHistoryState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////DELETED STATE + if (state is DeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Work has been deleted successfully", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Work History", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } + } + ////ADDED STATE + if (state is WorkHistoryAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } + } + if (state is WorkHistoryDevAttachmentAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } + } + ////ATTACHMENT DELETED STATE + if (state is WorkHistoryDevAttachmentDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Attachment has been deleted successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Attachment", () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } + } + + //// EDITED STATE + if (state is WorkHistoryEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context + .read() + .add(LoadWorkHistories()); + }); + } + } + }, + builder: (context, state) { + if (state is WorkHistoryLoaded) { + for (var cat in state.attachmentCategory) { + if (cat.subclass!.id == 4) { + attachmentCategories.add(cat); + } + } + if (state.workExperiences.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.workExperiences.length, + itemBuilder: + (BuildContext context, int index) { + String position = state + .workExperiences[index] + .position! + .title!; + String agency = state + .workExperiences[index].agency!.name!; + String from = dteFormat2.format( + state.workExperiences[index].fromDate!); + String? to = + state.workExperiences[index].toDate == + null + ? present.toUpperCase() + : dteFormat2.format(state + .workExperiences[index] + .toDate!); + return Column( + children: [ + Container( + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Column( + children: [ + Row(children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + position, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w600, + color: primary), + ), + const SizedBox( + height: 8, + ), + Text( + agency, + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith( + fontWeight: + FontWeight + .w500), + ), + const SizedBox( + height: 5, + ), + Text( + "$from - $to ", + style: Theme.of(context) + .textTheme + .labelMedium, + ), + ], + )), + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete workhistory-= = = = = = = = =>> + if (value == 2) { + confirmAlert(context, () { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + BlocProvider.of< + WorkHistoryBloc>( + context) + .add( + DeleteWorkHistory( + profileId: profileId!, + token: token!, + workHistory: state + .workExperiences[ + index], + )); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + ////edit eligibilty-= = = = = = = = =>> + // final progress = + // ProgressHUD.of( + // context); + // progress!.showWithText( + // "Loading..."); + // WorkHistory workHistory = + // state.workExperiences[ + // index]; + // context + // .read< + // WorkHistoryBloc>() + // .add(ShowEditWorkHistoryForm( + // workHistory: + // workHistory)); + } + ////Attachment + if (value == 3) { + results.clear(); + showDialog( + context: context, + builder: (BuildContext + context) { + return AlertDialog( + contentPadding: + const EdgeInsets + .all(0), + backgroundColor: + Colors.grey + .shade100, + icon: const Icon( + Icons.file_copy, + size: 32, + color: primary, + ), + title: const Text( + "File Attachment:"), + content: StatefulBuilder( + builder: (context, + setState) { + return Padding( + padding: + const EdgeInsets + .all( + 16.0), + child: Column( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + const Divider(), + Text( + position, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(fontWeight: FontWeight.w600, color: primary), + ), + const SizedBox( + height: + 8, + ), + Text( + agency, + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(fontWeight: FontWeight.w500), + ), + const SizedBox( + height: + 5, + ), + Text( + "$from - $to ", + style: Theme.of(context) + .textTheme + .labelMedium, + ), + const Divider(), + FormBuilderDropdown( + autovalidateMode: AutovalidateMode + .always, + decoration: normalTextFieldStyle( + "attachment category", "attachment category"), + name: + 'attachments_categorues', + validator: + FormBuilderValidators.required(errorText: "This field is required"), + onChanged: (value) { + selectedAttachmentCategory = value; + }, + items: attachmentCategories.map((e) { + return DropdownMenuItem(value: e, child: Text(e.description!)); + }).toList()), + const SizedBox( + height: + 8, + ), + Text( + "You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.", + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.black), + ), + const SizedBox( + height: + 5, + ), + Text( + "Acceptable Files: PDF, JPEG, PNG", + style: Theme.of(context) + .textTheme + .bodySmall, + ), + Text( + "Max File Size (per attachment): 1MB", + style: Theme.of(context) + .textTheme + .bodySmall, + ), + const Divider(), + ElevatedButton( + style: + ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(Colors.white), + ), + onPressed: + () async { + FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [ + 'jpg', + 'png', + 'jpeg', + 'pdf' + ]); + setState(() { + if (newResult != null) { + newResult.files.forEach((element) { + results.add(element); + }); + } + }); + }, + child: const Center( + child: Text( + "Select Files", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.black), + ))), + const Divider(), + SingleChildScrollView( + child: + SizedBox( + height: + 100, + width: + double.maxFinite, + child: results.isEmpty + ? const SizedBox() + : Expanded( + child: ListView.builder( + itemCount: results.length, + itemBuilder: (BuildContext context, index) { + final kb = results[index].size / 1024; + final mb = kb / 1024; + final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB'; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: double.infinity, + child: Row( + children: [ + Flexible( + child: SizedBox( + child: results[index].extension!.toLowerCase() == 'pdf' + ? SvgPicture.asset( + 'assets/svgs/pdf.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'png' + ? SvgPicture.asset( + 'assets/svgs/png.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg' + ? SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: blockSizeVertical * 3, + allowDrawingOutsideViewBox: true, + ) + : const SizedBox())), + const SizedBox( + width: 12, + ), + Flexible( + flex: 6, + child: Text( + results[index].name, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2), + ), + ), + const SizedBox( + width: 6, + ), + Flexible( + flex: 2, + child: Text( + size, + style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey), + )), + Flexible( + flex: 1, + child: IconButton( + icon: const Icon( + Icons.close, + color: Colors.grey, + ), + onPressed: () { + setState(() { + results.removeAt(index); + }); + }, + )) + ], + )), + const Divider() + ], + ); + }), + ), + ), + ), + const SizedBox( + height: + 12, + ), + SizedBox( + width: + double.maxFinite, + height: + 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () { + List paths = []; + + if (selectedAttachmentCategory != null && results.isNotEmpty) { + for (var res in results) { + paths.add(res.path!); + } + setState(() { + results.clear(); + }); + Navigator.pop(context); + parent.read().add(AddWorkHistoryAttachment(attachmentModule: state.workExperiences[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString())); + } + }, + child: const Text("Submit")), + ) + ]), + ); + }), + ); + }); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 2, + icon: Icons.delete), + popMenuItem( + text: "Attach", + value: 3, + icon: + Icons.attach_file), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) + ]), + const Divider(), + ////Show Attachments + // SizedBox( + // child: state + // .workExperiences[ + // index] + // .attachments == + // null || + // state + // .workExperiences[ + // index] + // .attachments! + // .isEmpty + // ? const SizedBox() + // : state + // .workExperiences[ + // index] + // .attachments != + // null && + // state + // .workExperiences[ + // index] + // .attachments! + // .length == + // 1 + // ? + // ////Single Attachment view + // SingleAttachment( + // onpressed: () { + // confirmAlert( + // context, + // () { + // parent.read().add(DeleteWorkHistoryAttachment( + // attachment: state + // .workExperiences[ + // index] + // .attachments! + // .first, + // moduleId: state + // .workExperiences[ + // index] + // .id!, + // profileId: + // profileId!, + // token: + // token!)); + // }, "Delete?", + // "Confirm Delete?"); + // }, + // attachment: state + // .workExperiences[ + // index] + // .attachments! + // .first, + // ) + // ////Multiple Attachments View + // : MultipleAttachments( + // profileId: + // profileId!, + // token: token!, + // moduleId: state + // .workExperiences[ + // index] + // .id!, + // educationBloc: + // null, + // workHistoryBloc: + // BlocProvider.of(context), + // eligibilityBloc: + // null, + // learningDevelopmentBloc: + // null, + // blocId: 3, + // eligibilityName: state + // .workExperiences[ + // index] + // .position! + // .title!, + // attachments: state + // .workExperiences[ + // index] + // .attachments!, + // )) + ], + ), + ), + const SizedBox( + height: 5, + ), + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any work experience added. Please click + to add"); + } + } + if (state is AddWorkHistoryState) { + return AddWorkHistoryScreen( + profileId: profileId!, + token: token!, + ); + } + if (state is EditWorkHistoryState) { + return EditWorkHistoryScreen( + profileId: profileId!, + token: token!, + ); + } + if (state is WorkHistoryErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add( + GetWorkHistories( + profileId: profileId!, + token: token!)); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} + +PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); +} diff --git a/lib/screens/profile/profile.dart b/lib/screens/profile/profile.dart new file mode 100644 index 0000000..ec1a721 --- /dev/null +++ b/lib/screens/profile/profile.dart @@ -0,0 +1,402 @@ +import 'package:expandable_group/expandable_group_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/brandico_icons.dart'; +import 'package:fluttericon/elusive_icons.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttericon/modern_pictograms_icons.dart'; +import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; +import 'package:unit2/bloc/profile/primary_information/citizenship/citizenship_bloc.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/address_screen.dart'; +import 'package:unit2/screens/profile/components/basic_information/citizenship_screen.dart'; +import 'package:unit2/screens/profile/components/basic_information/contact_information_screen.dart'; +import 'package:unit2/screens/profile/components/basic_information/identification_information_screen.dart'; +import 'package:unit2/screens/profile/components/basic_information/primary_information_screen.dart'; +import 'package:unit2/screens/profile/components/education_screen.dart'; +import 'package:unit2/screens/profile/components/eligibility_screen.dart'; +import 'package:unit2/screens/profile/components/family_background_screen.dart'; +import 'package:unit2/screens/profile/components/learning_and_development_screen.dart'; +import 'package:unit2/screens/profile/components/loading_screen.dart'; +import 'package:unit2/screens/profile/components/other_information/non_academic_recognition_screen.dart'; +import 'package:unit2/screens/profile/components/other_information/org_membership_screen.dart'; +import 'package:unit2/screens/profile/components/other_information/skills_and_hobbies_screen.dart'; +import 'package:unit2/screens/profile/components/references_screen.dart'; +import 'package:unit2/screens/profile/components/work_history_screen.dart'; +import 'package:unit2/screens/profile/components/voluntary_works_screen.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../bloc/profile/eligibility/eligibility_bloc.dart'; +import '../../bloc/profile/family/family_bloc.dart'; +import '../../bloc/profile/education/education_bloc.dart'; +import '../../bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import '../../bloc/profile/other_information/hobbies/hoobies_bloc.dart'; +import '../../bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart'; +import '../../bloc/profile/other_information/org_membership/organization_membership_bloc.dart'; +import '../../bloc/profile/references/references_bloc.dart'; +import '../../bloc/profile/voluntary_works/voluntary_work_bloc.dart'; +import '../../bloc/profile/workHistory/workHistory_bloc.dart'; +import '../../bloc/user/user_bloc.dart'; +import '../../model/profile/basic_information/primary-information.dart'; +import '../unit2/homepage.dart/components/menu.dart'; +import 'components/main_menu.dart'; +import 'components/submenu.dart'; + +class ProfileInfo extends StatelessWidget { + const ProfileInfo({super.key}); + + @override + Widget build(BuildContext context) { + int? profileId; + String? token; + Profile profile; + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + centerTitle: true, + title: const Text('Profile'), + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder(builder: (context, state) { + if (state is UserLoggedIn) { + profileId = state.userData!.user!.login!.user!.profileId; + token = state.userData!.user!.login!.token!; + profile = state.userData!.employeeInfo!.profile!; + + return BlocConsumer( + listener: ( + context, + state, + ) { + if (state is ProfileLoading) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ProfileLoaded || + state is ProfileErrorState || + state is BasicInformationEditingState) { + final progress = ProgressHUD.of(context); + progress?.dismiss(); + } + }, + builder: (context, state) { + if (state is ProfileLoaded) { + return Container( + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + child: ListView( + children: [ + Text( + "View and Update your Profile Information", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyLarge, + ), + ExpandableGroup( + collapsedIcon: + const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + Elusive.address_book, + color: primary, + ), + title: Text( + "Basic Information", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu(Icons.person, "Primary", () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider.value( + value: ProfileBloc() + ..add(GetPrimaryBasicInfo( + primaryBasicInformation: profile)), + child: PrimaryInfo( + token: token!, + profileId: profileId!, + ), + ); + })); + }), + subMenu(Icons.home, "Addresses", () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => AddressBloc() + ..add(GetAddress( + addresses: state.profileInformation + .basicInfo.addresses)), + child: const AddressScreen(), + ); + })); + }), + subMenu(Icons.contact_mail, "Identifications", + () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => IdentificationBloc() + ..add(GetIdentifications( + identificationInformation: state + .profileInformation + .basicInfo + .identifications)), + child: const IdentificationsScreen(), + ); + })); + }), + subMenu(Icons.contact_phone, "Contact Info", + () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => ContactBloc() + ..add(GetContacts( + contactInformations: state + .profileInformation + .basicInfo + .contactInformation)), + child: const ContactInformationScreen(), + ); + })); + }), + subMenu(Icons.flag, "Citizenships", () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => CitizenshipBloc() + ..add(GetCitizenship( + citizenship: state + .profileInformation + .basicInfo + .citizenships)), + child: CitizenShipScreen( + profileId: profileId!, token: token!), + ); + })); + }), + ]), + const Divider(), + MainMenu( + icon: Elusive.group, + title: "Family", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => FamilyBloc() + ..add(GetFamilies( + profileId: profileId!, token: token!)), + child: const FamilyBackgroundScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.graduation_cap, + title: "Education", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => EducationBloc() + ..add(GetEducationalBackground( + profileId: profileId!, token: token!)), + child: const EducationScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: Icons.stars, + title: "Eligibility", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => EligibilityBloc() + ..add(GetEligibilities( + profileId: profileId!, token: token!)), + child: const EligibiltyScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.shopping_bag, + title: "Work History", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => WorkHistoryBloc() + ..add(GetWorkHistories( + profileId: profileId!, token: token!)), + child: const WorkHistoryScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: FontAwesome5.walking, + title: "Voluntary Work & Civic Services", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => VoluntaryWorkBloc() + ..add(GetVoluntarWorks( + profileId: profileId!, token: token!)), + child: const VolunataryWorkScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: Elusive.lightbulb, + title: "Learning & Development", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => LearningDevelopmentBloc() + ..add(GetLearningDevelopments( + profileId: profileId!, token: token!)), + child: const LearningAndDevelopmentScreen(), + ); + })); + }, + ), + const Divider(), + MainMenu( + icon: Brandico.codepen, + title: "Personal References", + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => ReferencesBloc() + ..add(GetReferences( + profileId: profileId!, token: token!)), + child: const ReferencesScreen(), + ); + })); + }, + ), + ExpandableGroup( + collapsedIcon: + const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + Icons.info, + color: primary, + ), + title: Text( + "Other Information", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu( + Icons.fitness_center, "Skills & Hobbies", + () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => HoobiesBloc() + ..add(GetSkillsHobbies( + profileId: profileId!, + token: token!)), + child: const SkillHobbiesScreen(), + ); + })); + }), + subMenu(FontAwesome5.certificate, + "Organization Memberships", () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + OrganizationMembershipBloc() + ..add(GetOrganizationMembership( + profileId: profileId!, + token: token!)), + child: const OrgMembershipsScreen(), + ); + })); + }), + subMenu(Entypo.doc_text, + "Non-Academic Recognitions", () { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + NonAcademicRecognitionBloc() + ..add(GetNonAcademicRecognition( + profileId: profileId!, + token: token!)), + child: + const NonAcademicRecognitionScreen(), + ); + })); + }), + ]), + ExpandableGroup( + collapsedIcon: + const Icon(Icons.keyboard_arrow_down), + expandedIcon: const Icon(Icons.keyboard_arrow_up), + header: const ListTile( + leading: Icon( + FontAwesome5.laptop_house, + color: primary, + ), + title: Text( + "Assets", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + items: [ + subMenu(ModernPictograms.home, + "Real Property Tax", () {}), + ]), + ], + ), + ); + } + if (state is ProfileLoading) { + return const LoadingScreen(); + } + if (state is ProfileErrorState) { + return SomethingWentWrong( + message: state.mesage, + onpressed: () { + BlocProvider.of(context).add( + LoadProfile(token: token!, userID: profileId!)); + }); + } + + return Container(); + }, + ); + } + return Container(); + }), + )); + } +} diff --git a/lib/screens/profile/shared/add_for_empty_search.dart b/lib/screens/profile/shared/add_for_empty_search.dart new file mode 100644 index 0000000..2d67130 --- /dev/null +++ b/lib/screens/profile/shared/add_for_empty_search.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; + +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/formatters.dart'; + +class EmptyWidget extends StatelessWidget { + final TextEditingController controller; + final Function()? onpressed; + final String title; + const EmptyWidget( + {super.key, + required this.controller, + required this.onpressed, + required this.title}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: box1(), + height: 100, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + height: 20, + ), + const Text("No result found..."), + const SizedBox( + height: 10, + ), + TextButton( + onPressed: () { + ////ADD POSITION DIALOG + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: SizedBox( + height: 130, + child: Column( + children: [ + TextFormField( + inputFormatters: [UpperCaseTextFormatter()], + controller: controller, + decoration: normalTextFieldStyle("", ""), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, + Colors.transparent, second), + onPressed: onpressed, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }, + child: Text(title)) + ]), + ); + } +} diff --git a/lib/screens/profile/shared/multiple_attachment.dart b/lib/screens/profile/shared/multiple_attachment.dart new file mode 100644 index 0000000..03dbeb4 --- /dev/null +++ b/lib/screens/profile/shared/multiple_attachment.dart @@ -0,0 +1,241 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; +import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart'; +import 'package:unit2/utils/global_context.dart'; + +import '../../../model/profile/attachment.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; + +class MultipleAttachments extends StatelessWidget { + final Function(String source, String fileName) viewAttachment; + final List attachments; + final String eligibilityName; + final EducationBloc? educationBloc; + final EligibilityBloc? eligibilityBloc; + final LearningDevelopmentBloc? learningDevelopmentBloc; + final WorkHistoryBloc? workHistoryBloc; + final int blocId; + final int moduleId; + final int profileId; + final String token; + const MultipleAttachments( + {super.key, + required this.viewAttachment, + required this.blocId, + required this.educationBloc, + required this.eligibilityBloc, + required this.learningDevelopmentBloc, + required this.workHistoryBloc, + required this.attachments, + required this.eligibilityName, + required this.moduleId, + required this.profileId, + required this.token}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Flexible( + flex: 3, + child: Container( + padding: const EdgeInsets.all(5), + decoration: + box1().copyWith(color: Colors.grey.shade300, boxShadow: []), + child: AutoSizeText( + + attachments.first.filename!, + wrapWords: false, + maxLines: 1, + ))), + const SizedBox( + width: 8, + ), + Flexible( + child: FittedBox( + child: Container( + padding: const EdgeInsets.all(3), + decoration: + box1().copyWith(color: Colors.grey.shade300, boxShadow: []), + child: InkWell( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text( + "$eligibilityName Attachments", + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: attachments.map((e) { + String ext = e.filename! + .substring(e.filename!.lastIndexOf(".")); + + return Column( + children: [ + Row( + children: [ + Flexible( + child: SizedBox( + child: ext == '.pdf' + ? SvgPicture.asset( + 'assets/svgs/pdf.svg', + height: blockSizeVertical * 5, + allowDrawingOutsideViewBox: + true, + ) + : ext == '.png' + ? SvgPicture.asset( + 'assets/svgs/png.svg', + height: + blockSizeVertical * + 5.5, + allowDrawingOutsideViewBox: + true, + ) + : ext == '.jpg' + ? SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: + blockSizeVertical * + 5, + allowDrawingOutsideViewBox: + true, + ) + : SvgPicture.asset( + 'assets/svgs/jpg.svg', + height: + blockSizeVertical * + 5, + allowDrawingOutsideViewBox: + true, + ), + ), + ), + const SizedBox( + width: 8, + ), + Flexible( + flex: 4, + child: Tooltip( + message: e.filename, + child: GestureDetector( + onTap: (){ + viewAttachment(e.source!,e.filename!); + }, + child: Text( + e.filename!, + overflow: TextOverflow.ellipsis, + ), + )), + ), + const SizedBox( + width: 8, + ), + Flexible( + child: Row( + children: [ + Flexible( + child: IconButton( + icon: const Icon( + Icons.delete, + color: primary, + ), + onPressed: () { + confirmAlert(context, () { + if (blocId == 1) { + Navigator.pop( + NavigationService + .navigatorKey + .currentContext!); + educationBloc!.add( + DeleteEducationAttachment( + attachment: e, + moduleId: + moduleId, + profileId: + profileId, + token: token)); + } else if (blocId == 2) { + Navigator.pop( + NavigationService + .navigatorKey + .currentContext!); + eligibilityBloc!.add( + DeleteEligibyAttachment( + attachment: e, + moduleId: moduleId + .toString(), + profileId: profileId + .toString(), + token: token)); + } else if (blocId == 3) { + Navigator.pop( + NavigationService + .navigatorKey + .currentContext!); + workHistoryBloc!.add( + DeleteWorkHistoryAttachment( + attachment: e, + moduleId: + moduleId, + profileId: + profileId, + token: token)); + } else { + Navigator.pop( + NavigationService + .navigatorKey + .currentContext!); + learningDevelopmentBloc!.add( + DeleteLearningDevAttachment( + attachment: e, + moduleId: + moduleId, + profileId: + profileId, + token: token)); + } + }, "Delete?", + "Confirm Delete?"); + }), + ) + ], + ), + ), + ], + ), + const Divider() + ], + ); + }).toList(), + )); + }); + }, + child: Row( + children: const [ + Text(" See more.."), + Icon( + Icons.keyboard_arrow_right, + color: Colors.black54, + ), + ], + ), + ), + ), + )), + ], + ); + } +} diff --git a/lib/screens/profile/shared/single_attachment.dart b/lib/screens/profile/shared/single_attachment.dart new file mode 100644 index 0000000..3f790da --- /dev/null +++ b/lib/screens/profile/shared/single_attachment.dart @@ -0,0 +1,56 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../../model/profile/attachment.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/alerts.dart'; + +class SingleAttachment extends StatelessWidget { + final Function()? onpressed; + final Attachment attachment; + final Function()? view; + const SingleAttachment({ + required this.attachment, + required this.onpressed, + required this.view, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: + const EdgeInsets.all( + 5), + decoration: box1().copyWith( + color: Colors + .grey + .shade300, + boxShadow: []), + child: + Row( + children: [ + Expanded( + child: + GestureDetector( + onTap: view, + child: AutoSizeText( + attachment.filename!, + wrapWords: false, + maxLines: 1, + ), + ), + ), + const SizedBox( + width: + 8, + ), + GestureDetector( + onTap:onpressed, + child: const Icon(Icons.delete,color: primary,)) + ], + )); + } +} \ No newline at end of file diff --git a/lib/screens/sos/add_mobile.dart b/lib/screens/sos/add_mobile.dart new file mode 100644 index 0000000..8fb0d22 --- /dev/null +++ b/lib/screens/sos/add_mobile.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:unit2/theme-data.dart/text-styles.dart'; +import 'package:unit2/utils/screen_info.dart'; +import '../../theme-data.dart/btn-style.dart'; +import '../../theme-data.dart/colors.dart'; +import '../../theme-data.dart/form-style.dart'; +import '../../utils/global.dart'; +import '../../utils/text_container.dart'; +import '../../utils/validators.dart'; +import '../../widgets/wave.dart'; + +class AddMobile extends StatelessWidget { + AddMobile({super.key}); + final _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + return true; + }, + child: SafeArea( + child: Scaffold( + appBar: AppBar( + title: const Text("Add contact info"), + centerTitle: true, + backgroundColor: primary, + elevation: 0, + ), + resizeToAvoidBottomInset: true, + body: SingleChildScrollView( + child: SizedBox( + height: screenHeight * .90, + child: Stack( + children: [ + Wave(height: blockSizeVertical * 8), + Positioned( + bottom: 0, + right: 0, + child: WaveReverse(height: blockSizeVertical * 8)), + Container( + height: screenHeight, + padding: isMobile() + ? const EdgeInsets.symmetric(horizontal: 24) + : const EdgeInsets.symmetric(horizontal: 60), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: isMobile() + ? screenHeight * .12 + : screenHeight * .20), + SvgPicture.asset( + 'assets/svgs/add_mobile.svg', + height: isMobile() + ? blockSizeVertical * 22 + : blockSizeVertical * 30, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 24, + ), + Text(addMobile, style: titleTextStyle()), + const SizedBox( + height: 8, + ), + Text(addMobileCaption, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.caption), + const SizedBox( + height: 24, + ), + FormBuilder( + key: _formKey, + child: Column( + children: [ + // Mobile number 1 + FormBuilderTextField( + name: 'mobile1', + validator: mobileNumberValidator, + maxLength: 11, + decoration: + normalTextFieldStyle(mobile1, "sfdfsdfsd")), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + name: 'mobile2', + maxLength: 11, + decoration: + normalTextFieldStyle(mobile2, "0900000000000")), + + SizedBox( + height: isMobile() + ? blockSizeVertical * 3 + : blockSizeHorizontal * 5), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle(second, + Colors.transparent, Colors.white54), + child: const Text( + submit, + style: TextStyle(color: Colors.white), + ), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + + } + + // } + }, + ), + ), + ], + )) + ]), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/sos/components/acknnowledge.dart b/lib/screens/sos/components/acknnowledge.dart new file mode 100644 index 0000000..8a771ba --- /dev/null +++ b/lib/screens/sos/components/acknnowledge.dart @@ -0,0 +1,123 @@ +import 'package:animate_do/animate_do.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttericon/iconic_icons.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; + +import '../../../model/sos/session.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/global.dart'; + +class SosAcknowledged extends StatelessWidget { + final Function() onpressed; + final SessionData sessionData; + const SosAcknowledged({super.key, required this.onpressed, required this.sessionData}); + + @override + Widget build(BuildContext context) { + + return Container( + padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 35), + height: screenHeight, + child: Stack( + children: [ + Positioned( + bottom: 0, + child: SizedBox( + width: screenWidth, + height: screenHeight / 2, + child: Opacity( + opacity: .2, + child: Image.asset( + "assets/pngs/emergency.png", + fit: BoxFit.cover, + ), + ), + )), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 18, + ), + SlideInDown( + child: AutoSizeText( + "SOS Acknowledged!", + maxLines: 2, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.displayMedium!.copyWith( + fontSize: 40, + color: success2, + fontWeight: FontWeight.w600), + ), + ), + const SizedBox( + height: 5, + ), + SlideInDown( + child: const Icon( + Iconic.ok_circle, + color: success2, + size: 120, + ), + ), + const SizedBox( + height: 22, + ), + SlideInUp( + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(15))), + child: Column( + children: [ + + + ListTile( + title: AutoSizeText( + sessionData.acknowledgedBy!.toUpperCase(), + maxLines: 2, + style: Theme.of(context).textTheme.headline4!.copyWith( + fontSize: 22, + fontWeight: FontWeight.bold, + color: third), + ), + subtitle: Text( + "Acknowledge by", + style: Theme.of(context).textTheme.labelLarge, + ), + ), + Container( + padding: const EdgeInsets.all(15), + child: Text( + "NOTE: Please ensure that the mobile numbers you provided are still active, and look for an area with stable network. The response team will contact your mobile number.", + textAlign: TextAlign.justify, + style: Theme.of(context).textTheme.caption!.copyWith( + fontSize: 14, + color: Colors.black87, + ), + ), + ), + ], + ), + ), + ), + Expanded(child: Container()), + SlideInUp( + child: SizedBox( + height: 50, + width: double.infinity, + child: ElevatedButton( + style: + mainBtnStyle(second, Colors.transparent, Colors.white54), + onPressed: onpressed, + child: const Text("DONE!")), + ), + ) + ], + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/sos/components/add_mobile.dart b/lib/screens/sos/components/add_mobile.dart new file mode 100644 index 0000000..cec691c --- /dev/null +++ b/lib/screens/sos/components/add_mobile.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/sos/sos_bloc.dart'; +import 'package:unit2/screens/sos/components/request_sos.dart'; +import 'package:unit2/theme-data.dart/text-styles.dart'; +import 'package:unit2/utils/screen_info.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/global.dart'; +import '../../../utils/text_container.dart'; +import '../../../utils/validators.dart'; +import '../../../widgets/wave.dart'; + +class AddMobile extends StatelessWidget { + AddMobile({super.key}); + final _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + + return BlocBuilder( + builder: (context, state) { + if(state is UserLocationLoaded){ + return SingleChildScrollView( + child: SizedBox( + height: screenHeight * .95, + child: Stack( + children: [ + + Positioned( + bottom: 0, + right: 0, + child: WaveReverse(height: blockSizeVertical * 8)), + Container( + height: screenHeight, + padding: isMobile() + ? const EdgeInsets.symmetric(horizontal: 60) + : const EdgeInsets.symmetric(horizontal: 60), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 100,), + SvgPicture.asset( + 'assets/svgs/add_mobile.svg', + height: isMobile() + ? blockSizeVertical * 22 + : blockSizeVertical * 30, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 24, + ), + Text(addMobile,textAlign: TextAlign.center, style: titleTextStyle()), + const SizedBox( + height: 8, + ), + Text(addMobileCaption, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall), + const SizedBox( + height: 24, + ), + FormBuilder( + key: _formKey, + child: Column( + children: [ + //// Mobile number 1 + FormBuilderTextField( + keyboardType: const TextInputType.numberWithOptions(), + autovalidateMode: AutovalidateMode.onUserInteraction, + name: 'mobile1', + validator: mobileNumberValidator, + maxLength: 11, + decoration: + normalTextFieldStyle(mobile1, "+639000000000")), + + //// Mobile number 2 + FormBuilderTextField( + + keyboardType: const TextInputType.numberWithOptions(), + autovalidateMode: AutovalidateMode.onUserInteraction, + name: 'mobile2', + + decoration: + normalTextFieldStyle(mobile2, "+639000000000")), + + const SizedBox(height: 30,), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle(primary, + Colors.transparent, Colors.white54), + child: const Text( + submit, + style: TextStyle(color: Colors.white), + ),//// on pressed + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + String mobile1 = _formKey.currentState!.value['mobile1']; + String? mobile2 = _formKey.currentState!.value['mobile2']; + context.read().add(SubmitMobile(mobile1: mobile1, mobile2: mobile2)); + } + + // } + }, + ), + ), + ], + )) + ]), + ), + ], + ), + ), + ); + } + return Container(); + + }, + ); + } +} diff --git a/lib/screens/sos/components/edit_mobile.dart b/lib/screens/sos/components/edit_mobile.dart new file mode 100644 index 0000000..8270841 --- /dev/null +++ b/lib/screens/sos/components/edit_mobile.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:unit2/main.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/validators.dart'; + +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; + +class EditMobile extends StatelessWidget { + final String initialValue; + final String title; + final String label; + final Function() onpressed; + final Function(String?) onchanged; + const EditMobile( + {super.key, + required this.initialValue, + required this.label, + required this.title, + required this.onpressed, + required this.onchanged}); + + + @override + + Widget build(BuildContext context) { + final formKey = GlobalKey(); + return Container( + height: 300, + padding: const EdgeInsets.all(26), + child: Stack( + children: [ + Positioned( + top: -16, + right: -10, + child: IconButton( + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + icon: const Icon( + Icons.close, + size: 18, + )), + ), + FormBuilder( + key: formKey, + child: Column( + children: [ + Text(title), + const SizedBox( + height: 25, + ), + FormBuilderTextField( + autovalidateMode: AutovalidateMode.onUserInteraction, + name: "mobile", + onChanged: onchanged, + validator: mobileNumberValidator, + keyboardType: TextInputType.number, + initialValue: initialValue, + decoration: normalTextFieldStyle(label, label), + maxLength: 11, + ), + const SizedBox( + height: 25, + ), + SizedBox( + height: 50, + width: 200, + child: ElevatedButton( + onPressed: (){ + if(formKey.currentState!.saveAndValidate()){ + onpressed(); + } + }, + style: mainBtnStyle(success2, Colors.transparent, success), + child: const Text("Submit")), + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/sos/components/mobile.dart b/lib/screens/sos/components/mobile.dart new file mode 100644 index 0000000..bd0c522 --- /dev/null +++ b/lib/screens/sos/components/mobile.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; + +import '../../../theme-data.dart/colors.dart'; + +class Mobile extends StatelessWidget { + final String title; + final String subtitle; + final Function onPressed; + const Mobile({ + super.key, + required this.title, + required this.subtitle, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: const Icon( + FontAwesome5.sim_card, + color: second, + ), + title: Text(title), + subtitle: Text( + subtitle, + style: Theme.of(context).textTheme.caption, + ), + trailing: IconButton( + icon: const Icon(Icons.edit), + onPressed: () { + onPressed(); + }, + ), + ); + } +} diff --git a/lib/screens/sos/components/request_sos.dart b/lib/screens/sos/components/request_sos.dart new file mode 100644 index 0000000..a7510a6 --- /dev/null +++ b/lib/screens/sos/components/request_sos.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttericon/typicons_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/bloc/sos/sos_bloc.dart'; +import 'package:unit2/screens/sos/components/mobile.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; + +import '../../../sevices/sos/sos_service.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/global.dart'; +import 'edit_mobile.dart'; + +class RequestSOS extends StatefulWidget { + const RequestSOS({super.key}); + + @override + State createState() => _RequestSOSState(); +} + +class _RequestSOSState extends State { + final formKey = GlobalKey(); + DateFormat dteFormat = DateFormat("y-M-d H:m:s"); + + String? mobileNumber1; + String? mobileNumber2; + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if(state is RequestSosState){ + return SingleChildScrollView( + child: Container( + height: screenHeight * .82, + padding: const EdgeInsets.symmetric(horizontal: 42, vertical: 10), + child: FormBuilder( + key: formKey, + child: Column( + children: [ + SizedBox( + height: blockSizeVertical * 2, + ), + SvgPicture.asset( + 'assets/svgs/request_sos.svg', + height: blockSizeVertical * 22, + allowDrawingOutsideViewBox: true, + ), + Mobile( + title: state.mobile1, + subtitle: mobile1, + //// edit modal + onPressed: () { + showBottomSheet( + context: context, + builder: (context) { + return EditMobile( + title: "Edit Mobile 1", + label: "Mobile number 1", + initialValue: state.mobile1, + onchanged: (value) { + mobileNumber1 = value; + }, + onpressed: () { + Navigator.of(context, + rootNavigator: true) + .pop(); + BlocProvider.of(context) + .add(SubmitMobile( + mobile1: mobileNumber1!, + mobile2: state.mobile2)); + }, + ); + }); + },), + const Divider(), + ////edit mobile 2 + Mobile( + title: state.mobile2??"N/A", + subtitle: mobile2, + onPressed: () { + showBottomSheet( + context: context, + builder: (context) { + return EditMobile( + title: "Edit Mobile 2", + label: "Mobile number 2", + initialValue: state.mobile2??'', + onchanged: (value) { + mobileNumber2 = value; + }, + onpressed: () { + Navigator.of(context, + rootNavigator: true) + .pop(); + BlocProvider.of(context) + .add(SubmitMobile( + mobile1: state.mobile1, + mobile2: mobileNumber2)); + }, + ); + }); + }), + const Divider(), + ListTile( + leading: const Icon( + Typicons.location, + color: second, + ), + title: Text("${state.locationData.latitude}/${state.locationData.longitude}"), + subtitle: Text( + currentLocation, + style: Theme.of(context).textTheme.bodySmall, + ), + ), + FormBuilderTextField( + name: "message", + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required(errorText: messageRequired) + ]), + autovalidateMode: AutovalidateMode.onUserInteraction, + maxLines: 5, + decoration: normalTextFieldStyle("", sosMessage), + ), + const Expanded( + child: SizedBox(), + ), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle( + primary, Colors.transparent, Colors.white54), + child: const Text( + submit, + style: TextStyle(color: Colors.white), + ), + //// on pressed + onPressed: () async{ + if( formKey.currentState!.saveAndValidate()){ + String message = formKey.currentState!.value['message']; + DateTime today = DateTime.now(); + String requestedDate = + dteFormat.format(today); + BlocProvider.of(context).add(SendSOS(msg: message, requestDate: requestedDate)); + + } + + }, + ), + ), + ], + ), + )), + ); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/sos/components/sos_received.dart b/lib/screens/sos/components/sos_received.dart new file mode 100644 index 0000000..a8bad17 --- /dev/null +++ b/lib/screens/sos/components/sos_received.dart @@ -0,0 +1,133 @@ +import 'package:animate_do/animate_do.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/global.dart'; + +class SOSreceived extends StatelessWidget { + final Function() onpressed; + const SOSreceived({super.key, required this.onpressed}); + + @override + Widget build(BuildContext context) { + + return Container( + padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 35), + height: screenHeight, + child: Stack( + children: [ + Positioned( + bottom: 0, + child: SizedBox( + width: screenWidth, + height: screenHeight / 2, + child: Opacity( + opacity: .2, + child: Image.asset( + "assets/pngs/emergency.png", + fit: BoxFit.cover, + ), + ), + )), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: blockSizeVertical * 6, + ), + Bounce( + from: 20, + infinite: true, + delay: const Duration(milliseconds: 800), + child: Stack( + alignment: AlignmentDirectional.topCenter, + children: [ + Container( + margin: const EdgeInsets.only(top: 20), + child: CircleAvatar( + radius: blockSizeVertical * 8, + backgroundColor: second, + child: Container( + margin: const EdgeInsets.only(top: 25), + child: SvgPicture.asset( + 'assets/svgs/sos.svg', + height: blockSizeHorizontal * 17, + color: Colors.white, + allowDrawingOutsideViewBox: true, + alignment: Alignment.bottomCenter, + ), + ), + ), + ), + Positioned( + top: blockSizeVertical * 3, + child: const SpinKitPulse( + color: primary, + size: 120, + ), + ), + ], + ), + ), + const SizedBox(height: 16), + SlideInUp( + from: 50, + child: AutoSizeText( + sosReceived, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.displayMedium!.copyWith( + fontSize: 40, + color: third, + fontWeight: FontWeight.w500, + ), + ), + ), + const SizedBox( + height: 8, + ), + SlideInUp( + from: 50, + child: Container( + padding: const EdgeInsets.all(15), + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(15))), + child: AutoSizeText( + sOSReceivedMessage, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.caption!.copyWith( + fontSize: 16, + color: Colors.black87, + ), + ), + ), + ), + const SizedBox( + height: 40, + ), + Expanded(child: Container()), + SlideInUp( + child: SizedBox( + height: 50, + width: 200, + child: TextButton( + style: mainBtnStyle(second, Colors.transparent, second), + onPressed: onpressed, + child: const Text(cancelRequest, + style: TextStyle( + color: Colors.white, + )), + ), + ), + ) + ], + ), + ], + ), + ); + } +} diff --git a/lib/screens/sos/index.dart b/lib/screens/sos/index.dart new file mode 100644 index 0000000..cb9dbcc --- /dev/null +++ b/lib/screens/sos/index.dart @@ -0,0 +1,128 @@ +import 'dart:async'; + +import 'package:animate_do/animate_do.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:unit2/bloc/sos/sos_bloc.dart'; +import 'package:unit2/screens/sos/components/acknnowledge.dart'; +import 'package:unit2/screens/sos/components/add_mobile.dart'; +import 'package:unit2/screens/sos/components/request_sos.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../utils/global.dart'; +import '../../widgets/wave.dart'; +import 'components/request_sos.dart'; +import 'components/sos_received.dart'; + +class SosScreen extends StatefulWidget { + const SosScreen({super.key}); + + @override + State createState() => _SosScreenState(); +} + +class _SosScreenState extends State { + Timer? timer; + + @override + void dispose() { + timer != null ? timer!.cancel() : timer = null; + super.dispose(); + } + + @override + void initState() { + timer = Timer(Duration.zero, () {}); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar(title:const Text("SOS"),backgroundColor: primary,centerTitle: true,), + resizeToAvoidBottomInset: true, + body: ProgressHUD( + padding: const EdgeInsets.all(32), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is ErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////loading state + if (state is LoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText(state.message); + } + //// dismiss progress + if (state is ErrorState || state is SOSReceivedState || state is RequestSosState || state is UserLocationLoaded || state is SoSAcknowledgementConfirm) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + //// error state + if (state is ErrorState) { + timer!.cancel(); + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(LoadUserLocation()); + }); + } //// user location loaded + if (state is UserLocationLoaded) { + return AddMobile(); + + //// request sos state + } + if (state is RequestSosState) { + return const RequestSOS(); + } + //// received sos state + if (state is SOSReceivedState) { + timer = Timer.periodic(const Duration(seconds: 10), (timer) { + context.read().add( + CheckAcknowledgement(sessionToken: state.sessionToken)); + }); + return SOSreceived(onpressed: () async { + timer!.cancel(); + await SOS!.delete('session_token'); + Navigator.pop(context); + }); + } + ///// sos acknowledge and confirm + if (state is SoSAcknowledgementConfirm) { + return SosAcknowledged( + onpressed: () async { + timer!.cancel(); + await SOS!.delete('session_token'); + Navigator.pop(context); + }, + sessionData: state.sessionData); + } + return SizedBox( + height: screenHeight, + child: Stack(children: [ + + Positioned( + bottom: 0, + right: 0, + child: WaveReverse(height: blockSizeVertical * 8)) + ]), + ); + }, + ), + ), + )); + } +} diff --git a/lib/screens/superadmin/agency/agency_screen.dart b/lib/screens/superadmin/agency/agency_screen.dart new file mode 100644 index 0000000..0640b76 --- /dev/null +++ b/lib/screens/superadmin/agency/agency_screen.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/agency/agency_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/category.dart'; +import 'package:unit2/utils/formatters.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/Leadings/add_leading.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacAgencyScreen extends StatelessWidget { + const RbacAgencyScreen({super.key}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + List agencyCategory = []; + Category? selectedAgencyCategory; + bool? isPrivate; + final agencyCategoryFocusNode = FocusNode(); + BuildContext parent; + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Agencies"), + actions: [ + AddLeading(onPressed: () { + parent = context; + showDialog( + context: NavigationService.navigatorKey.currentContext!, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add Agency"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + inputFormatters: [UpperCaseTextFormatter()], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "name", + decoration: normalTextFieldStyle( + "Agency name ", "Agency name"), + ), + const SizedBox( + height: 12, + ), + SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 80, + suggestions: agencyCategory + .map((Category category) => + SearchFieldListItem(category.name!, + item: category, + child: ListTile( + title: Text(category.name!), + subtitle: Text( + category.industryClass!.name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text("No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + selectedAgencyCategory = agencyCategory.item; + agencyCategoryFocusNode.unfocus(); + }, + searchInputDecoration: + normalTextFieldStyle("Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode.unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ), + FormBuilderRadioGroup( + decoration: InputDecoration( + border: InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 24), + ), + const Icon(FontAwesome.help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + if (value.toString() == "YES") { + isPrivate = true; + } else { + isPrivate = false; + } + }, + + name: 'isPrivate', + validator: FormBuilderValidators.required(), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption(value: lang)) + .toList(growable: false), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = + formKey.currentState!.value['name']; + Navigator.pop(context); + parent.read().add(AddAgency( + agency: Agency( + category: selectedAgencyCategory, + id: null, + name: name, + privateEntity: isPrivate))); + } + }, + child: const Text("Add")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + print(state); + if (state is AgencyLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is AgenciesLoaded || + state is AgencyAddesState || + state is AgencyErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////Deleted State + if (state is AgencyDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Agency Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetAgencies()); + }); + } else { + errorAlert(context, "Delete Failed", "Object Delete Failed", + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } + } + ////ADDED STATE + if (state is AgencyAddesState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetAgencies()); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); + context.read().add(GetAgencies()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is AgenciesLoaded) { + agencyCategory = state.agencyCategory; + if (state.agencies.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.agencies.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Expanded( + child: Row( + children: [ + CircleAvatar( + child: Text('${index + 1}'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(state.agencies[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Object available. Please click + to add."); + } + } + if (state is AgencyErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + parent.read().add(GetAgencies()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/module/module_screen.dart b/lib/screens/superadmin/module/module_screen.dart new file mode 100644 index 0000000..98d287f --- /dev/null +++ b/lib/screens/superadmin/module/module_screen.dart @@ -0,0 +1,374 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/module/module_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacModuleScreen extends StatelessWidget { + final int id; + const RbacModuleScreen({super.key, required this.id}); + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Module Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Module"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "object_name", + decoration: normalTextFieldStyle( + "Module name *", "Module name "), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "slug", + decoration: normalTextFieldStyle("Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + validator: FormBuilderValidators.maxLength(50, + errorText: "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle("Shorthand ", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = formKey + .currentState!.value['object_name']; + String? slug = + formKey.currentState!.value['slug']; + String? short = formKey + .currentState!.value['shorthand']; + parent.read().add( + AddRbacModule( + id: id, + name: name, + shorthand: short, + slug: slug)); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is ModuleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ModuleLoaded || + state is ModuleErrorState || + state is ModuleAddedState || + state is ModuleDeletedState || + state is ModuleUpdatedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is ModuleAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } + } + ////Updated state + if (state is ModuleUpdatedState) { + if (state.response['success']) { + successAlert( + context, "Updated Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } else { + errorAlert(context, "Update Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } + } + ////Deleted State + if (state is ModuleDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Module Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } else { + errorAlert(context, "Delete Failed", "Module Delete Failed", + () { + Navigator.of(context).pop(); + context.read().add(GetModule()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is ModuleLoaded) { + if (state.module.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.module.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar(child: Text('${index+1}'),), + const SizedBox(width: 12,), + Text(state.module[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 2) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Update Module"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + FormBuilderTextField( + initialValue: state + .module[index].name, + name: "object_name", + decoration: + normalTextFieldStyle( + "Module name *", + "Module name "), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .module[index].slug, + name: "slug", + decoration: + normalTextFieldStyle( + "Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .module[index] + .shorthand, + validator: + FormBuilderValidators + .maxLength(50, + errorText: + "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle( + "Shorthand ", + "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, + Colors + .transparent, + second), + onPressed: () { + if (formKey + .currentState! + .saveAndValidate()) { + String name = formKey + .currentState! + .value[ + 'object_name']; + String? slug = formKey + .currentState! + .value['slug']; + String? short = formKey + .currentState! + .value[ + 'shorthand']; + + ////Update + parent.read().add(UpdateRbacModule( + moduleId: state + .module[ + index] + .id!, + name: name, + slug: slug, + short: + short, + createdBy: state + .module[ + index] + .createdBy + ?.id, + updatedBy: + id)); + Navigator.pop( + context); + } + }, + child: const Text( + "Update"))), + ], + ), + ), + ); + }); + } + if (value == 1) { + ////delete + confirmAlert(context, () { + context.read().add( + DeleteRbacModule( + moduleId: + state.module[index].id!)); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 2, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is ModuleErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetModule()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/module_objects/module_objects_screen.dart b/lib/screens/superadmin/module_objects/module_objects_screen.dart new file mode 100644 index 0000000..e63f33c --- /dev/null +++ b/lib/screens/superadmin/module_objects/module_objects_screen.dart @@ -0,0 +1,301 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:group_list_view/group_list_view.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/module_objects/module_objects_bloc.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../model/rbac/rbac.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global_context.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacModuleObjectsScreen extends StatelessWidget { + final int id; + const RbacModuleObjectsScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final parent = context; + Map> moduleObjects = {}; + List modules = []; + List objects = []; + RBAC? selectedModule; + List valueItemObjects = []; + List selectedValueItemObjects = []; + final formKey = GlobalKey(); + return Scaffold( + + appBar: AppBar( + centerTitle: true, + elevation: 0, + backgroundColor: primary, + title: const Text("Module Object Screen"), + actions: [ + AddLeading(onPressed: () { + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (BuildContext context) { + valueItemObjects = objects.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add New Module Object"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "module", + decoration: + normalTextFieldStyle("Module", "Module"), + items: modules.isEmpty + ? [] + : modules.map((e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + onChanged: (RBAC? object) { + selectedModule = object; + }, + ), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemObjects = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Objects", + padding: const EdgeInsets.all(8), + options: valueItemObjects, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate() && + selectedValueItemObjects.isNotEmpty) { + int assignerId = id; + int moduleId = selectedModule!.id!; + List objectId = []; + for (var object in objects) { + selectedValueItemObjects + .forEach((element) { + if (element.label.toLowerCase() == + object.name?.toLowerCase()) { + objectId.add(object.id!); + } + }); + } + Navigator.of(context).pop(); + parent.read().add( + AddRbacModuleObjects( + assignerId: assignerId, + moduleId: moduleId, + objectsId: objectId)); + } + }, + child: const Text("Submit")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + + if (state is ModuleObjectLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ModuleObjectLoadedState || + state is ModuleObjectsErrorState || + state is ModuleObjectAddedState || + state is ModuleObjectDeletedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////Deleted State + if (state is ModuleObjectDeletedState) { + if (state.success) { + successAlert( + context, "Delete Successfull!", "Role Deleted Successfully", + () { + Navigator.of(context).pop(); + context.read().add(GetModuleObjects()); + }); + } else { + errorAlert(context, "Delete Failed", "Role Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetModuleObjects()); + }); + } + } + ////Added State + if (state is ModuleObjectAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModuleObjects()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetModuleObjects()); + }); + } + } + }, + builder: (context, state) { + if (state is ModuleObjectLoadedState) { + modules = state.modules; + objects = state.objecs; + moduleObjects = {}; + if (state.moduleObjects.isNotEmpty) { + for (var modObjects in state.moduleObjects) { + if (!moduleObjects.keys + .contains(modObjects.module.name!.toLowerCase())) { + moduleObjects + .addAll({modObjects.module.name!.toLowerCase(): []}); + moduleObjects[modObjects.module.name!.toLowerCase()]!.add( + Content( + id: modObjects.id, name: modObjects.object.name!)); + } else { + moduleObjects[modObjects.module.name!.toLowerCase()]!.add( + Content( + id: modObjects.id, name: modObjects.object.name!)); + } + } + } + + if (state.moduleObjects.isNotEmpty) { + return GroupListView( + sectionsCount: moduleObjects.keys.toList().length, + countOfItemInSection: (int section) { + return moduleObjects.values.toList()[section].length; + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + itemBuilder: (BuildContext context, IndexPath index) { + return ListTile( + trailing: IconButton( + color: Colors.grey.shade600, + icon: const Icon(Icons.delete), + onPressed: () { + confirmAlert(context, () { + context.read().add( + DeleteRbacModuleObject( + moduleObjectId: moduleObjects.values + .toList()[index.section][index.index] + .id)); + }, "Delete?", "Confirm Delete?"); + }, + ), + title: Row( + children: [ + CircleAvatar( + child: Text("${index.index + 1}", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white))), + const SizedBox( + width: 20, + ), + Expanded( + child: Text( + moduleObjects.values + .toList()[index.section][index.index] + .name + .toUpperCase(), + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith( + fontWeight: FontWeight.w600, + color: primary), + ), + ), + ], + ), + ); + }, + groupHeaderBuilder: (BuildContext context, int section) { + return ListTile( + tileColor: second, + title: Text( + moduleObjects.keys.toList()[section].toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: Colors.white), + ), + ); + }, + ); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is ModuleObjectsErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + parent.read().add(GetModuleObjects()); + }); + } + return Container(); + }, + ), + ), + ); + } +} + +class Content { + final int id; + final String name; + const Content({required this.id, required this.name}); +} diff --git a/lib/screens/superadmin/object/object_screen.dart b/lib/screens/superadmin/object/object_screen.dart new file mode 100644 index 0000000..7a4640c --- /dev/null +++ b/lib/screens/superadmin/object/object_screen.dart @@ -0,0 +1,377 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/Leadings/add_leading.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacObjectScreen extends StatelessWidget { + final int id; + const RbacObjectScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Objects Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Object"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "object_name", + decoration: normalTextFieldStyle( + "Object name *", "Object name "), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "slug", + decoration: normalTextFieldStyle("Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + validator: FormBuilderValidators.maxLength(50, + errorText: "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle("Shorthand ", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = formKey + .currentState!.value['object_name']; + String? slug = + formKey.currentState!.value['slug']; + String? short = formKey + .currentState!.value['shorthand']; + parent.read().add( + AddRbacObject( + id: id, + name: name, + shorthand: short, + slug: slug)); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is ObjectLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is ObjectLoaded || + state is ObjectAddedState || + state is ObjectErrorState || + state is ObjectUpdatedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is ObjectAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } + } + ////Updated state + if (state is ObjectUpdatedState) { + if (state.response['success']) { + successAlert( + context, "Updated Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } else { + errorAlert(context, "Update Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } + } + ////Deleted State + if (state is ObjectDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Object Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } else { + errorAlert(context, "Delete Failed", "Object Delete Failed", + () { + Navigator.of(context).pop(); + context.read().add(GetObjects()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is ObjectLoaded) { + if (state.objects.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.objects.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar( + child: Text('${index + 1}'), + ), + const SizedBox( + width: 12, + ), + Text(state.objects[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 2) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: + const Text("Update Object"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + FormBuilderTextField( + initialValue: state + .objects[index].name, + name: "object_name", + decoration: + normalTextFieldStyle( + "Object name *", + "Object name "), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .objects[index].slug, + name: "slug", + decoration: + normalTextFieldStyle( + "Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .objects[index] + .shorthand, + validator: + FormBuilderValidators + .maxLength(50, + errorText: + "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle( + "Shorthand ", + "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, + Colors + .transparent, + second), + onPressed: () { + if (formKey + .currentState! + .saveAndValidate()) { + String name = formKey + .currentState! + .value[ + 'object_name']; + String? slug = formKey + .currentState! + .value['slug']; + String? short = formKey + .currentState! + .value[ + 'shorthand']; + + parent.read().add(UpdateRbacObject( + objectId: state + .objects[ + index] + .id!, + name: name, + slug: slug, + short: + short, + createdBy: state + .objects[ + index] + .createdBy + ?.id, + updatedBy: + id)); + Navigator.pop( + context); + } + }, + child: const Text( + "Update"))), + ], + ), + ), + ); + }); + } + if (value == 1) { + confirmAlert(context, () { + context.read().add( + DeleteRbacObject( + objectId: + state.objects[index].id!)); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 2, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Object available. Please click + to add."); + } + } + if (state is ObjectErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetObjects()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/operation/operation_screen.dart b/lib/screens/superadmin/operation/operation_screen.dart new file mode 100644 index 0000000..6b4a6bb --- /dev/null +++ b/lib/screens/superadmin/operation/operation_screen.dart @@ -0,0 +1,374 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/operation/operation_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/Leadings/add_leading.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacOperationScreen extends StatelessWidget { + final int id; + const RbacOperationScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + title: const Text("Operations Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Operation"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "object_name", + decoration: normalTextFieldStyle( + "Operation name *", "Operation name "), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "slug", + decoration: normalTextFieldStyle("Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + validator: FormBuilderValidators.maxLength(50, + errorText: "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle("Shorthand ", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = formKey + .currentState!.value['object_name']; + String? slug = + formKey.currentState!.value['slug']; + String? short = formKey + .currentState!.value['shorthand']; + parent.read().add( + AddRbacOperation( + id: id, + name: name, + shorthand: short, + slug: slug)); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is OperationLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is OperationsLoaded || + state is OperationErrorState || + state is OperationAddedState || + state is OperationUpdatedState || + state is OperationDeletedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is OperationAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } + } + ////Updated state + if (state is OperationUpdatedState) { + if (state.response['success']) { + successAlert( + context, "Updated Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } else { + errorAlert(context, "Update Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } + } + ////Deleted State + if (state is OperationDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Operation Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } else { + errorAlert(context, "Delete Failed", "Operation Delete Failed", + () { + Navigator.of(context).pop(); + context.read().add(GetOperations()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is OperationsLoaded) { + if (state.operations.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.operations.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar(child: Text('${index+1}'),), + const SizedBox(width: 12,), + Text(state.operations[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 2) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Update Operation"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + FormBuilderTextField( + initialValue: state + .operations[index] + .name, + name: "object_name", + decoration: + normalTextFieldStyle( + "Operation name *", + "Operation name "), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .operations[index] + .slug, + name: "slug", + decoration: + normalTextFieldStyle( + "Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .operations[index] + .shorthand, + validator: + FormBuilderValidators + .maxLength(50, + errorText: + "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle( + "Shorthand ", + "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, + Colors + .transparent, + second), + onPressed: () { + if (formKey + .currentState! + .saveAndValidate()) { + String name = formKey + .currentState! + .value[ + 'object_name']; + String? slug = formKey + .currentState! + .value['slug']; + String? short = formKey + .currentState! + .value[ + 'shorthand']; + + parent.read().add(UpdateRbacOperation( + operationId: state + .operations[ + index] + .id!, + name: name, + slug: slug, + short: + short, + createdBy: state + .operations[ + index] + .createdBy + ?.id, + updatedBy: + id)); + Navigator.pop( + context); + } + }, + child: const Text( + "Update"))), + ], + ), + ), + ); + }); + } + if (value == 1) { + confirmAlert(context, () { + context.read().add( + DeleteRbacOperation( + operationId: state + .operations[index].id!)); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 2, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is OperationErrorState) { + return SomethingWentWrong( + message: state.message.toString(), + onpressed: () { + context.read().add(GetOperations()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/permission/permission_screen.dart b/lib/screens/superadmin/permission/permission_screen.dart new file mode 100644 index 0000000..0400599 --- /dev/null +++ b/lib/screens/superadmin/permission/permission_screen.dart @@ -0,0 +1,286 @@ +import 'dart:math'; +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/permission/permission_bloc.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacPermissionScreen extends StatelessWidget { + final int id; + const RbacPermissionScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + List objects = []; + RBAC? selectedObject; + List operations = []; + List valueItemOperations = []; + List selectedValueItemOperations = []; + final formKey = GlobalKey(); + BuildContext? parent; + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Permissions Screen"), + actions: [ + AddLeading(onPressed: () { + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (BuildContext context) { + valueItemOperations = operations.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add Permission"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "object", + decoration: + normalTextFieldStyle("Permission", "Permission"), + items: objects.isEmpty + ? [] + : objects.map((e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + onChanged: (RBAC? object) { + selectedObject = object; + }, + ), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemOperations = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Operations", + padding: const EdgeInsets.all(8), + options: valueItemOperations, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate() && + selectedValueItemOperations + .isNotEmpty) { + int assignerId = id; + int objectId = selectedObject!.id!; + + List opIds = []; + for (var operation in operations) { + selectedValueItemOperations + .forEach((element) { + if (element.label.toLowerCase() == + operation.name?.toLowerCase()) { + opIds.add(operation.id!); + } + }); + } + opIds.forEach((element) { + print(element); + }); + Navigator.pop(context); + parent!.read().add( + AddRbacPermission( + assignerId: assignerId, + objectId: objectId, + operationIds: opIds)); + } + }, + child: const Text("Submit")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is PermissonLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is PermissionLoaded || + state is PermissionErrorState || + state is PermissionAddedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is PermissionAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetPermissions()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetPermissions()); + }); + } + } + ////Deleted State + if (state is PermissionDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Permission Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetPermissions()); + }); + } else { + errorAlert(context, "Delete Failed", "Permission Delete Failed", + () { + Navigator.of(context).pop(); + context.read().add(GetPermissions()); + }); + } + } + }, + builder: (context, state) { + parent = context; + if (state is PermissionLoaded) { + objects = state.objects; + operations = state.operations; + if (state.permissions.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.permissions.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar( + child: Text('${index + 1}'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + "${state.permissions[index].object?.name} - ${state.permissions[index].operation?.name}", + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 1) { + + confirmAlert(context, () { + context.read().add( + DeleteRbacPermission( + permissionId: state.permissions[index].id!)); + }, "Delete?", "Confirm Delete?"); + + } + }, + menuItems: [ + + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Permission available. Please click + to add."); + } + } + if (state is PermissionErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + parent!.read().add(GetPermissions()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/role/role_screen.dart b/lib/screens/superadmin/role/role_screen.dart new file mode 100644 index 0000000..5c65a71 --- /dev/null +++ b/lib/screens/superadmin/role/role_screen.dart @@ -0,0 +1,373 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../theme-data.dart/box_shadow.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacRoleScreen extends StatelessWidget { + final int id; + const RbacRoleScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Role Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Role"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "object_name", + decoration: normalTextFieldStyle( + "Role name *", "Role name "), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "slug", + decoration: normalTextFieldStyle("Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + validator: FormBuilderValidators.maxLength(50, + errorText: "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle("Shorthand ", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = formKey + .currentState!.value['object_name']; + String? slug = + formKey.currentState!.value['slug']; + String? short = formKey + .currentState!.value['shorthand']; + parent.read().add(AddRbacRole( + id: id, + name: name, + shorthand: short, + slug: slug)); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is RoleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is RoleLoadedState || + state is RoleErrorState || + state is RoleAddedState || + state is RoleDeletedState || + state is RoleUpdatedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is RoleAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } + } + ////Updated state + if (state is RoleUpdatedState) { + if (state.response['success']) { + successAlert( + context, "Updated Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } else { + errorAlert(context, "Update Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } + } + ////Deleted State + if (state is RoleDeletedState) { + if (state.success) { + successAlert( + context, "Delete Successfull!", "Role Deleted Successfully", + () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } else { + errorAlert(context, "Delete Failed", "Role Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetRoles()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is RoleLoadedState) { + if (state.roles.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.roles.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar(child: Text('${index+1}'),), + const SizedBox(width: 12,), + Flexible( + child: Text(state.roles[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 2) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Update Role"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + FormBuilderTextField( + initialValue: state + .roles[index].name, + name: "object_name", + decoration: + normalTextFieldStyle( + "Role name *", + "Role name "), + validator: + FormBuilderValidators + .required( + errorText: + "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .roles[index].slug, + name: "slug", + decoration: + normalTextFieldStyle( + "Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + initialValue: state + .roles[index] + .shorthand, + validator: + FormBuilderValidators + .maxLength(50, + errorText: + "Max characters only 50"), + name: "shorthand", + decoration: + normalTextFieldStyle( + "Shorthand ", + "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, + Colors + .transparent, + second), + onPressed: () { + if (formKey + .currentState! + .saveAndValidate()) { + String name = formKey + .currentState! + .value[ + 'object_name']; + String? slug = formKey + .currentState! + .value['slug']; + String? short = formKey + .currentState! + .value[ + 'shorthand']; + + parent.read().add(UpdateRbacRole( + roleId: state + .roles[ + index] + .id!, + name: name, + slug: slug, + short: + short, + createdBy: state + .roles[ + index] + .createdBy + ?.id, + updatedBy: + id)); + Navigator.pop( + context); + } + }, + child: const Text( + "Update"))), + ], + ), + ), + ); + }); + } + if (value == 1) { + confirmAlert(context, () { + context.read().add( + DeleteRbacRole( + roleId: + state.roles[index].id!)); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Update", + value: 2, + icon: Icons.edit), + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is RoleErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetRoles()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/role/shared_pop_up_menu.dart b/lib/screens/superadmin/role/shared_pop_up_menu.dart new file mode 100644 index 0000000..3359c56 --- /dev/null +++ b/lib/screens/superadmin/role/shared_pop_up_menu.dart @@ -0,0 +1,21 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; + +PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); +} \ No newline at end of file diff --git a/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart b/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart new file mode 100644 index 0000000..8feade2 --- /dev/null +++ b/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart @@ -0,0 +1,287 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/bloc/role_assignment/role_assignment_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../model/rbac/rbac.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacRoleAssignment extends StatelessWidget { + final int id; + final String name; + final String lname; + const RbacRoleAssignment({super.key, required this.id, required this.lname, required this.name}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + List roles = []; + List valueItemRoles = []; + List selectedValueItemRoles = []; + return Scaffold( + appBar: AppBar( + elevation: 0, + centerTitle: true, + backgroundColor: primary, + title: const Text("User Roles Screenss"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + valueItemRoles = roles.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add New Role"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemRoles = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Select Roles", + padding: const EdgeInsets.all(8), + options: valueItemRoles, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + List rolesId = []; + for (var role in roles) { + selectedValueItemRoles + .forEach((element) { + if (element.label.toLowerCase() == + role.name?.toLowerCase()) { + rolesId.add(role.id!); + } + }); + } + parent + .read() + .add(AssignRole( + assignerId: id, + roles: rolesId, + )); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is RoleAssignmentLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is AssignedRoleLoaded || + state is RoleAssignmentErrorState || + state is AssignedRoleDeletedState || + state is UserNotExistError || state is AssignedRoleAddedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Deleted State + if (state is AssignedRoleDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Role Module Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(LoadAssignedRole()); + }); + } else { + errorAlert( + context, "Delete Failed", "Role Module Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(LoadAssignedRole()); + }); + } + } + + ////Added State + if (state is AssignedRoleAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(LoadAssignedRole()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(LoadAssignedRole()); + }); + } + } + }, + builder: (context, state) { + final parent = context; + if (state is AssignedRoleLoaded) { + + roles = state.roles; + if (state.assignedRoles.isNotEmpty) { + return Column( + children: [ + ListTile( + tileColor: second, + leading: const Icon( + FontAwesome5.user_alt, + color: Colors.white, + ), + title: Text(state.fullname.toUpperCase(), + style: Theme.of(context) + .textTheme + .titleLarge! + .copyWith(color: Colors.white)), + subtitle: Text("Person full name", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white)), + ), + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.assignedRoles.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar( + child: Text('${index + 1}'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + state.assignedRoles[index].role! + .name, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500, + color: primary)), + ), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 1) { + confirmAlert(context, () { + context + .read() + .add(DeleteAssignRole( + roleId: state + .assignedRoles[index].id! + )); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const Divider(), + ], + ); + }), + ), + ], + ); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is RoleAssignmentErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetAssignedRoles(firstname: name,lastname: lname)); + }); + } + if (state is UserNotExistError) { + return const Center( + child: Text("User Not Exsit"), + ); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/role_extend/role_extend_screen.dart b/lib/screens/superadmin/role_extend/role_extend_screen.dart new file mode 100644 index 0000000..ffe490c --- /dev/null +++ b/lib/screens/superadmin/role_extend/role_extend_screen.dart @@ -0,0 +1,299 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:group_list_view/group_list_view.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role_extend/role_extend_bloc.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../model/rbac/rbac.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global_context.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacRoleExtendScreen extends StatelessWidget { + final int id; + const RbacRoleExtendScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final parent = context; + Map> rolesExtend = {}; + List roles = []; + RBAC? selectedRole; + List valueItemRoles = []; + List selectedValueItemRoles = []; + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + elevation: 0, + backgroundColor: primary, + title: const Text("Role Extend"), + actions: [ + AddLeading(onPressed: () { + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (BuildContext context) { + valueItemRoles = roles.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add Role Extend"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "role", + decoration: normalTextFieldStyle( + "Role Extend Main", "Role Extend Main"), + items: roles.isEmpty + ? [] + : roles.map((e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + onChanged: (RBAC? role) { + selectedRole = role; + }, + ), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemRoles = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Roles Extend", + padding: const EdgeInsets.all(8), + options: valueItemRoles, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate() && + selectedValueItemRoles.isNotEmpty) { + int roleId = selectedRole!.id!; + List rolesId = []; + for (var role in roles) { + selectedValueItemRoles + .forEach((element) { + if (element.label.toLowerCase() == + role.name?.toLowerCase()) { + rolesId.add(role.id!); + } + }); + } + Navigator.of(context).pop(); + rolesExtend = {}; + parent.read().add( + AddRoleExtend( + roleId: roleId, + roleExtendsId: rolesId)); + } + }, + child: const Text("Submit")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is RoleExtendLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is RoleExtendLoadedState || + state is RoleExtendAddedState || + state is RoleExtendDeletedState || + state is RoleExtendErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////Deleted State + if (state is RoleExtendDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Role Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetRoleExtend()); + }); + } else { + errorAlert( + context, "Delete Failed", "Role Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetRoleExtend()); + }); + } + } + ////Added State + if (state is RoleExtendAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoleExtend()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoleExtend()); + }); + } + } + }, + builder: (context, state) { + if (state is RoleExtendLoadedState) { + rolesExtend = {}; + roles = state.roles; + + if (state.rolesExtend.isNotEmpty) { + for (var roleExt in state.rolesExtend) { + if (!rolesExtend.keys + .contains(roleExt.roleExtendMain.name!.toLowerCase())) { + rolesExtend.addAll( + {roleExt.roleExtendMain.name!.toLowerCase(): []}); + rolesExtend[roleExt.roleExtendMain.name!.toLowerCase()]! + .add(Content( + id: roleExt.id, + name: roleExt.roleExtendChild.name!)); + } else { + rolesExtend[roleExt.roleExtendMain.name!.toLowerCase()]! + .add(Content( + id: roleExt.id, + name: roleExt.roleExtendChild.name!)); + } + } + } + + if (state.rolesExtend.isNotEmpty) { + return GroupListView( + padding: const EdgeInsets.all(0), + sectionsCount: rolesExtend.keys.toList().length, + countOfItemInSection: (int section) { + return rolesExtend.values.toList()[section].length; + }, + itemBuilder: (BuildContext context, IndexPath index) { + return ListTile( + dense: true, + trailing: IconButton( + color: Colors.grey.shade600, + icon: const Icon(Icons.delete), + onPressed: () { + confirmAlert(context, () { + context.read().add(DeleteRoleExtend( + roleExtendId: rolesExtend.values + .toList()[index.section][index.index] + .id)); + }, "Delete?", "Confirm Delete?"); + }, + ), + title: Row( + children: [ + CircleAvatar( + child: Text("${index.index + 1}", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white))), + const SizedBox( + width: 20, + ), + Expanded( + child: Text( + rolesExtend.values + .toList()[index.section][index.index] + .name + .toUpperCase(), + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith( + fontWeight: FontWeight.w500, + color: primary), + ), + ), + ], + ), + ); + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + groupHeaderBuilder: (BuildContext context, int section) { + return ListTile( + tileColor: second, + title: Text( + rolesExtend.keys.toList()[section].toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: Colors.white), + ), + ); + }, + ); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is RoleExtendErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetRoleExtend()); + }); + } + return Container(); + }, + ), + ), + ); + } +} + +class Content { + final int id; + final String name; + const Content({required this.id, required this.name}); +} diff --git a/lib/screens/superadmin/role_module/role_module_scree.dart b/lib/screens/superadmin/role_module/role_module_scree.dart new file mode 100644 index 0000000..1f3b199 --- /dev/null +++ b/lib/screens/superadmin/role_module/role_module_scree.dart @@ -0,0 +1,289 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:group_list_view/group_list_view.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role_module/role_module_bloc.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../model/rbac/rbac.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global_context.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacRoleModuleScreen extends StatelessWidget { + final int id; + const RbacRoleModuleScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final parent = context; + Map> roleModules = {}; + List modules = []; + List roles = []; + RBAC? selectedRole; + List valueItemModules = []; + List selectedValueItemModules = []; + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + title: const Text("Role Modules Screen"), + actions: [ + AddLeading(onPressed: () { + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (BuildContext context) { + valueItemModules = modules.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add Role Module"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "role", + decoration: normalTextFieldStyle("Role", "Role"), + items: roles.isEmpty + ? [] + : roles.map((e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + onChanged: (RBAC? role) { + selectedRole = role; + }, + ), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemModules = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Modules", + padding: const EdgeInsets.all(8), + options: valueItemModules, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate() && + selectedValueItemModules.isNotEmpty) { + int assignerId = id; + int roleId = selectedRole!.id!; + List modulesId = []; + for (var module in modules) { + selectedValueItemModules + .forEach((element) { + if (element.label.toLowerCase() == + module.name?.toLowerCase()) { + modulesId.add(module.id!); + } + }); + } + Navigator.of(context).pop(); + parent.read().add( + AddRoleModule( + assignerId: assignerId, + roleId: roleId, + moduleIds: modulesId)); + } + }, + child: const Text("Submit")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is RoleModuleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is RoleModuleLoadedState || + state is RoleModuleErrorState || + state is RoleModuleDeletedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////Deleted State + if (state is RoleModuleDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Role Module Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetRoleModules()); + }); + } else { + errorAlert( + context, "Delete Failed", "Role Module Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetRoleModules()); + }); + } + } + ////Added State + if (state is RoleModuleAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoleModules()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRoleModules()); + }); + } + } + }, + builder: (context, state) { + if (state is RoleModuleLoadedState) { + modules = state.modules; + roles = state.roles; + roleModules = {}; + if (state.roleModules.isNotEmpty) { + for (var roleMod in state.roleModules) { + if (!roleModules.keys + .contains(roleMod.role!.name!.toLowerCase())) { + roleModules.addAll({roleMod.role!.name!.toLowerCase(): []}); + roleModules[roleMod.role!.name!.toLowerCase()]!.add( + Content(id: roleMod.id!, name: roleMod.module!.name!)); + } else { + roleModules[roleMod.role!.name!.toLowerCase()]!.add( + Content(id: roleMod.id!, name: roleMod.module!.name!)); + } + } + } + + if (state.roleModules.isNotEmpty) { + return GroupListView( + sectionsCount: roleModules.keys.toList().length, + countOfItemInSection: (int section) { + return roleModules.values.toList()[section].length; + }, + itemBuilder: (BuildContext context, IndexPath index) { + return ListTile( + dense: true, + trailing: IconButton( + color: Colors.grey.shade600, + icon: const Icon(Icons.delete), + onPressed: () { + confirmAlert(context, () { + context.read().add(DeleteRoleModule( + roleModuleId: roleModules.values + .toList()[index.section][index.index] + .id)); + }, "Delete?", "Confirm Delete?"); + }, + ), + title: Row( + children: [ + CircleAvatar( + child: Text("${index.index + 1}", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white))), + const SizedBox( + width: 20, + ), + Expanded( + child: Text( + roleModules.values + .toList()[index.section][index.index] + .name + .toUpperCase(), + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: primary), + ), + ), + ], + ), + ); + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + groupHeaderBuilder: (BuildContext context, int section) { + return ListTile( + tileColor: second, + title: Text( + roleModules.keys.toList()[section].toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: Colors.white), + ), + ); + }, + ); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is RoleModuleErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetRoleModules()); + }); + } + return Container(); + }, + ), + ), + ); + } +} + +class Content { + final int id; + final String name; + const Content({required this.id, required this.name}); +} diff --git a/lib/screens/superadmin/roles_under/roles_under_screen.dart b/lib/screens/superadmin/roles_under/roles_under_screen.dart new file mode 100644 index 0000000..6f82a78 --- /dev/null +++ b/lib/screens/superadmin/roles_under/roles_under_screen.dart @@ -0,0 +1,296 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:group_list_view/group_list_view.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../model/rbac/rbac.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global_context.dart'; +import '../../../widgets/empty_data.dart'; + +class RbacRoleUnderScreen extends StatelessWidget { + final int id; + const RbacRoleUnderScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final parent = context; + Map> rolesUnder = {}; + List roles = []; + RBAC? selectedRole; + List valueItemRoles = []; + List selectedValueItemRoles = []; + final formKey = GlobalKey(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Assignable Roles"), + actions: [ + AddLeading(onPressed: () { + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (BuildContext context) { + valueItemRoles = roles.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + return AlertDialog( + title: const Text("Add Role Under"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "role", + decoration: normalTextFieldStyle( + "Main Role", "Main Role"), + items: roles.isEmpty + ? [] + : roles.map((e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + onChanged: (RBAC? role) { + selectedRole = role; + }, + ), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemRoles = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Roles Under", + padding: const EdgeInsets.all(8), + options: valueItemRoles, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate() && + selectedValueItemRoles.isNotEmpty) { + int assignerId = id; + int roleId = selectedRole!.id!; + List rolesId = []; + for (var role in roles) { + selectedValueItemRoles + .forEach((element) { + if (element.label.toLowerCase() == + role.name?.toLowerCase()) { + rolesId.add(role.id!); + } + }); + } + Navigator.of(context).pop(); + parent.read().add( + AddRoleUnder( + roleId: roleId, + roleUnderIds: rolesId)); + } + }, + child: const Text("Submit")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is RoleUnderLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is RoleUnderLoadedState || + state is RoleUnderErrorState || + state is RoleUnderDeletedState || + state is RoleUnderAddedState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + + ////Deleted State + if (state is RoleUnderDeletedState) { + if (state.success) { + successAlert(context, "Delete Successfull!", + "Role Deleted Successfully", () { + Navigator.of(context).pop(); + context.read().add(GetRolesUnder()); + }); + } else { + errorAlert( + context, "Delete Failed", "Role Module Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetRolesUnder()); + }); + } + } + ////Added State + if (state is RoleUnderAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRolesUnder()); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetRolesUnder()); + }); + } + } + }, + builder: (context, state) { + if (state is RoleUnderLoadedState) { + rolesUnder = {}; + roles = state.roles; + + if (state.rolesUnder.isNotEmpty) { + for (var roleUnder in state.rolesUnder) { + if (!rolesUnder.keys + .contains(roleUnder.roleUnderMain.name!.toLowerCase())) { + rolesUnder.addAll( + {roleUnder.roleUnderMain.name!.toLowerCase(): []}); + rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]! + .add(Content( + id: roleUnder.id, + name: roleUnder.roleUnderChild.name!)); + } else { + rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]! + .add(Content( + id: roleUnder.id, + name: roleUnder.roleUnderChild.name!)); + } + } + } + + if (state.rolesUnder.isNotEmpty) { + return GroupListView( + sectionsCount: rolesUnder.keys.toList().length, + countOfItemInSection: (int section) { + return rolesUnder.values.toList()[section].length; + }, + itemBuilder: (BuildContext context, IndexPath index) { + return ListTile( + trailing: IconButton( + color: Colors.grey.shade500, + icon: const Icon(Icons.delete), + onPressed: () { + context.read().add(DeleteRoleUnder( + roleUnderId: rolesUnder.values + .toList()[index.section][index.index] + .id)); + }, + ), + title: Row( + children: [ + CircleAvatar( + child: Text("${index.index + 1}", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white))), + const SizedBox( + width: 20, + ), + Expanded( + child: Text( + rolesUnder.values + .toList()[index.section][index.index] + .name + .toUpperCase(), + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith( + fontWeight: FontWeight.w500, + color: primary) + ), + ), + ], + ), + ); + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + groupHeaderBuilder: (BuildContext context, int section) { + return ListTile( +tileColor: Colors.white, + dense: true, + title: Text( + rolesUnder.keys.toList()[section].toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: primary,fontWeight: FontWeight.bold), + ), + ); + }, + ); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is RoleUnderErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetRolesUnder()); + }); + } + return Container(); + }, + ), + ), + ); + } +} + +class Content { + final int id; + final String name; + const Content({required this.id, required this.name}); +} diff --git a/lib/screens/superadmin/stations/stations_screen.dart b/lib/screens/superadmin/stations/stations_screen.dart new file mode 100644 index 0000000..6bfa28d --- /dev/null +++ b/lib/screens/superadmin/stations/stations_screen.dart @@ -0,0 +1,885 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/station/station_bloc.dart'; +import 'package:unit2/model/rbac/rbac_station.dart'; +import 'package:unit2/model/utils/agency.dart'; +import 'package:unit2/model/utils/position.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../model/rbac/station_type.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../utils/global.dart'; +import '../../../../widgets/empty_data.dart'; +import '../../../utils/formatters.dart'; +import '../../profile/shared/add_for_empty_search.dart'; + +class RbacStationScreen extends StatefulWidget { + final int agencyId; + const RbacStationScreen({ + required this.agencyId, + super.key, + }); + + @override + State createState() => _RbacStationScreenState(); +} + +class _RbacStationScreenState extends State { + @override + Widget build(BuildContext context) { + final rbacStationBloc = BlocProvider.of(context); + List stations = []; + final formKey = GlobalKey(); + List> hierarchy = []; + bool mainParent = false; + bool isWithinParent = true; + bool isHospital = false; + List stationTypes = []; + List positions = []; + List mainParentStations = []; + List parentStations = []; + List agencies = []; + RbacStation? selectedMainParentStation; + RbacStation? selectedParentStation; + StationType? selectedStationType; + PositionTitle? selectedPositiontitle; + int selectedAgencyId = widget.agencyId; + final addStationTypeController = TextEditingController(); + final stationTypeFocusNode = FocusNode(); + final agencyFocusNode = FocusNode(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Station Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + mainParentStations = []; + mainParent = stations.isEmpty ? true : false; + for (RbacStation station in stations) { + if (station.hierarchyOrderNo == 1) { + mainParentStations.add(station); + } + } + + /////Add new tation + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Station"), + content: SingleChildScrollView( + child: FormBuilder( + key: formKey, + child: StatefulBuilder(builder: (context, setState) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////is main parent + FormBuilderSwitch( + initialValue: mainParent, + activeColor: second, + onChanged: (value) { + setState(() { + mainParent = !mainParent; + }); + }, + decoration: normalTextFieldStyle( + "is Main Parent?", 'is Main Parent?'), + name: 'main-parent', + title: Text(mainParent ? "YES" : "NO"), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + SizedBox( + height: mainParent ? 0 : 8, + ), + //// selected main parent + SizedBox( + child: mainParent == true + ? const SizedBox.shrink() + : FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Main Parent Station", + "Main Parent Station"), + name: "parent-stations", + items: mainParentStations.isEmpty + ? [] + : mainParentStations.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.stationName!), + ); + }).toList(), + onChanged: (RbacStation? e) { + setState(() { + selectedMainParentStation = e; + parentStations = []; + for (RbacStation station + in stations) { + if (station.mainParentStation == + selectedMainParentStation! + .id) { + parentStations.add(station); + } + } + parentStations.add( + selectedMainParentStation!); + }); + }, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + ), + ), + SizedBox( + height: mainParent ? 0 : 8, + ), + ////parent station + SizedBox( + child: mainParent == true + ? const SizedBox.shrink() + : FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Parent Station", "Parent Station"), + name: "parent-stations", + onChanged: (RbacStation? e) { + setState(() { + selectedParentStation = e; + }); + }, + items: parentStations.isEmpty + ? [] + : parentStations.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.stationName!), + ); + }).toList(), + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + ), + ), + const SizedBox( + height: 12, + ), + ////Station Type + SearchField( + itemHeight: 50, + suggestionsDecoration: box1(), + suggestions: stationTypes + .map((StationType stationType) => + SearchFieldListItem( + stationType.typeName!, + item: stationType, + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + stationType.typeName!, + overflow: TextOverflow.visible, + )), + ))) + .toList(), + validator: (station) { + if (station!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: stationTypeFocusNode, + searchInputDecoration: + normalTextFieldStyle("Station Type *", "") + .copyWith( + suffixIcon: GestureDetector( + onTap: () => stationTypeFocusNode.unfocus(), + child: const Icon(Icons.arrow_drop_down), + )), + onSuggestionTap: (position) { + setState(() { + selectedStationType = position.item!; + stationTypeFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add StationType", + controller: addStationTypeController, + onpressed: () { + setState(() { + StationType stationType = StationType( + id: null, + typeName: + addStationTypeController.text, + color: null, + order: null, + isActive: null, + group: null); + stationTypes.add(stationType); + Navigator.pop(context); + }); + }), + ), + const SizedBox( + height: 12, + ), + ////Position title + FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Head Position", "Head Position"), + name: "head-position", + items: positions.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.title!), + ); + }).toList(), + onChanged: (title) { + selectedPositiontitle = title; + }, + ), + const SizedBox( + height: 12, + ), + ////is within parent + FormBuilderSwitch( + initialValue: true, + activeColor: second, + onChanged: (value) { + setState(() { + isWithinParent = value!; + }); + }, + decoration: normalTextFieldStyle( + "Location of the station within this parent?", + 'Location of the station within this parent?'), + name: 'isWithinParent', + title: Text(isWithinParent ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + Row( + //// Station Name + children: [ + Flexible( + child: FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This Field is required"), + decoration: normalTextFieldStyle( + "Station name", "Station name"), + name: "station-name"), + ), + const SizedBox( + width: 12, + ), + //// Acronym + Flexible( + child: FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This Field is required"), + decoration: normalTextFieldStyle( + "Acronym", "Acronym"), + name: "acronym"), + ), + ], + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + ////Description + decoration: normalTextFieldStyle( + "Station description", + "Station description"), + name: "station-description"), + const SizedBox( + height: 12, + ), + Row( + children: [ + Flexible( + ////Code + child: FormBuilderTextField( + decoration: normalTextFieldStyle( + "Code", "Code"), + name: "code"), + ), + const SizedBox( + width: 12, + ), + Flexible( + //// Full Code + child: FormBuilderTextField( + decoration: normalTextFieldStyle( + "Full Code", "Full Code"), + name: "fullcode"), + ), + ], + ), + const SizedBox( + height: 12, + ), + ////is Hospital + FormBuilderSwitch( + initialValue: isHospital, + activeColor: second, + onChanged: (value) { + setState(() { + isHospital = !isHospital; + }); + }, + decoration: + normalTextFieldStyle("Is Hospital", ''), + name: 'isHospital', + title: Text(isHospital == true ? "YES" : "NO"), + ), + const SizedBox( + height: 20, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + RbacStation? newStation; + if (formKey.currentState! + .saveAndValidate()) { + String? stationName = formKey + .currentState! + .value['station-name']; + String? acronym = formKey + .currentState!.value['acronym']; + String? code = formKey + .currentState!.value['code']; + String? fullcode = formKey + .currentState!.value['fullcode']; + String? description = formKey + .currentState! + .value['station-description']; + newStation = RbacStation( + id: null, + stationName: stationName, + stationType: selectedStationType, + hierarchyOrderNo: mainParent + ? 1 + : selectedParentStation! + .hierarchyOrderNo! + + 1, + headPosition: + selectedPositiontitle?.title, + governmentAgency: + GovernmentAgency( + agencyid: + selectedAgencyId, + agencyname: null, + agencycatid: null, + privateEntity: null, + contactinfoid: null), + acronym: acronym, + parentStation: mainParent + ? null + : selectedParentStation!.id!, + code: code, + fullcode: fullcode, + childStationInfo: null, + islocationUnderParent: + isWithinParent, + mainParentStation: mainParent + ? null + : selectedMainParentStation! + .id!, + description: description, + ishospital: isHospital, + isactive: true, + sellingStation: null); + Navigator.pop(context); + rbacStationBloc.add(AddRbacStation( + station: newStation)); + } + }, + child: const Text("Add"))), + ], + ); + }), + ), + ), + ); + }); + }), + ////Filter + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text( + "Select agency to filter stations", + textAlign: TextAlign.center, + ), + content: SizedBox( + child: // //// Filter Agencies + Padding( + padding: const EdgeInsets.all(8), + child: SearchField( + inputFormatters: [UpperCaseTextFormatter()], + itemHeight: 100, + focusNode: agencyFocusNode, + suggestions: agencies + .map((Agency agency) => + SearchFieldListItem(agency.name!, + item: agency, + child: ListTile( + title: Text( + agency.name!, + overflow: TextOverflow.visible, + ), + ))) + .toList(), + searchInputDecoration: + normalTextFieldStyle("Filter", "").copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyFocusNode.unfocus(); + }, + )), + onSuggestionTap: (agency) { + agencyFocusNode.unfocus(); + + selectedAgencyId = agency.item!.id!; + print(selectedAgencyId); + Navigator.pop(context); + rbacStationBloc.add(FilterStation( + agencyId: selectedAgencyId)); + }, + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + emptyWidget: const Center( + child: Text("No result found..."), + )), + ), + ), + ); + }); + }, + icon: const Icon(Icons.filter_list)) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is StationLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is RbacStationAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context + .read() + .add(GetStations(agencyId: selectedAgencyId)); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context + .read() + .add(GetStations(agencyId: selectedAgencyId)); + }); + } + } + if (state is StationLoadedState || + state is RbacStationAddedState || + state is StationErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + final parent = context; + if (state is StationLoadedState) { + stations = state.stations; + stationTypes = state.stationTypes; + positions = state.positions; + agencies = state.agencies; + int max = 0; + hierarchy = []; + for (RbacStation station in stations) { + if (station.hierarchyOrderNo != null) { + if (max < station.hierarchyOrderNo!) { + max = station.hierarchyOrderNo!; + } + } + } + for (int i = 1; i <= max; i++) { + hierarchy.add({i: []}); + } + for (var station in stations) { + if (station.hierarchyOrderNo != null) { + for (int i = 0; i <= max; i++) { + if (station.hierarchyOrderNo == i + 1) { + hierarchy[i][i + 1].add(station); + } + } + } + } + + if (stations.isNotEmpty && hierarchy[0][1].isNotEmpty) { + return Column( + children: [ + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: hierarchy[0][1].length, + itemBuilder: (BuildContext context, int index) { + List second = []; + if (max >= 2) { + for (var rbacStation in hierarchy[1][2]) { + if (rbacStation.parentStation == + hierarchy[0][1][index].id) { + second.add(rbacStation); + } + } + } + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + const CircleAvatar( + child: Text('1'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + hierarchy[0][1][index] + .stationName!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500, + color: primary)), + ), + ], + )), + ], + ), + ), + ////SECOND + SizedBox( + child: second.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: second.map((e) { + List childs = []; + if (max >= 3) { + for (RbacStation station + in hierarchy[2][3]) { + if (station.parentStation == + e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + child: Container( + width: screenWidth, + decoration: box1() + .copyWith( + boxShadow: []), + padding: + const EdgeInsets + .only( + left: 30), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: + const EdgeInsets.all( + 6), + child: + Text( + "2", + style: Theme.of(context) + .textTheme + .bodyLarge, + selectionColor: + Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + e + .stationName!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + ], + ), + ), + ), + ], + ), + ////THIRD + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: + MainAxisSize + .min, + children: childs + .map((e) { + List + childs = []; + if (max >= 4) { + for (RbacStation station + in hierarchy[ + 3] + [4]) { + if (station + .parentStation == + e.id) { + childs.add( + station); + } + } + } else { + childs = []; + } + return Column( + children: [ + Container( + width: + screenWidth, + decoration: + box1() + .copyWith(boxShadow: []), + padding: const EdgeInsets + .only( + left: + 50), + child: + Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6), + child: Text( + "3", + style: Theme.of(context).textTheme.bodyLarge, + selectionColor: Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ////Fourth + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: childs.map((e) { + List childs = []; + if (max > 4) { + for (RbacStation station in hierarchy[4][5]) { + if (station.parentStation == e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1().copyWith(boxShadow: []), + padding: const EdgeInsets.only(left: 80), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6), + child: Text( + "4", + style: Theme.of(context).textTheme.bodyLarge, + selectionColor: Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ////Fifth + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: childs.map((e) { + List childs = []; + if (max > 5) { + for (RbacStation station in hierarchy[5][6]) { + if (station.parentStation == e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.only(left: 80), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + const CircleAvatar( + child: Text('5'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ], + ); + }).toList(), + ) + : const SizedBox()), + ], + ); + }).toList(), + ) + : const SizedBox()), + ], + ); + }).toList(), + ) + : const SizedBox + .shrink()), + ], + ); + }).toList(), + ) + : const SizedBox()), + const Divider( + height: 5, + ), + ], + ); + }), + ) + ], + ); + } else { + return const EmptyData( + message: "No Station available. Please click + to add."); + } + } + if (state is StationErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetStations(agencyId: selectedAgencyId)); + }); + } + + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/unit2/basic-info/basic-info.dart b/lib/screens/unit2/basic-info/basic-info.dart new file mode 100644 index 0000000..07539a4 --- /dev/null +++ b/lib/screens/unit2/basic-info/basic-info.dart @@ -0,0 +1,194 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:signature/signature.dart'; +import 'package:unit2/model/login_data/user_info/user_data.dart'; +import 'package:unit2/screens/unit2/basic-info/components/qr_image.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../bloc/user/user_bloc.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../widgets/splash_screen.dart'; +import '../signature/signature_pad.dart'; +import './components/cover-image.dart'; + +class BasicInfo extends StatelessWidget { + const BasicInfo({super.key}); + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + return Future.value(true); + }, + child: ProgressHUD( + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + state.userData!.employeeInfo!.profile!.sex!.toUpperCase(); + return SafeArea( + child: Scaffold( + body: SizedBox( + width: screenWidth, + child: Column( + children: [ + Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + const CoverImage(), + Positioned( + top: blockSizeVertical * 15.5, + child: Stack( + alignment: Alignment.center, + children: [ + const CircleAvatar( + radius: 72, + backgroundColor: Colors.white, + ), + CircleAvatar( + radius: 69, + backgroundColor: Colors.grey.shade800, + child: SvgPicture.asset( + 'assets/svgs/male.svg', + ), + ), + ], + ), + ), + Positioned( + top: 10, + left: 20, + child: IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: const Icon( + FontAwesome5.arrow_left, + size: 24, + color: Colors.white, + ), + )), + Positioned( + top: 10, + right: 20, + child: IconButton( + onPressed: () {}, + icon: const Icon( + Icons.edit, + size: 24, + color: Colors.white, + ), + )), + ], + ), + SizedBox( + height: blockSizeVertical * 5, + ), + BuildInformation( + userData: state.userData!, + ), + ], + ), + ), + ), + ); + } + return const UniTSplashScreen(); + }, + ), + ), + ); + } +} + +class BuildInformation extends StatelessWidget { + final UserData userData; + const BuildInformation({super.key, required this.userData}); + @override + Widget build(BuildContext context) { + DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); + final String firstName = + userData.user!.login!.user!.firstName!.toUpperCase(); + final String lastname = userData.user!.login!.user!.lastName!.toUpperCase(); + final String? middlename = userData.employeeInfo == null + ? '' + : userData.employeeInfo!.profile?.middleName?.toUpperCase(); + final String sex = userData.employeeInfo!.profile!.sex!.toUpperCase(); + final DateTime? bday = userData.employeeInfo!.profile!.birthdate; + final uuid = userData.employeeInfo!.uuid; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 25), + width: screenWidth, + child: Column( + children: [ + const SizedBox( + height: 25, + ), + Text( + "$firstName ${middlename ?? ''} $lastname", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 10, + ), + Text( + "${dteFormat2.format(bday!)} | $sex", + style: + Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 18), + ), + const SizedBox( + height: 15, + ), + GestureDetector( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return QRFullScreenImage(uuid: uuid); + })); + }, + child: QrImage( + data: uuid!, + size: blockSizeVertical * 24, + ), + ), + const SizedBox( + height: 25, + ), + SizedBox( + width: screenWidth * .60, + height: blockSizeVertical * 7, + child: SizedBox( + child: ElevatedButton.icon( + style: + mainBtnStyle(third, Colors.transparent, Colors.white54), + onPressed: () { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return const SignaturePad(); + })); + }, + icon: const Icon( + FontAwesome5.signature, + size: 15, + ), + label: const Text(signature)), + ), + ), + const SizedBox( + height: 5, + ), + ], + ), + ); + } +} diff --git a/lib/screens/unit2/basic-info/components/cover-image.dart b/lib/screens/unit2/basic-info/components/cover-image.dart new file mode 100644 index 0000000..f0f5031 --- /dev/null +++ b/lib/screens/unit2/basic-info/components/cover-image.dart @@ -0,0 +1,21 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; + +class CoverImage extends StatelessWidget { + const CoverImage({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.grey, + child: CachedNetworkImage( + imageUrl: + "https://live.staticflickr.com/7320/9052838885_af9b21c79b_b.jpg", + // 'https://static.vecteezy.com/system/resources/thumbnails/008/074/253/small/tropical-forest-sunset-nature-background-with-coconut-trees-vector.jpg', + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ); + } +} diff --git a/lib/screens/unit2/basic-info/components/qr_image.dart b/lib/screens/unit2/basic-info/components/qr_image.dart new file mode 100644 index 0000000..6cd2d39 --- /dev/null +++ b/lib/screens/unit2/basic-info/components/qr_image.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; + +class QRFullScreenImage extends StatelessWidget { + final String uuid; + const QRFullScreenImage({super.key, required this.uuid}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary,title: const Text("Profile QR Code"),), + body: Center( + child: QrImage( + data: uuid, + size: blockSizeVertical * 50 + ), + ),); + } +} \ No newline at end of file diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart new file mode 100644 index 0000000..c814837 --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart @@ -0,0 +1,712 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:unit2/model/login_data/user_info/assigned_area.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/dashboard_icon_generator.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart'; +import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import '../../../../../bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart'; +import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart'; +import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart'; +import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart'; +import '../../../roles/establishment_point_person/est_point_person_agecies.dart'; +import '../../../roles/establishment_point_person/est_point_person_role_member_screen.dart'; +import '../../../roles/establishment_point_person/est_point_person_role_under_screen.dart'; +import '../../../roles/establishment_point_person/est_point_person_station.dart'; +import './shared_card_label.dart'; + +class DashBoard extends StatefulWidget { + final List? estPersonAssignedArea; + final List cards; + final int userId; + const DashBoard( + {super.key, + required this.cards, + required this.userId, + required this.estPersonAssignedArea}); + + @override + State createState() => _DashBoardState(); +} + +List finishRoles = []; +List unit2Cards = []; +List superadminCards = []; +List rpassCards = []; +List docSmsCards = []; +List tempSuperAdminCards = []; +List tempUnit2Cards = []; + +class _DashBoardState extends State { + @override + Widget build(BuildContext context) { + setState(() { + finishRoles.clear(); + unit2Cards.clear(); + superadminCards.clear(); + rpassCards.clear(); + docSmsCards.clear(); + tempSuperAdminCards.clear(); + }); + widget.cards.forEach((e) { + if (e.moduleName == "unit2") { + if (!finishRoles.contains(e.object.name)) { + unit2Cards.add(e); + } + finishRoles.add(e.object.name!); + } + if (e.moduleName == 'superadmin') { + superadminCards.add(e); + } + if (e.moduleName == 'rpass') { + rpassCards.add(e); + } + if (e.moduleName == 'document management') { + docSmsCards.add(e); + } + }); + unit2Cards.forEach((element) { + print( + "${element.moduleName} - ${element.object.name!} - ${element.roleName} "); + }); + if (superadminCards.length > 3) { + tempSuperAdminCards = superadminCards.sublist(0, 4); + } + if (unit2Cards.length > 3) { + tempUnit2Cards = unit2Cards.sublist(0, 4); + } + + return Container( + padding: + const EdgeInsetsDirectional.symmetric(vertical: 24, horizontal: 24), + child: ListView( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ////unit2 module operations + Container( + child: unit2Cards.isEmpty + ? const SizedBox() + : Text( + "Unit2 module operations", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith( + fontSize: 16, + color: primary, + fontWeight: FontWeight.w300), + ), + ), + SizedBox( + height: unit2Cards.isEmpty ? 0 : 8, + ), + Container( + child: unit2Cards.isEmpty + ? const SizedBox.shrink() + : GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 8, + mainAxisSpacing: 10, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 5), + children: unit2Cards.length > 3 + ? tempUnit2Cards.map(( + e, + ) { + int index = tempUnit2Cards.indexOf(e); + //// if unit2 cards is greater then 3 + return Container( + child: index == 3 + ? CardLabel( + icon: FontAwesome5 + .chevron_circle_right, + title: "See More", + ontap: () { + showDialog( + context: context, + builder: + (BuildContext context) { + return AlertDialog( + title: const Text( + "Unit2 Admin Module Operations", + textAlign: + TextAlign.center, + ), + content: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + SizedBox( + height: 300, + width: double + .maxFinite, + child: + GridView.count( + shrinkWrap: + true, + crossAxisCount: + 3, + crossAxisSpacing: + 8, + mainAxisSpacing: + 10, + physics: + const BouncingScrollPhysics(), + padding: const EdgeInsets + .symmetric( + vertical: + 5, + horizontal: + 5), + children: + unit2Cards + .map(( + e, + ) { + int index = + unit2Cards + .indexOf(e); + //// if unit2 cards is less then 3 + return AnimationConfiguration + .staggeredGrid( + position: + index, + columnCount: + 3, + child: + ScaleAnimation( + child: + FadeInAnimation( + child: Container( + child: (e.roleName == 'qr code scanner' || e.roleName == 'security guard' || e.roleName == 'establishment point-person' || e.roleName == 'registration in-charge') && e.moduleName == 'unit2' + ? CardLabel( + icon: iconGenerator(name: e.object.name!), + title: e.object.name!.toLowerCase() == 'role based access control' + ? "RBAC" + : e.object.name!.toLowerCase() == "person basic information" + ? "Basic Info" + : e.object.name!, + ontap: () { + if (e.object.name!.toLowerCase() == 'pass check') { + PassCheckArguments passCheckArguments = PassCheckArguments(roleId: e.roleId, userId: widget.userId); + Navigator.pushNamed(context, '/pass-check', arguments: passCheckArguments); + } + if (e.object.name!.toLowerCase() == 'role based access control') { + Navigator.pushNamed(context, '/rbac'); + } + if (e.object.name!.toLowerCase() == 'agency') { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (context) => AssignAreaAgencyBloc()..add((EstPointPersonGetAgencies(assignedAreas: widget.estPersonAssignedArea))), + child: const EstPorintPersonAgencyScreen(), + ); + })); + } + if (e.object.name!.toLowerCase() == "role member") { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (context) => EstRoleAssignmentBloc()..add(GetEstPointPersonRolesUnder(userId: widget.userId)), + child: EstPointPersonRoleAssignmentScreen( + id: widget.userId, + ), + ); + })); + } + if (e.object.name!.toLowerCase() == 'assignable role') { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (context) => EstPointPersonAssinableRoleBloc()..add(const GetEstPointPersonAssignableRoles(roleId: 16)), + child: EstPointPersonRoleUnderScreen( + id: widget.userId, + ), + ); + })); + } + ////Station + if (e.object.name == 'Station') { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Select Agency"), + content: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + DropdownButtonFormField( + isDense: true, + decoration: normalTextFieldStyle("select agency", "select agency"), + isExpanded: true, + items: widget.estPersonAssignedArea!.map((e) { + return DropdownMenuItem( + value: e, + child: FittedBox(child: Text(e.areaName!)), + ); + }).toList(), + onChanged: (value) { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (context) => EstPointPersonStationBloc() + ..add(EstPointPersonGetStations( + agencyId: value.areaid!, + )), + child: EstPointPersonStationScreen( + agencyId: value!.areaid!, + ), + ); + })); + }) + ], + ), + ); + }); + } + }) + : Container( + color: Colors.black, + )), + ), + ), + ); + }).toList()), + ), + ], + ), + ); + }); + }) + : (e.roleName == 'superadmin' || + e.roleName == + 'qr code scanner' || + e.roleName == + 'security guard' || + e.roleName == + 'establishment point-person' || + e.roleName == + 'registration in-charge') && + e.moduleName == 'unit2' + ? CardLabel( + icon: iconGenerator( + name: e.object.name!), + title: e.object.name! + .toLowerCase() == + 'role based access control' + ? "RBAC" + : e.object.name! + .toLowerCase() == + "person basic information" + ? "Basic Info" + : e.object.name!, + ontap: () { + if (e.object.name! + .toLowerCase() == + 'pass check') { + PassCheckArguments + passCheckArguments = + PassCheckArguments( + roleId: 10, + userId: + widget.userId); + Navigator.pushNamed( + context, '/pass-check', + arguments: + passCheckArguments); + } + if (e.object.name! + .toLowerCase() == + 'role based access control') { + Navigator.pushNamed( + context, '/rbac'); + } + + if (e.object.name! + .toLowerCase() == + 'agency') { + Navigator.push(context, + MaterialPageRoute( + builder: + (BuildContext + context) { + return BlocProvider( + create: (context) => + AssignAreaAgencyBloc() + ..add((EstPointPersonGetAgencies( + assignedAreas: + widget + .estPersonAssignedArea))), + child: + const EstPorintPersonAgencyScreen(), + ); + })); + } + }) + : Container( + color: Colors.black, + )); + }).toList() + : unit2Cards.map(( + e, + ) { + ////if unit2 cards is greater than 3 + return Container( + child: (e.roleName == 'superadmin' || + e.roleName == + 'qr code scanner' || + e.roleName == + 'security guard' || + e.roleName == + 'establishment point-person' || + e.roleName == + 'registration in-charge') && + e.moduleName == 'unit2' + ? CardLabel( + icon: iconGenerator( + name: e.object.name!), + title: e.object.name! + .toLowerCase() == + 'role based access control' + ? "RBAC" + : e.object.name! + .toLowerCase() == + "person basic information" + ? "Basic Info" + : e.object.name!, + ontap: () { + if (e.object.name! + .toLowerCase() == + 'pass check') { + PassCheckArguments + passCheckArguments = + PassCheckArguments( + roleId: 10, + userId: widget.userId); + Navigator.pushNamed( + context, '/pass-check', + arguments: + passCheckArguments); + } + if (e.object.name! + .toLowerCase() == + 'role based access control') { + Navigator.pushNamed( + context, '/rbac'); + } + + if (e.object.name! + .toLowerCase() == + 'agency') { + Navigator.push(context, + MaterialPageRoute(builder: + (BuildContext context) { + return BlocProvider( + create: (context) => + AssignAreaAgencyBloc() + ..add((EstPointPersonGetAgencies( + assignedAreas: widget + .estPersonAssignedArea))), + child: + const EstPorintPersonAgencyScreen(), + ); + })); + } + }) + : Container( + color: Colors.black, + )); + }).toList(), + ), + ), + SizedBox( + height: superadminCards.isEmpty ? 0 : 24, + ), + Container( + child: superadminCards.isEmpty + ? const SizedBox.shrink() + : Text( + "Superadmin module operations", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith( + fontSize: 16, + color: primary, + fontWeight: FontWeight.w300), + ), + ), + SizedBox( + height: superadminCards.isEmpty ? 0 : 8, + ), + Container( + child: superadminCards.isEmpty + ? const SizedBox.shrink() + : GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 8, + mainAxisSpacing: 10, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 5), + children: superadminCards.length > 3 + //// in superadmincards lenght is greaterthan 3 + ? tempSuperAdminCards.map((e) { + int index = tempSuperAdminCards.indexOf(e); + return Container( + child: index == 3 + ? CardLabel( + icon: FontAwesome5 + .chevron_circle_right, + title: "See More", + ontap: () { + showDialog( + context: context, + builder: + (BuildContext context) { + return AlertDialog( + title: const Text( + "Super Admin Module Operations", + textAlign: + TextAlign.center, + ), + content: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + SizedBox( + height: 480, + width: double + .maxFinite, + child: GridView + .count( + shrinkWrap: + true, + crossAxisCount: + 3, + crossAxisSpacing: + 8, + mainAxisSpacing: + 10, + physics: + const BouncingScrollPhysics(), + padding: const EdgeInsets + .symmetric( + vertical: 5, + horizontal: + 5), + children: + superadminCards + .map( + (e) { + int index = + superadminCards + .indexOf( + e); + return SuperAdminMenu( + id: widget + .userId, + columnCount: + 3, + index: + index, + object: e, + ); + }).toList(), + ), + ), + ], + ), + ); + }); + }) + : SuperAdminMenu( + id: widget.userId, + object: e, + index: index, + columnCount: 3, + )); + }).toList() + //// in superadmincards lenght is lessthan 3 + : superadminCards.map((e) { + int index = tempSuperAdminCards.indexOf(e); + return Container( + child: index == 3 + ? CardLabel( + icon: FontAwesome5 + .chevron_circle_right, + title: "See More", + ontap: () { + showDialog( + context: context, + builder: + (BuildContext context) { + return AlertDialog( + title: const Text( + "Super Admin Module Operations", + textAlign: + TextAlign.center, + ), + content: Column( + mainAxisSize: + MainAxisSize.min, + children: [ + SizedBox( + height: 480, + width: double + .maxFinite, + child: GridView + .count( + shrinkWrap: + true, + crossAxisCount: + 3, + crossAxisSpacing: + 8, + mainAxisSpacing: + 10, + physics: + const BouncingScrollPhysics(), + padding: const EdgeInsets + .symmetric( + vertical: 5, + horizontal: + 5), + children: + superadminCards + .map( + (e) { + return SuperAdminMenu( + id: widget + .userId, + columnCount: + 4, + index: + index, + object: e, + ); + }).toList(), + ), + ), + ], + ), + ); + }); + }) + : SuperAdminMenu( + id: widget.userId, + object: e, + index: index, + columnCount: 4, + )); + }).toList())), + SizedBox( + height: rpassCards.isEmpty ? 0 : 24, + ), + Container( + child: rpassCards.isEmpty + ? const SizedBox.shrink() + : Text( + "RPAss module operations", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith( + fontSize: 16, + color: primary, + fontWeight: FontWeight.w300), + ), + ), + SizedBox( + height: rpassCards.isEmpty ? 0 : 8, + ), + Container( + child: rpassCards.isEmpty + ? const SizedBox.shrink() + : GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 8, + mainAxisSpacing: 10, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 5), + children: rpassCards.map((e) { + return Container( + child: (e.roleName == 'field surveyor') && + e.moduleName == 'rpass' + ? CardLabel( + icon: iconGenerator(name: e.object.name!), + title: e.object.name == 'Real Property' + ? "Field Surveyor" + : e.object.name!, + ontap: () { + Navigator.pushNamed(context, '/passo-home'); + }) + : Container( + color: Colors.black, + )); + }).toList(), + ), + ), + SizedBox( + height: docSmsCards.isEmpty ? 0 : 24, + ), + Container( + child: docSmsCards.isEmpty + ? const SizedBox.shrink() + : Text( + "DocSMS module operations", + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith( + fontSize: 16, + color: primary, + fontWeight: FontWeight.w300), + ), + ), + const SizedBox( + height: 8, + ), + GridView.count( + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 8, + mainAxisSpacing: 10, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + children: docSmsCards.map((e) { + return Container( + child: (e.roleName == 'process server') && + e.moduleName == 'document management' + ? CardLabel( + icon: iconGenerator(name: e.object.name!), + title: e.object.name == "Document" + ? "Process Server" + : e.object.name!, + ontap: () {}) + : Container( + color: Colors.black, + )); + }).toList(), + ) + ], + ) + ], + ), + ); + } +} + +class PassCheckArguments { + final int roleId; + final int userId; + const PassCheckArguments({required this.roleId, required this.userId}); +} diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/dashboard_icon_generator.dart b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard_icon_generator.dart new file mode 100644 index 0000000..ff8e816 --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard_icon_generator.dart @@ -0,0 +1,66 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:fluttericon/maki_icons.dart'; +import 'package:fluttericon/modern_pictograms_icons.dart'; +import 'package:fluttericon/octicons_icons.dart'; +import 'package:fluttericon/web_symbols_icons.dart'; + +IconData? iconGenerator({required String name}) { + if (name.toLowerCase() == 'agency') { + return FontAwesome5.building; + } else if (name.toLowerCase() == 'assignable role') { + return FontAwesome5.user_plus; + } else if (name.toLowerCase() == 'role') { + return FontAwesome5.user; + } else if (name.toLowerCase() == 'operation') { + return FontAwesome.export_alt; + } else if (name.toLowerCase() == 'module') { + return Icons.view_module; + } else if (name.toLowerCase() == 'area') { + return FontAwesome5.map_marked; + } else if (name.toLowerCase() == 'object') { + return FontAwesome.box; + } else if (name.toLowerCase() == 'permission') { + return FontAwesome5.door_open; + } else if (name.toLowerCase() == 'station') { + return ModernPictograms.home; + } else if (name.toLowerCase() == 'purok') { + return WebSymbols.list_numbered; + } else if (name.toLowerCase() == 'barangay') { + return Maki.industrial_building; + } else if (name.toLowerCase() == 'role module') { + return FontAwesome5.person_booth; + } else if (name.toLowerCase() == 'module object') { + return FontAwesome5.th_list; + } else if (name.toLowerCase() == 'roles extend') { + return FontAwesome5.external_link_square_alt; + } else if (name.toLowerCase() == 'real property') { + return FontAwesome5.eye; + } else if (name.toLowerCase() == 'document') { + return FontAwesome5.newspaper; + } else if (name.toLowerCase() == 'role based access control') { + return FontAwesome5.tasks; + } else if (name.toLowerCase() == 'pass check') { + return FontAwesome5.qrcode; + } else if (name.toLowerCase() == 'list of persons') { + return FontAwesome5.users; + } else if (name.toLowerCase() == 'person basic information') { + return FontAwesome5.info_circle; + }else if(name.toLowerCase() == "role member"){ + return FontAwesome5.users_cog; + } + + + + + + else if (name.toLowerCase() == 'security location') { + return FontAwesome5.location_arrow; + } + + else { + return null; + } +} diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/shared_card_label.dart b/lib/screens/unit2/homepage.dart/components/dashboard/shared_card_label.dart new file mode 100644 index 0000000..9dd8c3d --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/dashboard/shared_card_label.dart @@ -0,0 +1,61 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; + +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../utils/global.dart'; + +class CardLabel extends StatelessWidget { + final String title; + final IconData? icon; + final Function()? ontap; + const CardLabel( + {super.key, + required this.icon, + required this.title, + required this.ontap}); + + @override + Widget build(BuildContext context) { + return InkWell( + splashColor: second, + onTap: ontap, + child: Container( + padding: const EdgeInsetsDirectional.fromSTEB(8, 5, 8, 13), + alignment: Alignment.center, + decoration: const BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow(color: Colors.black12, spreadRadius: 1, blurRadius: 2) + ], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + flex: 1, + child: Icon( + icon, + size: 20, + weight: 100, + grade: 100, + color: second, + ), + ), + const Expanded(child: SizedBox()), + Flexible( + flex: 2, + child: AutoSizeText( + minFontSize: 10, + title, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelLarge!.copyWith( + fontSize: blockSizeVertical * 1.2, + fontWeight: FontWeight.bold), + ), + ), + ]), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart b/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart new file mode 100644 index 0000000..dd4c00f --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart @@ -0,0 +1,307 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/agency/agency_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/module/module_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/module_objects/module_objects_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/operation/operation_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/permission/permission_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role_extend/role_extend_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role_module/role_module_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/station/station_bloc.dart'; +import 'package:unit2/bloc/role_assignment/role_assignment_bloc.dart'; +import 'package:unit2/screens/superadmin/module/module_screen.dart'; +import 'package:unit2/screens/superadmin/object/object_screen.dart'; +import 'package:unit2/screens/superadmin/operation/operation_screen.dart'; +import 'package:unit2/screens/superadmin/permission/permission_screen.dart'; +import 'package:unit2/screens/superadmin/role/role_screen.dart'; +import 'package:unit2/screens/superadmin/role_assignment.dart/role_assignment_screen.dart'; +import 'package:unit2/screens/superadmin/role_extend/role_extend_screen.dart'; +import 'package:unit2/screens/superadmin/roles_under/roles_under_screen.dart'; +import 'package:unit2/screens/superadmin/stations/stations_screen.dart'; +import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import '../../../../superadmin/agency/agency_screen.dart'; +import '../../../../superadmin/module_objects/module_objects_screen.dart'; +import '../../../../superadmin/role_module/role_module_scree.dart'; +import './shared_card_label.dart'; +import 'dashboard_icon_generator.dart'; + +class SuperAdminMenu extends StatelessWidget { + final int id; + final DisplayCard object; + final int index; + final int columnCount; + const SuperAdminMenu( + {super.key, + required this.id, + required this.object, + required this.index, + required this.columnCount}); + + @override + Widget build(BuildContext context) { + final roleAssignmentKey = GlobalKey(); + return AnimationConfiguration.staggeredGrid( + position: index, + columnCount: columnCount, + child: ScaleAnimation( + child: FadeInAnimation( + child: Container( + child: (object.roleName == 'superadmin' || + object.object.name == 'Agency' || + object.object.name == 'Assignable Role' || + object.object.name == 'Role' || + object.object.name == 'Module' || + object.object.name == 'Object' || + object.object.name == 'Operation' || + object.object.name == 'Permission' || + object.object.name == 'Area' || + object.object.name == 'Station' || + object.object.name == 'Purok' || + object.object.name == 'Barangay' || + object.object.name == 'Role Module' || + object.object.name == 'Module Object' || + object.object.name == 'Roles Extend' || + object.object.name == "Role Member") && + object.moduleName == 'superadmin' + ? CardLabel( + icon: iconGenerator(name: object.object.name!), + title: + object.object.name!, + ontap: () { + + if (object.object.name == 'Role') { + + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => RoleBloc()..add(GetRoles()), + child: RbacRoleScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Operation') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + OperationBloc()..add(GetOperations()), + child: RbacOperationScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Module') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + ModuleBloc()..add(GetModule()), + child: RbacModuleScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Object') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + ObjectBloc()..add(GetObjects()), + child: RbacObjectScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Permission') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + PermissionBloc()..add(GetPermissions()), + child: RbacPermissionScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Module Object') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + ModuleObjectsBloc()..add(GetModuleObjects()), + child: RbacModuleObjectsScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Agency') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + AgencyBloc()..add(GetAgencies()), + child: RbacAgencyScreen( + + ), + ); + })); + } + if (object.object.name == 'Role Module') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + RoleModuleBloc()..add(GetRoleModules()), + child: RbacRoleModuleScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Assignable Role') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + RolesUnderBloc()..add(GetRolesUnder()), + child: RbacRoleUnderScreen( + id: id, + ), + ); + })); + } + if (object.object.name == 'Roles Extend') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => + RoleExtendBloc()..add(GetRoleExtend()), + child: RbacRoleExtendScreen( + id: id, + ), + ); + })); + } + + if (object.object.name == 'Station') { + Navigator.push(context, MaterialPageRoute( + builder: (BuildContext context) { + return BlocProvider( + create: (context) => StationBloc() + ..add(const GetStations(agencyId: 1)), + child: const RbacStationScreen( + agencyId: 1, + ), + ); + })); + } + if (object.object.name == 'Role Member') { + Navigator.of(context).pop(); + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Row( + children: [ + const Expanded(child: Text("Search User")), + IconButton(onPressed: (){ + Navigator.pop(context); + }, icon: const Icon(Icons.close)) + ], + ), + content: FormBuilder( + key: roleAssignmentKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "firstname", + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "First name", "first name"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + name: "lastname", + decoration: normalTextFieldStyle( + "Last name", "last tname"), + ), + const SizedBox( + height: 24, + ), + SizedBox( + height: 60, + width: double.maxFinite, + child: ElevatedButton( + onPressed: () { + if (roleAssignmentKey + .currentState! + .saveAndValidate()) { + + String fname = + roleAssignmentKey + .currentState! + .value['firstname']; + String lname = + roleAssignmentKey + .currentState! + .value['lastname']; + Navigator.push(context, + MaterialPageRoute(builder: + (BuildContext + context) { + return BlocProvider( + create: (context) => + RoleAssignmentBloc() + ..add(GetAssignedRoles( + firstname: + fname, + lastname: + lname),),child:RbacRoleAssignment(id:id,name: fname,lname: lname,) ,); + })); + } + }, + style: mainBtnStyle(primary, + Colors.transparent, second), + child: const Text("Submit"), + ), + ) + ], + )), + ); + }); + } + }) + : Container( + color: Colors.black, + )), + ), + ), + ); + } +} diff --git a/lib/screens/unit2/homepage.dart/components/drawer-screen.dart b/lib/screens/unit2/homepage.dart/components/drawer-screen.dart new file mode 100644 index 0000000..4f0d609 --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/drawer-screen.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import '../../../../bloc/user/user_bloc.dart'; +import '../../../../widgets/splash_screen.dart'; +import 'menu-screen.dart'; +import '../module-screen.dart'; + +class DrawerScreen extends StatefulWidget { + const DrawerScreen({Key? key}) : super(key: key); + @override + State createState() => _DrawerScreenState(); +} + +class _DrawerScreenState extends State { + final zoomDrawerController = ZoomDrawerController(); + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + return ZoomDrawer( + controller: zoomDrawerController, + menuScreen: MenuScreen( + userData: state.userData, + ), + mainScreen: SizedBox( + height: MediaQuery.of(context).size.height, + child: const MainScreen()), + style: DrawerStyle.defaultStyle, + borderRadius: 24.0, + showShadow: false, + angle: -0.0, + slideWidth: MediaQuery.of(context).size.width * .90, + openCurve: Curves.fastOutSlowIn, + closeCurve: Curves.easeOut, + menuBackgroundColor: Colors.grey, + ); + } + return const UniTSplashScreen(); + }, + ); + } +} diff --git a/lib/screens/unit2/homepage.dart/components/empty_module.dart b/lib/screens/unit2/homepage.dart/components/empty_module.dart new file mode 100644 index 0000000..e7c9590 --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/empty_module.dart @@ -0,0 +1,53 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:unit2/theme-data.dart/text-styles.dart'; + +import '../../../../utils/global.dart'; +import '../../../../utils/text_container.dart'; + +class NoModule extends StatelessWidget { + const NoModule({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 25), + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/no_module.svg', + height: blockSizeVertical * 30, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 24, + ), + Text( + noModule, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .displayLarge! + .copyWith(fontSize: blockSizeVertical * 5, height: .8), + ), + const SizedBox( + height: 5, + ), + Text( + noModuleSubTitle, + style: Theme.of(context) + .textTheme + .caption! + .copyWith(fontSize: blockSizeVertical * 1.5), + textAlign: TextAlign.center, + ) + ]), + ); + } +} diff --git a/lib/screens/unit2/homepage.dart/components/menu-screen.dart b/lib/screens/unit2/homepage.dart/components/menu-screen.dart new file mode 100644 index 0000000..0b712e3 --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/menu-screen.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:fluttericon/web_symbols_icons.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import '../../../../model/login_data/user_info/user_data.dart'; +import 'menu.dart'; +import '../../../../utils/global.dart'; + +class MenuScreen extends StatefulWidget { + final UserData? userData; + const MenuScreen({Key? key, required this.userData}) : super(key: key); + + @override + State createState() => _MenuScreenState(); +} + +class _MenuScreenState extends State { + @override + Widget build(BuildContext context) { + final String firstName = + widget.userData!.user!.login!.user!.firstName!.toUpperCase(); + final String lastname = + widget.userData!.user!.login!.user!.lastName!.toUpperCase(); + return Drawer( + child: SizedBox( + height: screenHeight, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Column( + // ignore: prefer_const_literals_to_create_immutables + children: [ + UserAccountsDrawerHeader( + decoration: const BoxDecoration( + color: primary, + image: DecorationImage( + image: AssetImage('assets/pngs/bg.png'), + fit: BoxFit.cover)), + accountName: Text("$firstName $lastname"), + accountEmail: null, + currentAccountPicture: CircleAvatar( + radius: 40, + backgroundColor: fifth, + child: CircleAvatar( + radius: 33, + backgroundColor: third, + child: //Icon(Icons.person, size: 40, color: fifth), + Text( + firstName[0].toUpperCase(), + style: const TextStyle(fontSize: 45.0, color: fifth), + ), + ), + ), + ), + getTile(FontAwesome5.user, "Basic Info", '/basic-info', context, + widget.userData!), + const Divider(), + getTile(FontAwesome5.user_circle, "Profile", + '/profile', context, widget.userData!), + const Divider(), + getTile(FontAwesome5.life_ring, "Request SOS", '/sos', + context, widget.userData!), + + ], + ), + const Expanded(child: SizedBox()), + const Divider(), + Align( + alignment: FractionalOffset.bottomLeft, + child: getTile(WebSymbols.logout, "Logout", '/', context, + widget.userData!), + ), + const SizedBox(height: 10,), + ], + ), + ), + ); + } +} diff --git a/lib/screens/unit2/homepage.dart/components/menu.dart b/lib/screens/unit2/homepage.dart/components/menu.dart new file mode 100644 index 0000000..abb12bc --- /dev/null +++ b/lib/screens/unit2/homepage.dart/components/menu.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/model/login_data/user_info/user_data.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/utils/global_context.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/global.dart'; + +Widget getTile( + IconData icondata, String title, String route, BuildContext context,UserData userData) { + return ListTile( + dense: true, + leading: Icon( + icondata, + color: primary, + ), + title: Text( + title, + style: const TextStyle(color: Colors.black), + ), + onTap: () async { + if (title.toLowerCase() == "logout") { + confirmAlert(context, () async{ + await CREDENTIALS!.clear(); + await CREDENTIALS!.deleteAll(['username','password','saved']); + Navigator.pushReplacementNamed (NavigationService.navigatorKey.currentContext!,"/"); + },"Logout","Are You sure you want to logout?"); + }if(title.toLowerCase() == 'profile'){ + ProfileArguments profileArguments = ProfileArguments(token: userData.user!.login!.token!, userID:userData.user!.login!.user!.profileId!); + Navigator.pushNamed(context, route,arguments: profileArguments); + }if(title.toLowerCase() == 'basic info'){ + Navigator.pushNamed(context, '/basic-info'); + }if(title.toLowerCase() == 'request sos'){ + Navigator.pushNamed(context, '/sos'); + } + + }, + ); +} + +class ProfileArguments{ + final int userID; + final String token; + const ProfileArguments({required this.token, required this.userID}); +} diff --git a/lib/screens/unit2/homepage.dart/module-screen.dart b/lib/screens/unit2/homepage.dart/module-screen.dart new file mode 100644 index 0000000..5f2046f --- /dev/null +++ b/lib/screens/unit2/homepage.dart/module-screen.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/dashboard.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; +import '../../../bloc/user/user_bloc.dart'; +import '../../../model/login_data/user_info/module.dart'; +import '../../../model/login_data/user_info/role.dart'; +import 'components/empty_module.dart'; + +class MainScreen extends StatefulWidget { + const MainScreen({Key? key}) : super(key: key); + + @override + State createState() => _MainScreenState(); +} + +class _MainScreenState extends State { + List roles = []; + List cards = []; + int? userId; + @override + Widget build(BuildContext context) { + setState(() { + cards.clear(); + cards=[]; + roles.clear(); + roles = []; + }); + return WillPopScope( + onWillPop: () async { + return Future.value(true); + }, + child: BlocBuilder(builder: (context, state) { + if (state is UserLoggedIn) { + userId = state.userData!.user!.login!.user!.id; + for (var role in state.userData!.user!.login!.user!.roles!) { + Role? getRole = role; + roles.add(getRole!); + } + for (var role in roles) { + for (var module in role.modules!) { + for (var object in module!.objects!) { + DisplayCard newCard = DisplayCard( + roleId: role.id!, + moduleName: module.name!.toLowerCase(), + object: object!, + roleName: role.name!.toLowerCase()); + cards.add(newCard); + } + } + } + + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + leading: IconButton( + onPressed: () { + ZoomDrawer.of(context)!.toggle(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + ), + ), + centerTitle: true, + title: const Text( + unit2ModuleScreen, + style: TextStyle( + fontSize: 18.0, + color: Colors.white, + ), + ), + ), + body: state.userData!.user!.login!.user!.roles!.isNotEmpty + ? DashBoard( + estPersonAssignedArea: state.estPersonAssignedArea, + userId: userId!, + cards: cards, + ) + : const NoModule(), + ); + } + return Container(); + }), + ); + } +} + +class DisplayCard { + final String roleName; + final String moduleName; + final ModuleObject object; + final int roleId; + const DisplayCard( + {required this.moduleName, required this.object, required this.roleName,required this.roleId}); +} + +class Module { + final String name; + final List roles; + Module({required this.name, required this.roles}); +} + +class Roles { + final IconData? icon; + final Role role; + Roles({required this.role, required this.icon}); +} diff --git a/lib/screens/unit2/login/components/login-via-qr-label.dart b/lib/screens/unit2/login/components/login-via-qr-label.dart new file mode 100644 index 0000000..e74183e --- /dev/null +++ b/lib/screens/unit2/login/components/login-via-qr-label.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +import '../../../../utils/global.dart'; + +class LoginViaQr extends StatelessWidget { + final String text; + const LoginViaQr({Key? key,@required required this.text}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: blockSizeVertical * 3, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 30, + child: Divider( + color: Colors.grey, + height: 2, + ), + ), + // LOGIN VIA QR CODE + Text( + text, + style: const TextStyle(fontSize: 12), + ), + const SizedBox( + width: 30, + child: Divider( + color: Colors.grey, + height: 2, + ), + ), + ], + )); + } +} diff --git a/lib/screens/unit2/login/components/showAlert.dart b/lib/screens/unit2/login/components/showAlert.dart new file mode 100644 index 0000000..615a19e --- /dev/null +++ b/lib/screens/unit2/login/components/showAlert.dart @@ -0,0 +1,17 @@ +import 'package:cool_alert/cool_alert.dart'; +import 'package:flutter/material.dart'; + +import '../../../../theme-data.dart/colors.dart'; + +showAlert(context,Function confirm) { + CoolAlert.show( + context: context, + type: CoolAlertType.error, + title: 'Download Failed!', + text: 'Make sure you have internet connection. Please try again.', + loopAnimation: false, + confirmBtnText: "Try again", + confirmBtnColor: primary, + onConfirmBtnTap: confirm(), + backgroundColor: Colors.black); +} diff --git a/lib/screens/unit2/login/components/update_required.dart b/lib/screens/unit2/login/components/update_required.dart new file mode 100644 index 0000000..a5ae6b0 --- /dev/null +++ b/lib/screens/unit2/login/components/update_required.dart @@ -0,0 +1,248 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:easy_app_installer/easy_app_installer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:unit2/screens/unit2/login/components/showAlert.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; + +import '../../../../bloc/user/user_bloc.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/cpu_architecture.dart'; +import '../../../../utils/text_container.dart'; +import '../../../../widgets/wave.dart'; + +class Update extends StatefulWidget { + final String apkVersion; + final String currenVersion; + const Update( + {super.key, required this.apkVersion, required this.currenVersion}); + + @override + State createState() => _UpdateState(); +} + +class _UpdateState extends State { + String progressRating = '0'; + bool downloading = false; + bool isDownloaded = false; + bool asyncCall = false; + Dio dio = Dio(); + @override + Widget build(BuildContext context) { + return SafeArea( + child: Stack(children: [ + BlocBuilder( + builder: (context, state) { + if (state is VersionLoaded) { + return ProgressHUD( + child: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 40, vertical: 25), + height: MediaQuery.of(context).size.height, + alignment: Alignment.center, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/download.svg', + height: 200.0, + width: 200.0, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 5, + ), + Text("UPDATE REQUIRED!", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .displaySmall! + .copyWith(color: primary, fontSize: 28)), + ], + ), + const SizedBox( + height: 10, + ), + RichText( + textAlign: TextAlign.justify, + text: TextSpan( + text: 'Your app version ', + style: const TextStyle( + fontSize: 16, + color: Colors.black, + ), + children: [ + TextSpan( + text: widget.apkVersion, + style: const TextStyle( + color: primary, + fontWeight: FontWeight.bold)), + const TextSpan( + text: + " did not match with the latest version ", + style: TextStyle(color: Colors.black)), + TextSpan( + text: widget.currenVersion.toString(), + style: const TextStyle( + color: primary, + fontWeight: FontWeight.bold)), + const TextSpan( + text: + ". Download the app latest version to procceed using the uniT-App.", + style: TextStyle(color: Colors.black)), + ])), + const SizedBox( + height: 12.0, + ), + Container( + child: downloading + ? FittedBox( + child: Text( + 'Downloading application $progressRating%', + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontWeight: FontWeight.bold), + ), + ) + : Container(), + ), + SizedBox( + height: 60, + width: MediaQuery.of(context).size.width, + child: downloading + ? Container() + : ElevatedButton.icon( + icon: const Icon(Icons.download), + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () async { + final progress = ProgressHUD.of(context); + progress?.showWithText( + 'Please wait...', + ); + setState(() { + downloading = true; + progressRating = '0'; + }); + await openFile(); + }, + label: const Text( + "Download Latest App Version.")), + ), + ], + ), + ), + ), + ); + } + if (state is UserError) { + showAlert(context, () { + setState(() { + downloading = false; + }); + }); + } + return Container(); + }, + ), + const Positioned(bottom: 0, child: WaveReverse(height: 80)) + ]), + ); + } + + Future openFile() async { + try { + final filePath = await downloadFile(); + await openAPK(filePath); + } catch (e) { + print(e.toString()); + } + } + + Future openAPK(String path) async { + PermissionStatus result = await Permission.storage.request(); + if (result.isGranted) { + await EasyAppInstaller.instance.installApk(path); + } + } + + Future downloadFile() async { + final progress = ProgressHUD.of(context); + final appStorage = await getApplicationDocumentsDirectory(); + try { + String url = await getCPUArchitecture(); + final response = await dio.download(url, '${appStorage.path}/uniT.apk', + deleteOnError: true, + options: Options( + receiveTimeout: 20000, + sendTimeout: 20000, + receiveDataWhenStatusError: true, + responseType: ResponseType.bytes, + followRedirects: false, + validateStatus: (status) { + return status! < 500; + }), onReceiveProgress: (recv, total) { + setState(() { + progressRating = ((recv / total) * 100).toStringAsFixed(0); + downloading = true; + }); + if (progressRating == '100') { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + setState(() { + downloading = false; + isDownloaded = true; + }); + } + }); + } on TimeoutException catch (_) { + progress!.dismiss(); + showAlert(context, () { + setState(() { + downloading = false; + }); + }); + throw TimeoutException(timeoutError); + } on SocketException catch (_) { + progress!.dismiss(); + showAlert(context, () { + setState(() { + downloading = false; + }); + }); + throw const SocketException(timeoutError); + } on DioError catch (_) { + progress!.dismiss(); + showAlert(context, () { + setState(() { + downloading = false; + }); + }); + throw TimeoutException(timeoutError); + } catch (_) { + progress!.dismiss(); + showAlert(context, () { + setState(() { + downloading = false; + }); + }); + throw TimeoutException(timeoutError); + } + return '${appStorage.path}/uniT.apk'; + } +} diff --git a/lib/screens/unit2/login/functions/get_app_version.dart b/lib/screens/unit2/login/functions/get_app_version.dart new file mode 100644 index 0000000..7ebd85b --- /dev/null +++ b/lib/screens/unit2/login/functions/get_app_version.dart @@ -0,0 +1,13 @@ +import 'package:package_info_plus/package_info_plus.dart'; + +Future getAppVersion() async{ + String appVersion; + try{ +PackageInfo packageInfo = await PackageInfo.fromPlatform(); +appVersion = packageInfo.version; + }catch(e){ + throw(e.toString()); + } + return appVersion; + +} \ No newline at end of file diff --git a/lib/screens/unit2/login/functions/press-again-to-exit.dart b/lib/screens/unit2/login/functions/press-again-to-exit.dart new file mode 100644 index 0000000..0b1e58d --- /dev/null +++ b/lib/screens/unit2/login/functions/press-again-to-exit.dart @@ -0,0 +1,19 @@ + + +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +Future pressAgainToExit() async { + DateTime? currentBackPressTime; + DateTime now = DateTime.now(); + if (currentBackPressTime == null || + now.difference(currentBackPressTime) > const Duration(seconds: 1)) { + currentBackPressTime = now; + Fluttertoast.showToast( + msg: "Press again to exit", + gravity: ToastGravity.CENTER, + backgroundColor: Colors.black); + return Future.value(false); + } + return true; +} diff --git a/lib/screens/unit2/login/login.dart b/lib/screens/unit2/login/login.dart new file mode 100644 index 0000000..ecd188a --- /dev/null +++ b/lib/screens/unit2/login/login.dart @@ -0,0 +1,392 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:unit2/screens/unit2/login/components/update_required.dart'; +import 'package:unit2/screens/unit2/login/qr_login.dart'; +import 'package:unit2/utils/alerts.dart'; +import 'package:unit2/utils/internet_time_out.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../bloc/user/user_bloc.dart'; +import '../../../utils/global_context.dart'; +import '../../../widgets/splash_screen.dart'; +import '../../../widgets/wave.dart'; +import '../../../utils/global.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../theme-data.dart/btn-style.dart'; +import './components/login-via-qr-label.dart'; +import './functions/press-again-to-exit.dart'; + +class UniT2Login extends StatefulWidget { + const UniT2Login({super.key}); + + @override + State createState() => _UniT2LoginState(); +} + +class _UniT2LoginState extends State { + final _formKey = GlobalKey(); + bool showSuffixIcon = false; + bool _showPassword = true; + String? password; + String? username; + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: pressAgainToExit, + child: Scaffold( + body: ProgressHUD( + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer(listener: (context, state) { + print(state); + if (state is UserLoggedIn || state is UuidLoaded) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + if (state is UserLoggedIn) { + if (state.success == true) { + if (!state.savedCredentials!) { + confirmAlertWithCancel(context, () async { + await CREDENTIALS?.put('saved', "saved"); + await CREDENTIALS?.put('username', + state.userData!.user!.login!.user!.username!); + await CREDENTIALS?.put('password', password); + Fluttertoast.showToast( + msg: "Credentials Successfully saved", + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + Navigator.pushReplacementNamed( + NavigationService.navigatorKey.currentContext!, + '/module-screen'); + }, + () => Navigator.pushReplacementNamed( + context, '/module-screen'), + "Save credentials?", + "Do you want to save credentials so you don't have to login again next time?."); + } else { + Navigator.pushReplacementNamed(context, '/module-screen'); + } + } else { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + errorAlert(context, "Error Login", state.message, () { + context + .read() + .add(LoadVersion(username: username, password: password)); + Navigator.of(context).pop(); + }); + } + } + if (state is UuidLoaded) { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return const QRLogin(); + })); + } + }, builder: (context, state) { + if (state is VersionLoaded) { + return Builder(builder: (context) { + if (state.versionInfo!.version != state.apkVersion) { + return SizedBox( + child: SingleChildScrollView( + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + bottom: 0, + right: 0, + child: + WaveReverse(height: blockSizeVertical * 7)), + SizedBox( + height: blockSizeVertical * 100, + child: FormBuilder( + key: _formKey, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 42), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/logo.svg', + height: blockSizeVertical * 12, + allowDrawingOutsideViewBox: true, + color: primary, + ), + + Text( + welcome, + style: TextStyle( + fontSize: blockSizeVertical * 4, + fontWeight: FontWeight.w600), + ), + Text(unitApp, + style: TextStyle( + fontSize: blockSizeVertical * 6, + fontWeight: FontWeight.w800, + letterSpacing: .2, + height: 1, + color: primary)), + // Text( + // loginToContinue, + // style: TextStyle( + // fontSize: blockSizeVertical * 1.7, + // height: 1.5, + // fontWeight: FontWeight.w600), + // ), + SizedBox( + height: blockSizeVertical * 3, + ), + //// USERNAME + FormBuilderTextField( + name: 'username', + initialValue: state.username, + validator: + FormBuilderValidators.required( + errorText: usernameRequired), + autofocus: false, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87), + decoration: + loginTextFieldStyle().copyWith()), + SizedBox( + height: blockSizeVertical * 1.5, + ), + //// PASSWORD + FormBuilderTextField( + name: 'password', + initialValue: state.password, + validator: FormBuilderValidators.required( + errorText: passwordRequired), + onChanged: (value) { + value!.isEmpty + ? setState(() { + showSuffixIcon = false; + }) + : setState(() { + showSuffixIcon = true; + }); + }, + autofocus: false, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87), + decoration: + loginTextFieldStyle().copyWith( + suffixIcon: Visibility( + visible: showSuffixIcon, + child: _showPassword + ? IconButton( + icon: Icon( + FontAwesome5 + .eye_slash, + size: 24, + color: Theme.of( + context) + .textTheme + .displayLarge + ?.color), + onPressed: () { + setState(() { + _showPassword = + false; + }); + }, + ) + : IconButton( + onPressed: () { + setState(() { + _showPassword = + true; + }); + }, + icon: Icon( + FontAwesome5.eye, + size: 24, + color: Theme.of( + context) + .textTheme + .displayLarge + ?.color)), + ), + prefixIcon: const Icon( + Icons.lock, + color: primary, + ), + labelText: "Password", + hintText: enterPassword), + obscureText: _showPassword ? true : false, + ), + SizedBox( + height: blockSizeVertical * 2, + ), + SizedBox( + height: blockSizeVertical * 7, + //// Login Button + child: SizedBox( + width: + MediaQuery.of(context).size.width, + child: ElevatedButton( + style: mainBtnStyle( + second, + Colors.transparent, + Colors.white54), + child: const Text( + login, + style: + TextStyle(color: Colors.white), + ), + onPressed: () { + final progress = + ProgressHUD.of(context); + + FocusScope.of(context).unfocus(); + + if (_formKey.currentState! + .saveAndValidate()) { + password = _formKey.currentState! + .value['password']; + username = _formKey.currentState! + .value['username']; + progress?.showWithText( + 'Logging in...', + ); + + BlocProvider.of(context) + .add(UserLogin( + username: username, + password: password)); + } + }, + ), + ), + ), + SizedBox( + height: blockSizeVertical * 1.5, + ), +//// Login via Scan QR + SizedBox( + height: blockSizeVertical * 7, + child: SizedBox( + width: + MediaQuery.of(context).size.width, + child: ElevatedButton.icon( + style: mainBtnStyle( + Colors.white, + second, + primary.withOpacity(.4)), + icon: const Icon( + Icons.qr_code, + color: second, + ), + label: const Text( + loginViaQr, + style: TextStyle(color: second), + ), + onPressed: () { + context + .read() + .add(GetUuid()); + }, + ), + )), + SizedBox( + height: blockSizeVertical * 2, + ), + const LoginViaQr( + text: emergencyReponseLabel), + SizedBox( + height: blockSizeVertical * 2, + ), + // REQUEST SOS + SizedBox( + height: screenHeight * .07, + width: MediaQuery.of(context).size.width, + child: ElevatedButton.icon( + icon: const Icon( + FontAwesome5.life_ring, + color: Colors.white, + ), + style: mainBtnStyle( + third, + Colors.transparent, + Colors.white38), + onPressed: () { + Navigator.pushNamed( + context, '/sos'); + }, + label: const Text( + requestSOS, + style: + TextStyle(color: Colors.white), + )), + ) + ], + ), + ), + ), + ), + ], + ), + ), + ); + } else { + //New update available + return Update( + apkVersion: state.apkVersion!, + currenVersion: state.versionInfo!.version!, + ); + } + }); + } + if (state is UserError) { + return SomethingWentWrong( + message: onError, + onpressed: () { + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(GetApkVersion()); + return MaterialPageRoute(builder: (_) { + return const UniT2Login(); + }); + }, + ); + } + if (state is InternetTimeout) { + return const TimeOutError(); + } + if (state is SplashScreen) { + return const UniTSplashScreen(); + } + if (state is LoginErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(GetApkVersion()); + return MaterialPageRoute(builder: (_) { + return const UniT2Login(); + }); + }, + ); + } + return Container(); + }), + ), + ), + ); + } +} diff --git a/lib/screens/unit2/login/qr_login.dart b/lib/screens/unit2/login/qr_login.dart new file mode 100644 index 0000000..9fd52c5 --- /dev/null +++ b/lib/screens/unit2/login/qr_login.dart @@ -0,0 +1,251 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/utils/global_context.dart'; +import 'package:unit2/widgets/wave.dart'; +import '../../../bloc/user/user_bloc.dart'; +import '../../../theme-data.dart/colors.dart'; +import '../../../theme-data.dart/form-style.dart'; +import '../../../utils/alerts.dart'; +import '../../../utils/global.dart'; +import '../../../utils/internet_time_out.dart'; +import '../../../utils/text_container.dart'; +import '../../../utils/validators.dart'; +import '../../../widgets/error_state.dart'; + +class QRLogin extends StatefulWidget { + const QRLogin({super.key}); + + @override + State createState() => _QRLoginState(); +} + +class _QRLoginState extends State { + bool showSuffixIcon = false; + bool _showPassword = true; + final _formKey = GlobalKey(); + String? password; + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: ()async{ + Navigator.pushReplacementNamed(context,"/"); + return true; + }, + child: SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + backgroundColor: primary, + elevation: 0, + title: const Text("Login via QR"), + centerTitle: true, + ), + body: ProgressHUD( + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context,state){ + if (state is UserLoggedIn) { + if (state.success == true) { + if (!state.savedCredentials!) { + confirmAlertWithCancel(context, () async { + await CREDENTIALS?.put('saved', "saved"); + await CREDENTIALS?.put('username', + state.userData!.user!.login!.user!.username!); + await CREDENTIALS?.put('password', password); + Fluttertoast.showToast( + msg: "Credentials Successfully saved", + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + Navigator.pushReplacementNamed(NavigationService.navigatorKey.currentContext!, '/module-screen'); + }, + () => Navigator.pushReplacementNamed( + context, '/module-screen'), + "Save credentials?", + "Do you want to save credentials so you don't have to login again next time?."); + } else { + Navigator.pushReplacementNamed(context, '/module-screen'); + } + } else { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + errorAlert(context, "Error Login", state.message, () { + context + .read() + .add(LoadUuid()); + Navigator.of(context).pop(); + }); + } + + } + }, + builder: (context, state) { + if (state is UuidLoaded) { + return SingleChildScrollView( + child: Stack( + children: [ + Positioned( + bottom: 0, + child: WaveReverse(height: blockSizeVertical * 8)), + Container( + height: screenHeight * .87, + padding: const EdgeInsets.symmetric(horizontal: 32), + child: FormBuilder( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/logo.svg', + height: blockSizeVertical * 12, + allowDrawingOutsideViewBox: true, + color: primary, + ), + const SizedBox( + height: 12, + ), + Text(unitApp, + style: TextStyle( + fontSize: blockSizeVertical * 5, + fontWeight: FontWeight.w800, + letterSpacing: .2, + height: 1, + color: Colors.black87)), + const SizedBox( + height: 15, + ), + Text( + "Enter your password", + style: TextStyle( + fontSize: blockSizeVertical * 1.5, + height: 1.5, + fontWeight: FontWeight.w600), + ), + const SizedBox( + height: 15, + ), + // Password + FormBuilderTextField( + name: 'password', + validator: registerPasswordValidator, + // initialValue: state.password, + onChanged: (value) { + value!.isEmpty + ? setState(() { + showSuffixIcon = false; + }) + : setState(() { + showSuffixIcon = true; + }); + }, + autofocus: false, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black87), + decoration: loginTextFieldStyle().copyWith( + suffixIcon: Visibility( + visible: showSuffixIcon, + child: _showPassword + ? IconButton( + icon: Icon(FontAwesome5.eye_slash, + size: 24, + color: Theme.of(context) + .textTheme + .displayLarge + ?.color), + onPressed: () { + setState(() { + _showPassword = false; + }); + }, + ) + : IconButton( + onPressed: () { + setState(() { + _showPassword = true; + }); + }, + icon: Icon(FontAwesome5.eye, + size: 24, + color: Theme.of(context) + .textTheme + .displayLarge + ?.color)), + ), + prefixIcon: const Icon(Icons.lock), + labelText: "Password", + hintText: enterPassword), + obscureText: _showPassword ? true : false, + ), + const SizedBox( + height: 15, + ), + + const SizedBox( + height: 15, + ), + SizedBox( + width: double.infinity, + height: blockSizeVertical * 6, + child: ElevatedButton( + style: secondaryBtnStyle( + primary, Colors.transparent, primary), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + password = _formKey.currentState!.value['password']; + final progress = + ProgressHUD.of(context); + progress?.showWithText( + 'Logging in...', + ); + context.read().add(UuidLogin(uuid: state.uuid,password: _formKey.currentState!.value['password'])); + + } + }, + child: const Text("LOGIN")), + ) + ], + ), + ), + ), + ], + ), + ); + } if (state is InternetTimeout) { + return SomethingWentWrong(message: state.message, onpressed: () { + context + .read() + .add(LoadUuid()); + Navigator.of(context).pop(); + },); + } + + if(state is LoginErrorState){ + return SomethingWentWrong(message: state.message, onpressed: () { + context + .read() + .add(LoadUuid()); + Navigator.of(context).pop(); + },); + } + return Container(); + }, + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/establishment_point_person/est_point_person_agecies.dart b/lib/screens/unit2/roles/establishment_point_person/est_point_person_agecies.dart new file mode 100644 index 0000000..a58c61f --- /dev/null +++ b/lib/screens/unit2/roles/establishment_point_person/est_point_person_agecies.dart @@ -0,0 +1,248 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/agency/agency_bloc.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; +import 'package:unit2/bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart'; +import 'package:unit2/model/utils/category.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../model/utils/agency.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; +import '../../../../utils/global_context.dart'; +import '../../../../widgets/Leadings/add_leading.dart'; +import '../../../../widgets/empty_data.dart'; + +class EstPorintPersonAgencyScreen extends StatelessWidget { + const EstPorintPersonAgencyScreen({super.key}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + List agencyCategory = []; + Category? selectedAgencyCategory; + bool? isPrivate; + final agencyCategoryFocusNode = FocusNode(); + BuildContext parent; + return Scaffold( + appBar: AppBar( + backgroundColor: primary, + title: const Text("Agencies"), + actions: [ + AddLeading(onPressed: () { + parent = context; + showDialog( + context: NavigationService.navigatorKey.currentContext!, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add Agency"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "name", + decoration: normalTextFieldStyle( + "Agency name ", "Agency name"), + ), + const SizedBox( + height: 12, + ), + SearchField( + focusNode: agencyCategoryFocusNode, + itemHeight: 80, + suggestions: agencyCategory + .map((Category category) => + SearchFieldListItem(category.name!, + item: category, + child: ListTile( + title: Text(category.name!), + subtitle: Text( + category.industryClass!.name!), + ))) + .toList(), + emptyWidget: Container( + height: 100, + decoration: box1(), + child: const Center( + child: Text("No result found ...")), + ), + onSuggestionTap: (agencyCategory) { + selectedAgencyCategory = agencyCategory.item; + agencyCategoryFocusNode.unfocus(); + }, + searchInputDecoration: + normalTextFieldStyle("Category *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + agencyCategoryFocusNode.unfocus(); + }, + )), + validator: (value) { + if (value!.isEmpty) { + return "This field is required"; + } + return null; + }, + ), + FormBuilderRadioGroup( + decoration: InputDecoration( + border: InputBorder.none, + label: Row( + children: [ + Text( + "Is this private sector? ", + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 24), + ), + const Icon(FontAwesome.help_circled) + ], + ), + ), + + ////onvhange private sector + onChanged: (value) { + if (value.toString() == "YES") { + isPrivate = true; + } else { + isPrivate = false; + } + }, + + name: 'isPrivate', + validator: FormBuilderValidators.required(), + options: ["YES", "NO"] + .map((lang) => + FormBuilderFieldOption(value: lang)) + .toList(growable: false), + ), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.maxFinite, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + String name = + formKey.currentState!.value['name']; + parent.read().add( + EstPointPersonAddAgency( + agency: Agency( + category: + selectedAgencyCategory, + id: null, + name: name, + privateEntity: isPrivate))); + Navigator.pop(context); + } + }, + child: const Text("Add")), + ) + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is EstPointPersonAgencyLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EstPointPersonAgenciesLoaded || + state is EstPointPersonAgencyAddesState || + state is EstPointAgencyErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + final parent = context; + if (state is EstPointPersonAgenciesLoaded) { + agencyCategory = state.agencyCategory; + if (state.agencies != null && state.agencies!.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.agencies!.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Expanded( + child: Row( + children: [ + CircleAvatar( + child: Text('${index + 1}'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(state.agencies![index].areaName!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Object available. Please click + to add."); + } + } + if (state is EstPointAgencyErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetObjects()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_member_screen.dart b/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_member_screen.dart new file mode 100644 index 0000000..185c62d --- /dev/null +++ b/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_member_screen.dart @@ -0,0 +1,307 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:group_list_view/group_list_view.dart'; +import 'package:multi_dropdown/models/value_item.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart'; +import 'package:unit2/bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart'; +import 'package:unit2/bloc/role_assignment/role_assignment_bloc.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../../model/rbac/assigned_role.dart'; +import '../../../../model/rbac/rbac.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../utils/global_context.dart'; + +class EstPointPersonRoleAssignmentScreen extends StatelessWidget { + final int id; + const EstPointPersonRoleAssignmentScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + Map> assignedRoles = {}; + List roles = []; + List valueItemAssignableRoles = []; + List selectedValueItemAssignableRoles = []; + List assignabledRoles = []; + List users = []; + List userIds = []; + int? selectedUserId; + final formKey = GlobalKey(); + final parent = context; + return Scaffold( + appBar: AppBar( + title: const Text("Role Members"), + backgroundColor: primary, + actions: [ + AddLeading(onPressed: () { + for (var role in roles) { + String fullname = + "${role.user!.firstName} ${role.user!.lastName}"; + if (!userIds.contains(role.user!.id)) { + userIds.add(role.user!.id); + users.add(Content(id: role.user!.id, name: fullname)); + } + } + showDialog( + context: NavigationService.navigatorKey.currentState!.context, + builder: (context) { + valueItemAssignableRoles = assignabledRoles.map((e) { + return ValueItem(label: e.name!, value: e.id.toString()); + }).toList(); + return AlertDialog( + title: const Text("Assign Role to User"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Select Person", "Select Person"), + name: 'users', + onChanged: (value) { + selectedUserId = value!.id; + }, + items: users.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.name), + ); + }).toList()), + const SizedBox( + height: 12, + ), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemAssignableRoles = + selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Select Roles", + padding: const EdgeInsets.all(8), + options: valueItemAssignableRoles, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + List rolesId = []; + for (var role in assignabledRoles) { + selectedValueItemAssignableRoles + .forEach((element) { + if (element.value == + role.id.toString()) { + rolesId.add(role.id!); + } + }); + } + parent + .read() + .add(EstPointPersonAssignRole( + rolesId: rolesId, + assingerId: id, + userId: selectedUserId!)); + Navigator.pop(context); + } + }, + child: const Text("Add"))), + ], + )), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + builder: (context, state) { + if (state is EstPointPersonRolesUnderLoadedState) { + roles = state.assignedRoles; + assignabledRoles = state.assignableRole; + assignedRoles = {}; + if (state.assignedRoles.isNotEmpty) { + for (var assignedRole in state.assignedRoles) { + String? fullName = + "${assignedRole.user!.firstName} ${assignedRole.user!.lastName}"; + if (!assignedRoles.keys.contains(fullName)) { + assignedRoles.addAll({fullName: []}); + assignedRoles[fullName]!.add(Content( + id: assignedRole.id!, name: assignedRole.role!.name)); + } else { + assignedRoles[fullName]!.add(Content( + id: assignedRole.id!, + name: assignedRole.role!.name)); + } + } + } + if (state.assignedRoles.isNotEmpty) { + return GroupListView( + sectionsCount: assignedRoles.keys.toList().length, + countOfItemInSection: (int section) { + return assignedRoles.values.toList()[section].length; + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + itemBuilder: (BuildContext context, IndexPath index) { + return ListTile( + trailing: IconButton( + color: Colors.grey.shade600, + icon: const Icon(Icons.delete), + onPressed: () { + confirmAlert(context, () { + context.read().add( + EstPointPersonDeleteAssignRole( + roleId: assignedRoles.values + .toList()[index.section][index.index] + .id)); + }, "Delete?", "Confirm Delete?"); + }, + ), + title: Row( + children: [ + CircleAvatar( + child: Text("${index.index + 1}", + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith(color: Colors.white))), + const SizedBox( + width: 20, + ), + Expanded( + child: Text( + assignedRoles.values + .toList()[index.section][index.index] + .name + .toUpperCase(), + style: Theme.of(context) + .textTheme + .labelLarge! + .copyWith( + fontWeight: FontWeight.w600, + color: primary), + ), + ), + ], + ), + ); + }, + groupHeaderBuilder: (BuildContext context, int section) { + return ListTile( + tileColor: second, + title: Text( + assignedRoles.keys.toList()[section].toUpperCase(), + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(color: Colors.white), + ), + ); + }, + ); + } else { + return const EmptyData(message: "Empty"); + } + } + if (state is EstPointPersonRolesUnderErrorState) { + return SomethingWentWrong( + message: "something went wrong. Please try again!", + onpressed: () {}); + } + return Container(); + }, listener: (context, state) { + if (state is EstPointPersonRoleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + ////Added State + if (state is EstPointPersonRoleUnderAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context + .read() + .add(GetEstPointPersonRolesUnder(userId: id)); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context + .read() + .add(GetEstPointPersonRolesUnder(userId: id)); + }); + } + } + ////Deleted State + if (state is EstPointPersonDeletedState) { + if (state.success) { + successAlert( + context, "Delete Successfull!", "Role Deleted Successfully", + () { + Navigator.of(context).pop(); + context + .read() + .add(GetEstPointPersonRolesUnder(userId: id)); + }); + } else { + errorAlert(context, "Delete Failed", "Role Delete Failed", () { + Navigator.of(context).pop(); + context + .read() + .add(GetEstPointPersonRolesUnder(userId: id)); + }); + } + } + if (state is EstPointPersonRolesUnderLoadedState || + state is EstPointPersonRoleUnderAddedState || + state is EstPointPersonRoleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }), + ), + ); + } +} + +class Content { + final int id; + final String name; + const Content({required this.id, required this.name}); +} diff --git a/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_under_screen.dart b/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_under_screen.dart new file mode 100644 index 0000000..9e5ded5 --- /dev/null +++ b/lib/screens/unit2/roles/establishment_point_person/est_point_person_role_under_screen.dart @@ -0,0 +1,264 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:multi_dropdown/models/value_item.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart'; +import '../../../../model/rbac/rbac.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../utils/global.dart'; +import '../../../../widgets/empty_data.dart'; + +class EstPointPersonRoleUnderScreen extends StatelessWidget { + final int id; + const EstPointPersonRoleUnderScreen({super.key, required this.id}); + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + List roles = []; + List valueItemRoles = []; + List selectedValueItemRoles = []; + RBAC? mainRole; + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Establishment Point Person Role Under Screen"), + actions: [ + AddLeading(onPressed: () { + valueItemRoles = roles.map((e) { + return ValueItem(label: e.name!, value: e.name); + }).toList(); + BuildContext parent = context; + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Role"), + content: FormBuilder( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderDropdown( + decoration: normalTextFieldStyle("", ""), + initialValue: mainRole!.name, + name: "main-role",items:[] ,), + const SizedBox(height: 12,), + MultiSelectDropDown( + onOptionSelected: + (List selectedOptions) { + selectedValueItemRoles = selectedOptions; + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Roles Under", + padding: const EdgeInsets.all(8), + options: valueItemRoles, + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ), + const SizedBox( + height: 8, + ), + + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + List rolesId = []; + for (var role in roles) { + selectedValueItemRoles + .forEach((element) { + if (element.label.toLowerCase() == + role.name?.toLowerCase()) { + rolesId.add(role.id!); + } + }); + } + Navigator.pop(context); + parent.read().add( + AddEstPointPersonAssignableRoles( + mainRoleId: mainRole!.id!, + rolesUnder: rolesId)); + } + }, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + listener: (context, state) { + if (state is EstPointPersonAssignableRoleLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EstPointPersonAssignableRoleLoaded || + state is EstPointPersonAssginableRoleAssignState || + state is EstPointPersonAssignableErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + ////Added State + if (state is EstPointPersonAssginableRoleAssignState) { + if (state.responseStatus['success']) { + successAlert( + context, "Adding Successfull!", state.responseStatus['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetEstPointPersonAssignableRoles(roleId:16 )); + }); + } else { + errorAlert(context, "Adding Failed", state.responseStatus['message'], + () { + Navigator.of(context).pop(); + context.read().add(GetEstPointPersonAssignableRoles(roleId:16 )); + }); + } + } + + ////Deleted State + if (state is EstPointPersonAssignableDeletedState) { + if (state.success) { + successAlert( + context, "Delete Successfull!", "Role Deleted Successfully", + () { + Navigator.of(context).pop(); + context.read().add(GetEstPointPersonAssignableRoles(roleId:16 )); + }); + } else { + errorAlert(context, "Delete Failed", "Role Delete Failed", () { + Navigator.of(context).pop(); + context.read().add(GetEstPointPersonAssignableRoles(roleId:16 )); + }); + } + } + + }, + builder: (context, state) { + final parent = context; + + if (state is EstPointPersonAssignableRoleLoaded) { + roles = state.roles; + mainRole = state.mainRole; + if (state.rolesUnder.isNotEmpty) { + return ListView.builder( + padding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + itemCount: state.rolesUnder.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + CircleAvatar(child: Text('${index+1}'),), + const SizedBox(width: 12,), + Flexible( + child: Text(state.rolesUnder[index].name!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + + if (value == 1) { + confirmAlert(context, () { + context.read().add( + DeleteEstPointPersonAssignableRoles( + roleId: + state.rolesUnder[index].id!)); + }, "Delete?", "Confirm Delete?"); + } + }, + menuItems: [ + + popMenuItem( + text: "Remove", + value: 1, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ), + ], + ), + ), + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: "No Role available. Please click + to add."); + } + } + if (state is EstPointPersonAssignableErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + context.read().add(GetRoles()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/establishment_point_person/est_point_person_station.dart b/lib/screens/unit2/roles/establishment_point_person/est_point_person_station.dart new file mode 100644 index 0000000..5193ef5 --- /dev/null +++ b/lib/screens/unit2/roles/establishment_point_person/est_point_person_station.dart @@ -0,0 +1,809 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart'; +import 'package:unit2/model/rbac/rbac_station.dart'; +import 'package:unit2/model/roles/pass_check/station_assign_area.dart'; +import 'package:unit2/model/utils/position.dart'; +import 'package:unit2/widgets/Leadings/add_leading.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart'; +import '../../../../model/rbac/station_type.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/alerts.dart'; +import '../../../../utils/global.dart'; +import '../../../../widgets/empty_data.dart'; +import '../../../profile/shared/add_for_empty_search.dart'; + +class EstPointPersonStationScreen extends StatelessWidget { + final String agencyId; + const EstPointPersonStationScreen({ + required this.agencyId, + super.key, + }); + + @override + Widget build(BuildContext context) { + final estPointPersonBloc = + BlocProvider.of(context); + List stations = []; + final formKey = GlobalKey(); + List> hierarchy = []; + bool mainParent = false; + bool isWithinParent = true; + bool isHospital = false; + List stationTypes = []; + List positions = []; + List mainParentStations = []; + List parentStations = []; + RbacStation? selectedMainParentStation; + RbacStation? selectedParentStation; + StationType? selectedStationType; + PositionTitle? selectedPositiontitle; + final addStationTypeController = TextEditingController(); + final stationTypeFocusNode = FocusNode(); + return Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: primary, + title: const Text("Station Screen"), + actions: [ + AddLeading(onPressed: () { + BuildContext parent = context; + mainParentStations = []; + mainParent = stations.isEmpty?true:false; + for (RbacStation station in stations) { + if (station.hierarchyOrderNo == 1) { + mainParentStations.add(station); + } + } + //// Add New Station + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Add New Station"), + content: SingleChildScrollView( + child: FormBuilder( + key: formKey, + child: StatefulBuilder(builder: (context, setState) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ////is main parent + FormBuilderSwitch( + initialValue: mainParent, + activeColor: second, + onChanged: (value) { + setState(() { + mainParent = !mainParent; + }); + }, + decoration: normalTextFieldStyle( + "is Main Parent?", 'is Main Parent?'), + name: 'main-parent', + title: Text(mainParent ? "YES" : "NO"), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + ), + SizedBox( + height: mainParent?0: 8, + ), + //// selected main parent + SizedBox( + child: mainParent == true + ? const SizedBox.shrink() + : FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Main Parent Station", + "Main Parent Station"), + name: "parent-stations", + items: mainParentStations.isEmpty + ? [] + : mainParentStations.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.stationName!), + ); + }).toList(), + onChanged: (RbacStation? e) { + setState(() { + selectedMainParentStation = e; + parentStations = []; + for (RbacStation station + in stations) { + if (station.mainParentStation == + selectedMainParentStation! + .id) { + parentStations.add(station); + } + } + parentStations.add( + selectedMainParentStation!); + }); + }, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + ), + ), + SizedBox( + height: mainParent?0: 8, + ), + ////parent station + SizedBox( + child: mainParent == true + ? const SizedBox.shrink() + : FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Parent Station", "Parent Station"), + name: "parent-stations", + onChanged: (RbacStation? e) { + setState(() { + selectedParentStation = e; + }); + }, + items: parentStations.isEmpty + ? [] + : parentStations.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.stationName!), + ); + }).toList(), + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + ), + ), + const SizedBox( + height: 12, + ), + ////Station Type + SearchField( + itemHeight: 50, + suggestionsDecoration: box1(), + suggestions: stationTypes + .map((StationType stationType) => + SearchFieldListItem( + stationType.typeName!, + item: stationType, + child: Padding( + padding: + const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + stationType.typeName!, + overflow: TextOverflow.visible, + )), + ))) + .toList(), + validator: (station) { + if (station!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: stationTypeFocusNode, + searchInputDecoration: + normalTextFieldStyle("Station Type *", "") + .copyWith( + suffixIcon: GestureDetector( + onTap: () => stationTypeFocusNode.unfocus(), + child: const Icon(Icons.arrow_drop_down), + )), + onSuggestionTap: (position) { + setState(() { + selectedStationType = position.item!; + stationTypeFocusNode.unfocus(); + }); + }, + emptyWidget: EmptyWidget( + title: "Add StationType", + controller: addStationTypeController, + onpressed: () { + setState(() { + StationType stationType = StationType( + id: null, + typeName: + addStationTypeController.text, + color: null, + order: null, + isActive: null, + group: null); + stationTypes.add(stationType); + Navigator.pop(context); + }); + }), + ), + const SizedBox( + height: 12, + ), + ////Position title + FormBuilderDropdown( + decoration: normalTextFieldStyle( + "Head Position", "Head Position"), + name: "head-position", + items: positions.map((e) { + return DropdownMenuItem( + value: e, + child: Text(e.title!), + ); + }).toList(), + onChanged: (title) { + selectedPositiontitle = title; + }, + ), + const SizedBox( + height: 12, + ), + ////is within parent + FormBuilderSwitch( + initialValue: true, + activeColor: second, + onChanged: (value) { + setState(() { + isWithinParent = value!; + }); + }, + decoration: normalTextFieldStyle( + "Location of the station within this parent?", + 'Location of the station within this parent?'), + name: 'isWithinParent', + title: Text(isWithinParent ? "YES" : "NO"), + ), + const SizedBox( + height: 12, + ), + Row( + //// Station Name + children: [ + Flexible( + child: FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This Field is required"), + decoration: normalTextFieldStyle( + "Station name", "Station name"), + name: "station-name"), + ), + const SizedBox( + width: 12, + ), + //// Acronym + Flexible( + child: FormBuilderTextField( + validator: + FormBuilderValidators.required( + errorText: + "This Field is required"), + decoration: normalTextFieldStyle( + "Acronym", "Acronym"), + name: "acronym"), + ), + ], + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + ////Description + decoration: normalTextFieldStyle( + "Station description", + "Station description"), + name: "station-description"), + const SizedBox( + height: 12, + ), + Row( + children: [ + Flexible( + ////Code + child: FormBuilderTextField( + decoration: normalTextFieldStyle( + "Code", "Code"), + name: "code"), + ), + const SizedBox( + width: 12, + ), + Flexible( + //// Full Code + child: FormBuilderTextField( + decoration: normalTextFieldStyle( + "Full Code", "Full Code"), + name: "fullcode"), + ), + ], + ), + const SizedBox( + height: 12, + ), + ////is Hospital + FormBuilderSwitch( + initialValue: isHospital, + activeColor: second, + onChanged: (value) { + setState(() { + isHospital = !isHospital; + }); + }, + decoration: + normalTextFieldStyle("Is Hospital", ''), + name: 'isHospital', + title: Text(isHospital == true ? "YES" : "NO"), + ), + const SizedBox( + height: 20, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + RbacStation? newStation; + if (formKey.currentState! + .saveAndValidate()) { + String? stationName = formKey + .currentState! + .value['station-name']; + String? acronym = formKey + .currentState!.value['acronym']; + String? code = formKey + .currentState!.value['code']; + String? fullcode = formKey + .currentState!.value['fullcode']; + String? description = formKey + .currentState! + .value['station-description']; + newStation = RbacStation( + id: null, + stationName: stationName, + stationType: selectedStationType, + hierarchyOrderNo:mainParent?1: + selectedParentStation! + .hierarchyOrderNo! + + 1, + headPosition: + selectedPositiontitle?.title, + governmentAgency: + GovernmentAgency( + agencyid: int.tryParse( + agencyId), + agencyname: null, + agencycatid: null, + privateEntity: null, + contactinfoid: null), + acronym: acronym, + parentStation: mainParent?null: selectedParentStation!.id!, + + code: code, + fullcode: fullcode, + childStationInfo: null, + islocationUnderParent: + isWithinParent, + mainParentStation: + mainParent?null:selectedMainParentStation! + .id!, + description: description, + ishospital: isHospital, + isactive: true, + sellingStation: null); + Navigator.pop(context); + estPointPersonBloc.add( + AddEstPointPersonStation( + station: newStation)); + } + }, + child: const Text("Add"))), + ], + ); + }), + ), + ), + ); + }); + }) + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: + BlocConsumer( + listener: (context, state) { + if (state is EstPersonStationLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EstPointPersonAddedState) { + if (state.response['success']) { + successAlert( + context, "Adding Successfull!", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add( + EstPointPersonGetStations(agencyId: agencyId.toString())); + }); + } else { + errorAlert(context, "Adding Failed", state.response['message'], + () { + Navigator.of(context).pop(); + context.read().add( + EstPointPersonGetStations(agencyId: agencyId.toString())); + }); + } + } + if (state is EstPersonStationLoadedState || + state is EstPointPersonAddedState || + state is EstPersonStationErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + final parent = context; + if (state is EstPersonStationLoadedState) { + stations = state.stations; + stationTypes = state.stationTypes; + positions = state.positions; + int max = 0; + for (RbacStation station in stations) { + if (station.hierarchyOrderNo != null) { + if (max < station.hierarchyOrderNo!) { + max = station.hierarchyOrderNo!; + } + } + } + for (int i = 1; i <= max; i++) { + hierarchy.add({i: []}); + } + for (var station in stations) { + if (station.hierarchyOrderNo != null) { + for (int i = 0; i <= max; i++) { + if (station.hierarchyOrderNo == i + 1) { + hierarchy[i][i + 1].add(station); + } + } + } + } + + if (stations.isNotEmpty && hierarchy[0][1].isNotEmpty) { + return Column( + children: [ + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: hierarchy[0][1].length, + itemBuilder: (BuildContext context, int index) { + List second = []; + if(max >=2){ + for (var rbacStation in hierarchy[1][2]) { + if (rbacStation.parentStation == + hierarchy[0][1][index].id) { + second.add(rbacStation); + } + } + } + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + const CircleAvatar( + child: Text('1'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + hierarchy[0][1][index] + .stationName!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: + FontWeight.w500, + color: primary)), + ), + ], + )), + ], + ), + ), + ////SECOND + SizedBox( + child: second.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: second.map((e) { + List childs = []; + if (max >= 3) { + for (RbacStation station + in hierarchy[2][3]) { + if (station.parentStation == + e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + child: Container( + width: screenWidth, + decoration: box1() + .copyWith( + boxShadow: []), + padding: + const EdgeInsets + .only( + left: 30), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: + const EdgeInsets.all( + 6), + child: + Text( + "2", + style: Theme.of(context) + .textTheme + .bodyLarge, + selectionColor: + Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text( + e + .stationName!, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + fontWeight: FontWeight.w500, + color: primary)), + ), + ], + )), + ], + ), + ), + ), + ], + ), + ////THIRD + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: + MainAxisSize + .min, + children: childs + .map((e) { + List + childs = []; + if (max >= 4) { + for (RbacStation station + in hierarchy[ + 3] + [4]) { + if (station + .parentStation == + e.id) { + childs.add( + station); + } + } + } else { + childs = []; + } + return Column( + children: [ + Container( + width: + screenWidth, + decoration: + box1() + .copyWith(boxShadow: []), + padding: const EdgeInsets + .only( + left: + 50), + child: + Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6), + child: Text( + "3", + style: Theme.of(context).textTheme.bodyLarge, + selectionColor: Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ////Fourth + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: childs.map((e) { + List childs = []; + if (max > 4) { + for (RbacStation station in hierarchy[4][5]) { + if (station.parentStation == e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1().copyWith(boxShadow: []), + padding: const EdgeInsets.only(left: 80), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6), + child: Text( + "4", + style: Theme.of(context).textTheme.bodyLarge, + selectionColor: Colors.redAccent, + )), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ////Fifth + SizedBox( + child: childs.isNotEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + children: childs.map((e) { + List childs = []; + if (max > 5) { + for (RbacStation station in hierarchy[5][6]) { + if (station.parentStation == e.id) { + childs.add(station); + } + } + } else { + childs = []; + } + + return Column( + children: [ + Container( + width: screenWidth, + decoration: box1(), + padding: const EdgeInsets.only(left: 80), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + const CircleAvatar( + child: Text('5'), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Text(e.stationName!, style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary)), + ), + ], + )), + ], + ), + ), + ], + ); + }).toList(), + ) + : const SizedBox()), + ], + ); + }).toList(), + ) + : const SizedBox()), + ], + ); + }).toList(), + ) + : const SizedBox + .shrink()), + ], + ); + }).toList(), + ) + : const SizedBox()), + const Divider( + height: 5, + ), + ], + ); + }), + ), + ], + ); + } else { + return const EmptyData( + message: "No Station available. Please click + to add."); + } + } + if (state is EstPersonStationErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(GetRoles()); + }); + } + + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart new file mode 100644 index 0000000..0255d85 --- /dev/null +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:toggle_switch/toggle_switch.dart'; + +class CostumToggleSwitch extends StatelessWidget { + final List activeBGColors; + final List icons; +final int initialLabelIndex; + final void Function(int?)? onToggle; + final List labels; + const CostumToggleSwitch( + {Key? key, + required this.activeBGColors, + required this.icons, + required this.onToggle, + required this.labels, + required this.initialLabelIndex + + }) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(15), + height: 80, + child: ToggleSwitch( + animate: true, + minWidth: 150.0, + cornerRadius: 25.0, + activeBgColors: [ + [Colors.green[800]!], + [Colors.red[800]!] + ], + activeFgColor: Colors.white, + inactiveBgColor: Colors.grey, + inactiveFgColor: Colors.white, + initialLabelIndex: initialLabelIndex, + totalSwitches: 2, + labels: labels, + icons: icons, + radiusStyle: true, + onToggle: onToggle), + ); + } +} diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/components/save_settings.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/components/save_settings.dart new file mode 100644 index 0000000..ce4b27c --- /dev/null +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/components/save_settings.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; + +import '../../../../../theme-data.dart/colors.dart'; + +class SelectedState extends StatelessWidget { + final String title; + final String subtitle; + const SelectedState({Key? key,required this.subtitle, required this.title}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 80, + width: double.infinity, + padding: const EdgeInsets.all(10), + child: Wrap( + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + title, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.button!.copyWith( + color: third, fontWeight: FontWeight.bold, fontSize: 18), + ), + Text( + subtitle, + style: Theme.of(context).textTheme.labelMedium, + ), + const Divider(), + + ]), + ], + ), + ); + } +} diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/scan.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/scan.dart new file mode 100644 index 0000000..5e25ab4 --- /dev/null +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/scan.dart @@ -0,0 +1,360 @@ +import 'package:assets_audio_player/assets_audio_player.dart'; +import 'package:audioplayers/audioplayers.dart'; +import 'package:cool_alert/cool_alert.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/role/pass_check/pass_check_bloc.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/utils/validators.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/global.dart'; +import 'components/save_settings.dart'; + +class QRCodeScanner extends StatefulWidget { + const QRCodeScanner({super.key}); + + @override + State createState() => _QRCodeScannerState(); +} + +final GlobalKey scaffoldKey = GlobalKey(); +final formKey = GlobalKey(); +AudioPlayer? player; + +class _QRCodeScannerState extends State { + @override + void initState() { + player = AudioPlayer(); + super.initState(); + } + @override + void dispose() { + player?.dispose(); + super.dispose(); + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + key: scaffoldKey, + appBar: AppBar( + title: const Text(qrScannerTitle), + centerTitle: true, + backgroundColor: primary, + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocConsumer( + listener: (context, state) { + if (state is PassCheckLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is SettingSaved || + state is IncomingScanState || + state is OutGoingScanState || + state is ScanSuccess || + state is ScanFailed || + state is PassCheckErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + if (state is ScanSuccess) { + Future.delayed(const Duration(seconds: 1), () async{ + await player?.play(AssetSource("success.mp3")); + }); + context.read().add(ScanQr(token: state.token)); + } + if (state is QRInvalid) { + Future.delayed(const Duration(seconds: 1), ()async { + await player?.play(AssetSource("invalid.mp3")); + }); + context.read().add(ScanQr(token: state.token)); + } + if (state is ScanFailed) { + Future.delayed(const Duration(seconds: 1), ()async { + await player?.play(AssetSource("fail.mp3")); + }); + + context.read().add(ScanQr(token: state.token)); + } + if (state is IncomingScanState) { + CoolAlert.show( + barrierDismissible: false, + context: context, + type: CoolAlertType.loading, + text: "Enter Temperature", + widget: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: FormBuilder( + key: formKey, + child: Column( + children: [ + const SizedBox( + height: 24, + ), + FormBuilderTextField( + keyboardType: TextInputType.number, + name: "temp", + decoration: + normalTextFieldStyle("Temperature", ""), + validator: numericRequired), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + double temperature = double.parse( + formKey.currentState!.value['temp']); + context.read().add( + PerformIncomingPostLog( + temp: temperature)); + Navigator.of(context).pop(); + } + }, + ), + ) + ], + )), + )); + } + if (state is OutGoingScanState) { + CoolAlert.show( + barrierDismissible: false, + context: context, + type: CoolAlertType.loading, + text: "Enter Destination", + widget: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: FormBuilder( + key: formKey, + child: Column( + children: [ + const SizedBox( + height: 24, + ), + FormBuilderTextField( + textCapitalization: + TextCapitalization.sentences, + name: "destination", + decoration: + normalTextFieldStyle("Destination", ""), + validator: FormBuilderValidators.required( + errorText: "This field is required")), + const SizedBox( + height: 12, + ), + SizedBox( + height: 50, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + child: const Text(submit), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + String destination = formKey + .currentState!.value['destination']; + context.read().add( + PerformOutgoingPostLog( + destination: destination)); + Navigator.of(context).pop(); + } + }, + ), + ) + ], + )), + )); + } + }, + builder: (context, state) { + if (state is SettingSaved) { + return SizedBox( + height: screenHeight * 100, + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox( + height: 40, + ), + GestureDetector( + onTap: () {}, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 160, + child: GestureDetector( + child: Image.asset('assets/pngs/qr-scan.png'), + onTap: () { + context + .read() + .add(ScanQr(token: state.token)); + })), + const SizedBox( + height: 8, + ), + Text( + tapToScanQR, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .displayMedium! + .copyWith( + fontSize: 22, + color: primary, + fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 8, + ), + //TODO add API data + state.io == "INCOMING" + ? SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + incoming, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .displayMedium! + .copyWith( + fontSize: 20, + color: success2, + fontWeight: FontWeight.bold), + ), + const Icon( + Entypo.down_bold, + color: success2, + ) + ], + ), + ) + : SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "OUTGOING", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .displayMedium! + .copyWith( + fontSize: 20, + color: second, + fontWeight: FontWeight.bold), + ), + const Icon( + Entypo.up_bold, + color: second, + ) + ], + ), + ) + ], + ), + ), + Container( + padding: const EdgeInsets.only(top: 12), + decoration: const BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black38, + blurRadius: 30, + offset: Offset(-5, 0), + ), + ], + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15))), + width: double.infinity, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SelectedState( + //TODO add api data + title: state.roleId == 41 || + state.roleId == 13 || + state.roleId == 17 || + state.roleId == 22 + ? state.assignedArea.stationName + : state.roleId == 7 + ? state.assignedArea.brgydesc + : state.roleId == 10 + ? state.assignedArea.purokdesc + : state.roleId == 16 + ? "Agency" + : "", + subtitle: state.roleId == 41 || + state.roleId == 13 || + state.roleId == 17 || + state.roleId == 22 + ? "Station" + : state.roleId == 7 + ? "Barangay" + : state.roleId == 10 + ? "Purok" + : state.roleId == 16 + ? "Agency" + : "", + ), + SelectedState( + //TODO add api data + + title: state.otherInputs ? "YES" : "NO", + subtitle: "Include other inputs", + ), + const SizedBox( + height: 54, + ), + ], + ), + ), + ) + ], + ), + ); + } + if (state is PassCheckErrorState) { + return SomethingWentWrong( + message: state.message, + onpressed: () { + context.read().add(ScanError()); + }); + } + return Container(); + }, + ), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart new file mode 100644 index 0000000..c150df6 --- /dev/null +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart @@ -0,0 +1,630 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:fluttericon/modern_pictograms_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/bloc/role/pass_check/pass_check_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/dashboard.dart'; +import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart'; +import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/scan.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/global.dart'; + +class QRCodeScannerSettings extends StatefulWidget { + final int roleId; + final int userId; + const QRCodeScannerSettings({super.key, required this.roleId, required this.userId}); + + @override + State createState() => _QRCodeScannerSettingsState(); +} + +class _QRCodeScannerSettingsState extends State { + bool _includeOtherInputs = false; + String scanMode = 'INCOMING'; + String selectedLevel = ''; + String selectedEstablishment = ''; + String selectedArea = ''; + dynamic assignedArea; + int? checkerId; + String? token; + final _formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text(qrScannerTitle), + centerTitle: true, + backgroundColor: primary, + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + checkerId = state.userData!.user!.login!.user!.id; + return BlocConsumer( + listener: (context, state) { + if (state is PassCheckLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is AssignAreaLoaded || + state is PassCheckErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + builder: (context, state) { + if (state is AssignAreaLoaded) { + return Container( + height: screenHeight * .90, + padding: const EdgeInsets.symmetric( + horizontal: 42, vertical: 10), + child: FormBuilder( + key: _formKey, + child: Column( + children: [ + Flexible( + child: ListView( + children: [ + const SizedBox( + height: 32, + ), + SvgPicture.asset( + 'assets/svgs/switch.svg', + height: blockSizeVertical * 14, + allowDrawingOutsideViewBox: true, + ), + ListTile( + title: Text( + setQRScannerSettings, + style: Theme.of(context) + .textTheme + .titleLarge! + .copyWith(color: third), + textAlign: TextAlign.center, + ), + ), + Text(includeOtherInputs, + style: Theme.of(context) + .textTheme + .titleMedium), + Text( + includeOtherInputsSubTitle, + style: Theme.of(context) + .textTheme + .bodySmall, + ), + SizedBox( + child: FittedBox( + child: CostumToggleSwitch( + activeBGColors: [ + Colors.green[800]!, + Colors.red[800]! + ], + initialLabelIndex: + _includeOtherInputs ? 0 : 1, + icons: const [ + Entypo.check, + ModernPictograms.cancel + ], + labels: const ['YES', 'NO'], + onToggle: (value) { + value == 0 + ? _includeOtherInputs = true + : _includeOtherInputs = false; + }, + ), + ), + ), + // Incoming or outgoing + Text(incomingORoutgoing, + style: Theme.of(context) + .textTheme + .titleMedium), + Text( + incomingORoutgoingSubTitle, + style: Theme.of(context) + .textTheme + .bodySmall, + ), + FittedBox( + child: CostumToggleSwitch( + activeBGColors: [ + Colors.red[800]!, + Colors.green[800]! + ], + initialLabelIndex: + scanMode == 'INCOMING' ? 0 : 1, + icons: const [ + Entypo.down_bold, + Entypo.up_bold, + ], + labels: const [ + 'INCOMING', + 'OUTGOING' + ], + onToggle: (value) { + value == 0 + ? scanMode = 'INCOMING' + : scanMode = 'OUTGOING'; + }, + ), + ), + const SizedBox( + height: 24, + ), + + ////STATION + Container( + child: state.roleId == 41 + ? DropdownButtonFormField( + isExpanded: true, + validator: FormBuilderValidators + .required( + errorText: + fieldIsRequired), + decoration: + normalTextFieldStyle( + "station", "station"), + items: state.assignedArea + .map((station) { + if (station.motherStation) { + return DropdownMenuItem< + dynamic>( + enabled: false, + value: station, + child: Text( + station.stationName + .toUpperCase(), + style: + const TextStyle( + color: Colors + .grey), + ), + ); + } else { + return DropdownMenuItem< + dynamic>( + value: station, + child: Padding( + padding: + const EdgeInsets + .only( + left: 10), + child: Text(station + .stationName), + ), + ); + } + }).toList(), + // value: selectedLevel, + onChanged: (value) async { + assignedArea = value; + }, + ////BARANGAY + ) + : state.roleId == 7 + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Select Barangay", + textAlign: + TextAlign.start, + style: + Theme.of(context) + .textTheme + .titleMedium, + ), + const SizedBox( + height: 12, + ), + DropdownButtonFormField( + isExpanded: true, + decoration: + normalTextFieldStyle( + "Barangay", + "Barangay"), + items: state + .assignedArea + .map((barangay) { + return DropdownMenuItem< + dynamic>( + value: barangay, + child: Padding( + padding: + const EdgeInsets + .only( + left: + 5), + child: Text( + barangay + .brgydesc), + ), + ); + }).toList(), + onChanged: (value) { + assignedArea = + value; + }, + ), + ], + ) + : + ////PUROK + state.roleId == 10 + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Select Purok", + textAlign: + TextAlign + .start, + style: Theme.of( + context) + .textTheme + .titleMedium, + ), + const SizedBox( + height: 12, + ), + DropdownButtonFormField( + isExpanded: true, + decoration: + normalTextFieldStyle( + "Purok", + "Purok"), + items: state + .assignedArea + .map((purok) { + return DropdownMenuItem< + dynamic>( + value: purok, + child: + Padding( + padding: const EdgeInsets + .only( + left: + 5), + child: Text( + purok + .purokdesc), + ), + ); + }).toList(), + onChanged: + (value) { + assignedArea = + value; + }, + ), + ], + ) + : + ////Registration InCharge + state.roleId == 22 + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Select Station", + textAlign: + TextAlign + .start, + style: Theme.of( + context) + .textTheme + .titleMedium, + ), + const SizedBox( + height: 12, + ), + DropdownButtonFormField( + isExpanded: + true, + validator: FormBuilderValidators + .required( + errorText: + fieldIsRequired), + decoration: normalTextFieldStyle( + "station", + "station"), + items: state + .assignedArea + .map( + (station) { + if (station + .motherStation) { + return DropdownMenuItem< + dynamic>( + enabled: + false, + value: + station, + child: + Text( + station + .stationName + .toUpperCase(), + style: + const TextStyle(color: Colors.grey), + ), + ); + } else { + return DropdownMenuItem< + dynamic>( + value: + station, + child: + Padding( + padding: + const EdgeInsets.only(left: 5), + child: + Text(station.stationName), + ), + ); + } + }).toList(), + // value: selectedLevel, + onChanged: + (value) async { + assignedArea = + value; + }, + ), + ], + ) + : ////QR Code Scanner + state.roleId == 13 + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Select Station", + textAlign: + TextAlign + .start, + style: Theme.of( + context) + .textTheme + .titleMedium, + ), + const SizedBox( + height: + 12, + ), + DropdownButtonFormField( + isExpanded: + true, + validator: + FormBuilderValidators.required( + errorText: fieldIsRequired), + decoration: normalTextFieldStyle( + "station", + "station"), + items: state + .assignedArea + .map( + (station) { + if (station + .motherStation) { + return DropdownMenuItem< + dynamic>( + enabled: + false, + value: + station, + child: + Text( + station.stationName.toUpperCase(), + style: const TextStyle(color: Colors.grey), + ), + ); + } else { + return DropdownMenuItem< + dynamic>( + value: + station, + child: + Padding( + padding: const EdgeInsets.only(left: 5), + child: Text(station.stationName), + ), + ); + } + }).toList(), + // value: selectedLevel, + onChanged: + (value) async { + assignedArea = + value; + }, + ), + ], + ) + : + ////Establishment Point-Person + state.roleId == 16 + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Select Agency", + textAlign: + TextAlign.start, + style: Theme.of(context) + .textTheme + .titleMedium, + ), + const SizedBox( + height: + 12, + ), + DropdownButtonFormField( + isExpanded: + true, + validator: + FormBuilderValidators.required(errorText: fieldIsRequired), + decoration: normalTextFieldStyle( + "Agency", + "Agency"), + items: state + .assignedArea + .map((agency) { + return DropdownMenuItem( + value: agency, + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Text(agency.area.name), + ), + ); + }).toList(), + // value: selectedLevel, + onChanged: + (value) async { + assignedArea = + value; + }, + ), + ], + ) + : ////Office Branch Chief + state.roleId == + 17 + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Select Station", + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox( + height: 12, + ), + DropdownButtonFormField( + isExpanded: true, + validator: FormBuilderValidators.required(errorText: fieldIsRequired), + decoration: normalTextFieldStyle("station", "station"), + items: state.assignedArea.map((station) { + if (station.motherStation) { + return DropdownMenuItem( + enabled: false, + value: station, + child: Text( + station.stationName.toUpperCase(), + style: const TextStyle(color: Colors.grey), + ), + ); + } else { + return DropdownMenuItem( + value: station, + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: Text(station.stationName), + ), + ); + } + }).toList(), + // value: selectedLevel, + onChanged: (value) async { + assignedArea = value; + }, + ), + ], + ) + : Container()) + ], + ), + ), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle(primary, + Colors.transparent, Colors.white54), + child: const Text( + submit, + style: TextStyle(color: Colors.white), + ), + onPressed: () { + if (_formKey.currentState! + .saveAndValidate()) { + print(scanMode); + print(_includeOtherInputs); + print(checkerId); + print(assignedArea); + Navigator.push(context, + MaterialPageRoute(builder: + (BuildContext context) { + return BlocProvider< + PassCheckBloc>.value( + value: PassCheckBloc() + ..add(SetScannerSettings( + token: token!, + assignedArea: assignedArea, + checkerId: checkerId!, + entranceExit: scanMode, + includeOtherInputs: + _includeOtherInputs, + roleId: state.roleId)), + child: const QRCodeScanner(), + ); + })); + } + }, + ), + ), + const SizedBox( + height: 52, + ), + ], + ), + ), + ); + } + if (state is PassCheckErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () { + + context.read().add(GetPassCheckAreas(roleId: widget.roleId, userId: widget.userId)); + }); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} diff --git a/lib/screens/unit2/roles/rbac/add_rbac.dart b/lib/screens/unit2/roles/rbac/add_rbac.dart new file mode 100644 index 0000000..bf7fd3c --- /dev/null +++ b/lib/screens/unit2/roles/rbac/add_rbac.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/theme-data.dart/box_shadow.dart'; + +import '../../../../theme-data.dart/btn-style.dart'; +import '../../../../theme-data.dart/colors.dart'; +import '../../../../theme-data.dart/form-style.dart'; + +class AddRbac extends StatefulWidget { + +final Function() onpressed; +final GlobalKey formKey; +final String title; + const AddRbac({super.key,required this.title,required this.onpressed, required this.formKey}); + + @override + State createState() => _AddRbacState(); +} + +class _AddRbacState extends State { + final formKey = GlobalKey(); + @override + Widget build(BuildContext context) { + return Container( + decoration: box1(), + child: Column(mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 24,), + const Text("No result found"), + const SizedBox(height: 12,), + TextButton(onPressed: (){ + showDialog(context: context,builder: (BuildContext context) { + return AlertDialog( + title: Text(widget.title), + content: FormBuilder( + key: widget.formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FormBuilderTextField( + name: "object_name", + decoration: normalTextFieldStyle("Object name *", "Object name "), + validator: FormBuilderValidators.required(errorText: "This field is required"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "slug", + decoration: normalTextFieldStyle("Slug ", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + name: "shorthand", + decoration: normalTextFieldStyle("Shorthand ", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: widget.onpressed, + child: const Text("Add"))), + ], + ), + ), + ); + }); + }, child: Text(widget.title)) + ], + ), + ); + } +} diff --git a/lib/screens/unit2/roles/rbac/rbac.dart b/lib/screens/unit2/roles/rbac/rbac.dart new file mode 100644 index 0000000..12fe372 --- /dev/null +++ b/lib/screens/unit2/roles/rbac/rbac.dart @@ -0,0 +1,746 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; +import 'package:searchable_paginated_dropdown/searchable_paginated_dropdown.dart'; +import 'package:searchfield/searchfield.dart'; +import 'package:unit2/bloc/rbac/rbac_bloc.dart'; +import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/rbac/new_permission.dart'; +import 'package:unit2/model/rbac/permission.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/error_state.dart'; +import '../../../../model/profile/basic_information/primary-information.dart'; +import '../../../../sevices/roles/rbac_services.dart'; +import '../../../../theme-data.dart/box_shadow.dart'; +import '../../../../theme-data.dart/form-style.dart'; +import '../../../../utils/alerts.dart'; +import 'add_rbac.dart'; + +class RBACScreen extends StatefulWidget { + const RBACScreen({super.key}); + + @override + State createState() => _RBACScreenState(); +} + +class _RBACScreenState extends State { + ////roles + final roleFocusNode = FocusNode(); + final roleController = TextEditingController(); + RBAC? selectedRole; + + ////modules + final moduleFocusNode = FocusNode(); + final moduleController = TextEditingController(); + RBAC? selectedModule; + +////permissions + final permissionFocusNode = FocusNode(); + final permissionController = TextEditingController(); + List valueItemSelectedPermissions = []; + List valueItemPermission = []; + +////Object + RBAC? selectedObject; + final objectFocusNode = FocusNode(); + final objectController = TextEditingController(); + + ////operations + List operationsId = []; + List newOperations = []; + List valueItemOperation = []; + List selectedValueItemOperation = []; + + String? token; + + ////new permission + List newPermissions = []; + + final formKey = GlobalKey(); + final addRbacFormKey = GlobalKey(); + final newOperationKey = GlobalKey(); + int? selectedWebUserId; + bool showAddOperations = false; + @override + void dispose() { + moduleFocusNode.dispose(); + moduleController.dispose(); + roleFocusNode.dispose(); + roleController.dispose(); + permissionFocusNode.dispose(); + permissionController.dispose(); + objectFocusNode.dispose(); + objectController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: const FittedBox( + child: Text("Role Based Access Control"), + ), + backgroundColor: primary, + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocBuilder( + builder: (context, state) { + if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token; + return BlocConsumer( + listener: (context, state) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + if (state is RbacScreenSetted || state is RbacErrorState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + if (state is RbacAssignedState) { + if (state.responseStatus['success']) { + successAlert(context, "Assigning Successfull!", + state.responseStatus['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadRbac()); + }); + } else { + errorAlert(context, "Assigning Failed!", + state.responseStatus['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadRbac()); + }); + } + } + }, + builder: (context, state) { + if (state is RbacScreenSetted) { + //// permission value item + valueItemPermission = + state.permission.map((RBACPermission permission) { + return ValueItem( + label: + "${permission.operation?.name} - ${permission.object?.name!}", + value: permission.id.toString()); + }).toList(); + ////value item operation + valueItemOperation = + state.operations.map((RBAC operation) { + return ValueItem( + label: operation.name!, + value: operation.id.toString()); + }).toList(); + return Container( + padding: const EdgeInsets.symmetric( + vertical: 32, horizontal: 34), + child: FormBuilder( + key: formKey, + child: Column( + children: [ + const SizedBox( + height: 38, + ), + Flexible( + child: Column( + children: [ + ////users + SearchableDropdownFormField.paginated( + margin: const EdgeInsets.all(0), + trailingIcon: const Padding( + padding: EdgeInsets.only(right: 8), + child: Icon( + Icons.arrow_drop_down, + color: Colors.grey, + )), + hintText: const Padding( + padding: EdgeInsets.only(left: 8), + child: Text( + "Search User", + style: TextStyle( + color: Colors.grey, + fontSize: 16), + )), + searchHintText: "Search User", + backgroundDecoration: (child) { + return SizedBox( + width: double.infinity, + child: Container( + width: double.infinity, + height: 50, + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey), + borderRadius: + const BorderRadius.all( + Radius.circular(5))), + child: child, + )); + }, + paginatedRequest: + (int page, String? searchKey) async { + List users = await RbacServices + .instance + .searchUser( + page: page, + name: searchKey ??= "", + token: token!); + return users.map((e) { + String fullname = + "${e.firstName} ${e.lastName}"; + return SearchableDropdownMenuItem< + Profile>( + label: fullname, + child: ListTile( + title: Text(fullname), + subtitle: + Text(e.birthdate.toString()), + ), + onTap: () { + setState(() { + selectedWebUserId = e.webuserId; + }); + }, + ); + }).toList(); + }, + ), + + const SizedBox( + height: 12, + ), + ////Role + StatefulBuilder( + builder: (context, setState) { + return SearchField( + itemHeight: 40, + suggestionsDecoration: box1(), + suggestions: state.role + .map((RBAC role) => + SearchFieldListItem( + role.name!, + item: role, + child: Padding( + padding: + const EdgeInsets + .symmetric( + horizontal: 10), + child: ListTile( + title: Text( + role.name!, + overflow: TextOverflow + .visible, + )), + ))) + .toList(), + validator: (agency) { + if (agency!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: roleFocusNode, + searchInputDecoration: + normalTextFieldStyle("Role *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + roleFocusNode.unfocus(); + }, + )), + onSuggestionTap: (role) { + setState(() { + selectedRole = role.item; + roleFocusNode.unfocus(); + }); + }, + ////Add new role + emptyWidget: AddRbac( + formKey: addRbacFormKey, + title: "Add Role", + onpressed: () { + RBAC? newRole; + if (addRbacFormKey.currentState! + .saveAndValidate()) { + newRole = RBAC( + id: null, + name: addRbacFormKey + .currentState + ?.value['object_name'], + slug: addRbacFormKey + .currentState + ?.value['slug'], + shorthand: addRbacFormKey + .currentState + ?.value['shorthand'], + fontawesomeIcon: null, + createdAt: null, + updatedAt: null, + createdBy: null, + updatedBy: null); + } + setState(() { + state.role.insert(0, newRole!); + }); + roleFocusNode.unfocus(); + Navigator.pop(context); + }, + )); + }), + const SizedBox( + height: 12, + ), + // //// Modules + StatefulBuilder( + builder: (context, setState) { + return SearchField( + itemHeight: 40, + suggestionsDecoration: box1(), + suggestions: state.modules + .map((RBAC module) => + SearchFieldListItem( + module.name!, + item: module, + child: Padding( + padding: + const EdgeInsets + .symmetric( + horizontal: 10), + child: ListTile( + title: Text( + module.name!, + overflow: TextOverflow + .visible, + )), + ))) + .toList(), + validator: (module) { + if (module!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: moduleFocusNode, + searchInputDecoration: + normalTextFieldStyle( + "Module *", "") + .copyWith( + suffixIcon: IconButton( + icon: const Icon( + Icons.arrow_drop_down), + onPressed: () { + moduleFocusNode.unfocus(); + }, + )), + onSuggestionTap: (module) { + setState(() { + selectedModule = module.item; + moduleFocusNode.unfocus(); + }); + }, + // //// Add new module + + emptyWidget: AddRbac( + formKey: addRbacFormKey, + title: "Add Module", + onpressed: () { + RBAC? newModule; + if (addRbacFormKey.currentState! + .saveAndValidate()) { + newModule = RBAC( + id: null, + name: addRbacFormKey + .currentState + ?.value['object_name'], + slug: addRbacFormKey + .currentState + ?.value['slug'], + shorthand: addRbacFormKey + .currentState + ?.value['shorthand'], + fontawesomeIcon: null, + createdAt: null, + updatedAt: null, + createdBy: null, + updatedBy: null); + } + setState(() { + state.modules + .insert(0, newModule!); + }); + moduleFocusNode.unfocus(); + Navigator.pop(context); + }, + )); + }), + const SizedBox( + height: 12, + ), + //// Permission + + StatefulBuilder( + builder: (context, setState) { + return SizedBox( + width: double.infinity, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(5), + border: Border.all( + color: Colors.grey)), + child: Row( + children: [ + Expanded( + child: MultiSelectDropDown( + onOptionSelected: + (List + selectedOptions) { + setState(() { + valueItemSelectedPermissions = + selectedOptions; + }); + }, + hint: "Permissions", + hintStyle: const TextStyle( + fontSize: 16, + color: Colors.grey), + padding: + const EdgeInsets.all(8), + options: valueItemPermission, + selectionType: + SelectionType.multi, + chipConfig: const ChipConfig( + wrapType: + WrapType.scroll), + dropdownHeight: 300, + optionTextStyle: + const TextStyle( + fontSize: 16), + selectedOptionIcon: + const Icon( + Icons.check_circle), + ), + ), + const SizedBox( + width: 6, + ), + IconButton( + ////Add Permission not the dialog add button + onPressed: () { + final addPermissionFormKey = + GlobalKey(); + showDialog( + context: context, + builder: (BuildContext + context) { + String? objectname; + String? slug; + String? shorthand; + return AlertDialog( + title: Row( + children: [ + Expanded( + child: + Container( + child: !showAddOperations + ? const Text( + "Add new Permission") + : const Text( + "Add new Operation"), + ), + ), + ////close button + IconButton( + onPressed: + () { + setState( + () { + showAddOperations = + false; + }); + Navigator.pop( + context); + }, + icon: const Icon( + Icons + .close)) + ], + ), + content: StatefulBuilder( + builder: (context, + stateSetter) { + return showAddOperations + ////add permission content if choice is in the choices + ? FormBuilder( + key: + newOperationKey, + child: + Column( + mainAxisSize: + MainAxisSize.min, + children: [ + FormBuilderTextField( + onChanged: (value) { + objectname = value!; + }, + autovalidateMode: AutovalidateMode.always, + validator: FormBuilderValidators.required(errorText: "This field is required"), + name: "object_name", + decoration: normalTextFieldStyle("Object name *", "Object name "), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + onChanged: (value) { + slug = value!; + }, + name: "slug", + decoration: normalTextFieldStyle("Slug *", "Slug"), + ), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + onChanged: (value) { + shorthand = value!; + }, + name: "shorthand", + decoration: normalTextFieldStyle("Shorthand *", "Shorthand"), + ), + const SizedBox( + height: 12, + ), + SizedBox( + width: double.infinity, + height: 50, + /////Add new Operation submit button + child: ElevatedButton( + style: mainBtnStyle(primary, Colors.transparent, second), + onPressed: () async { + if (newOperationKey.currentState!.saveAndValidate()) { + RBAC newOperation = RBAC(id: null, name: objectname, slug: slug, shorthand: shorthand, fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null); + stateSetter(() { + newOperations.add(newOperation); + valueItemOperation.insert(0, ValueItem(label: newOperation.name!, value: newOperation.name)); + showAddOperations = false; + }); + } + }, + child: const Text("Add"))), + ], + ), + ) + ////add permission content if choice is in the choices + : Form( + key: + addPermissionFormKey, + child: + Column( + mainAxisSize: + MainAxisSize.min, + children: [ + ////Object + SizedBox( + width: double.infinity, + child: + ////Row ofr operation and add operation + Row( + children: [ + ////Operations + Expanded( + child: MultiSelectDropDown( + onOptionSelected: (List selectedOptions) { + stateSetter(() { + ////get operation ids + selectedValueItemOperation = selectedOptions; + }); + }, + borderColor: Colors.grey, + borderWidth: 1, + borderRadius: 5, + hint: "Operations", + hintStyle: const TextStyle(fontSize: 16, color: Colors.grey), + padding: const EdgeInsets.all(8), + options: valueItemOperation, + selectionType: SelectionType.multi, + chipConfig: const ChipConfig(wrapType: WrapType.wrap), + dropdownHeight: 300, + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: const Icon(Icons.check_circle), + ), + ), + const SizedBox( + width: 5, + ), + Container( + decoration: BoxDecoration(border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(5)), + child: IconButton( + ////Add Operation beside row button + onPressed: () { + stateSetter(() { + showAddOperations = true; + }); + }, + icon: const Icon(Icons.add)), + ) + ], + )), + const SizedBox( + height: 12, + ), + SearchField( + itemHeight: 40, + suggestionsDecoration: box1(), + suggestions: state.objects + .map((RBAC object) => SearchFieldListItem(object.name!, + item: object, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: ListTile( + title: Text( + object.name!, + overflow: TextOverflow.visible, + )), + ))) + .toList(), + validator: (module) { + if (module!.isEmpty) { + return "This field is required"; + } + return null; + }, + focusNode: objectFocusNode, + searchInputDecoration: normalTextFieldStyle("Object *", "").copyWith( + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_drop_down), + onPressed: () { + objectFocusNode.unfocus(); + }, + )), + onSuggestionTap: (object) { + stateSetter(() { + selectedObject = object.item; + objectFocusNode.unfocus(); + }); + }, + ////Add new Object + emptyWidget: AddRbac( + formKey: addRbacFormKey, + title: "Add Add Object", + onpressed: () { + if (addRbacFormKey.currentState!.saveAndValidate()) { + RBAC? newObject; + + if (addRbacFormKey.currentState!.saveAndValidate()) { + newObject = RBAC(id: null, name: addRbacFormKey.currentState?.value['object_name'], slug: addRbacFormKey.currentState?.value['slug'], shorthand: addRbacFormKey.currentState?.value['shorthand'], fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null); + } + stateSetter(() { + state.objects.insert(0, newObject!); + }); + objectFocusNode.unfocus(); + Navigator.pop(context); + } + }, + )), + const SizedBox( + height: 20, + ), + SizedBox( + width: double.infinity, + height: 50, + child: ElevatedButton( + onPressed: () { + ////Add Operation + if (addPermissionFormKey.currentState!.validate()) { + selectedValueItemOperation.forEach((e) { + setState(() { + // state.permission.insert(0, Permission(id: null, object: selectedObject!, operation: RBAC(id: null, name: e.label, slug: null, shorthand: null, fontawesomeIcon: null, createdAt: null, updatedAt: null, createdBy: null, updatedBy: null), createdAt: null, updatedAt: null, createdBy: null, updatedBy: null)); + valueItemPermission.insert(0, ValueItem(label: "${selectedObject!.name} - ${e.label}")); + valueItemPermission = valueItemPermission; + }); + }); + Navigator.pop(context); + setState(() {}); + } + }, + style: mainBtnStyle(primary, Colors.transparent, second), + child: const Text("Submit"), + )) + ], + )); + })); + }); + }, + icon: const Icon(Icons.add)), + ], + ), + ), + ); + }), + const SizedBox( + height: 12, + ), + ], + )), + SizedBox( + height: 50, + width: double.infinity, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState! + .saveAndValidate()) { + ////existing permission + List permissions = + valueItemSelectedPermissions + .map((e) => + int.parse(e.value!)) + .toList(); + + context.read().add( + AssignedRbac( + assigneeId: + selectedWebUserId!, + assignerId: 63, + newPermissions: [], + permissionId: permissions, + selectedModule: + selectedModule, + selectedRole: selectedRole)); + } + print(valueItemSelectedPermissions + .length); + }, + child: const Text("submit")), + ) + ], + )), + ); + } + if (state is RbacErrorState) { + return SomethingWentWrong( + message: state.message, onpressed: () {}); + } + return Container(); + }, + ); + } + return Container(); + }, + ), + )); + } +} diff --git a/lib/screens/unit2/roles/registration_in_charge/components/add.dart b/lib/screens/unit2/roles/registration_in_charge/components/add.dart new file mode 100644 index 0000000..45b3b71 --- /dev/null +++ b/lib/screens/unit2/roles/registration_in_charge/components/add.dart @@ -0,0 +1,232 @@ +import 'package:date_time_picker/date_time_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/widgets/label.dart'; +import '../../../../../test_data.dart'; +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; + +class AddPerson extends StatefulWidget { + const AddPerson({super.key}); + + @override + State createState() => _AddPersonState(); +} + +class _AddPersonState extends State { + final _formKey = GlobalKey(); + + DateFormat dteFormat = DateFormat("y-M-d"); + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 25), + child: SingleChildScrollView( + child: FormBuilder( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Label(text: basicInformation), + //Firstname + FormBuilderTextField( + name: 'firstname', + validator: FormBuilderValidators.required( + errorText: "First name is required"), + autofocus: false, + decoration: normalTextFieldStyle("First name", ""), + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.text, + ), + const SizedBox( + height: 10, + ), + //Firstname + FormBuilderTextField( + name: 'lastname', + validator: FormBuilderValidators.required( + errorText: "Middle name is required"), + autofocus: false, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.text, + decoration: normalTextFieldStyle("Last name", "")), + const SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + flex: 2, + child: FormBuilderTextField( + name: 'middlename', + validator: FormBuilderValidators.required( + errorText: "Middle name is required"), + autofocus: false, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.text, + decoration: normalTextFieldStyle("Middle name", "")), + ), + const SizedBox( + width: 10, + ), + Expanded( + flex: 1, + child: DateTimePicker( + decoration: normalTextFieldStyle("Birth date", ""), + initialValue: '', + firstDate: DateTime(2000), + lastDate: DateTime(2100), + dateLabelText: 'Date', + onChanged: (val) => print(val), + validator: (val) { + if (val!.isEmpty) { + return "Birthdate is required"; + } + return null; + }, + onSaved: (val) => print(val), + ), + ) + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + flex: 1, + child: FormBuilderTextField( + name: 'extension-name', + autofocus: false, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.text, + decoration: + normalTextFieldStyle("Extenstion name", "")), + ), + const SizedBox( + width: 10, + ), + Expanded( + flex: 1, + child: FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "Gender is required"), + name: 'gender', + autofocus: false, + decoration: normalTextFieldStyle("Gender", ""), + items: genders + .map((gender) => DropdownMenuItem( + value: gender, + child: Text(gender), + )) + .toList()), + ) + ], + ), + const Label(text: address), + FormBuilderDropdown( + name: 'region', + autofocus: false, + validator: FormBuilderValidators.required( + errorText: "Region is required"), + decoration: normalTextFieldStyle("Region", ""), + items: regions + .map((region) => DropdownMenuItem( + value: region, + child: Text(region), + )) + .toList()), + const SizedBox( + height: 10, + ), + FormBuilderDropdown( + name: 'province', + autofocus: false, + validator: FormBuilderValidators.required( + errorText: "Province is required"), + decoration: normalTextFieldStyle("Province", ""), + items: provinces + .map((province) => DropdownMenuItem( + value: province, + child: Text(province), + )) + .toList()), + const SizedBox( + height: 10, + ), + FormBuilderDropdown( + name: 'municipality', + autofocus: false, + validator: FormBuilderValidators.required( + errorText: "Municipality is required"), + decoration: normalTextFieldStyle("Municipalities", ""), + items: municipalities + .map((municipality) => DropdownMenuItem( + value: municipality, + child: Text(municipality), + )) + .toList()), + const SizedBox( + height: 10, + ), + FormBuilderDropdown( + name: 'barangay', + autofocus: false, + validator: FormBuilderValidators.required( + errorText: "Barangay is required"), + decoration: normalTextFieldStyle("Barangay", ""), + items: barangays + .map((barangay) => DropdownMenuItem( + value: barangay, + child: Text(barangay), + )) + .toList()), + const SizedBox( + height: 10, + ), + FormBuilderDropdown( + name: 'purok', + autofocus: false, + validator: FormBuilderValidators.required( + errorText: "Purok is required"), + decoration: normalTextFieldStyle("Purok", ""), + items: puroks + .map((purok) => DropdownMenuItem( + value: purok, + child: Text(purok), + )) + .toList()), + const SizedBox( + height: 10, + ), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle( + second, Colors.transparent, Colors.white54), + child: const Text( + submit, + style: TextStyle(color: Colors.white), + ), + onPressed: () { + print(_formKey.currentState!.value['firstname']); + if (_formKey.currentState!.saveAndValidate()) {} + }, + ), + ), + const SizedBox( + height: 20, + ), + ], + )), + ), + ); + } +} diff --git a/lib/screens/unit2/roles/registration_in_charge/components/request_qr.dart b/lib/screens/unit2/roles/registration_in_charge/components/request_qr.dart new file mode 100644 index 0000000..7f95879 --- /dev/null +++ b/lib/screens/unit2/roles/registration_in_charge/components/request_qr.dart @@ -0,0 +1,19 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; + +class RequestQR extends StatefulWidget { + const RequestQR({super.key}); + + @override + State createState() => _RequestQRState(); +} + +class _RequestQRState extends State { + @override + Widget build(BuildContext context) { + return Container( + child: Center(child: Text("Request QR")), + ); + } +} diff --git a/lib/screens/unit2/roles/registration_in_charge/components/sync.dart b/lib/screens/unit2/roles/registration_in_charge/components/sync.dart new file mode 100644 index 0000000..02e0236 --- /dev/null +++ b/lib/screens/unit2/roles/registration_in_charge/components/sync.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:fluttericon/linearicons_free_icons.dart'; +import 'package:fluttericon/octicons_icons.dart'; +import 'package:fluttericon/typicons_icons.dart'; +import 'package:unit2/widgets/label.dart'; + +import '../../../../../theme-data.dart/btn-style.dart'; +import '../../../../../theme-data.dart/colors.dart'; +import '../../../../../utils/global.dart'; +import '../../../../../utils/text_container.dart'; + +class SyncData extends StatefulWidget { + const SyncData({super.key}); + + @override + State createState() => _SyncDataState(); +} + +class _SyncDataState extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 25), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + const Label(text: syncTitle), + Icon( + Octicons.sync_icon, + size: blockSizeVertical * 25, + color: success2, + ), + Column( + children: [ + const Text(syncSubTittle), + const SizedBox( + height: 10, + ), + SizedBox( + width: double.infinity, + height: screenHeight * .06, + child: ElevatedButton( + style: secondaryBtnStyle( + second, Colors.transparent, Colors.white54), + child: const Text( + syncNow, + style: TextStyle(color: Colors.white), + ), + onPressed: () {}, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/screens/unit2/roles/registration_in_charge/components/view.dart b/lib/screens/unit2/roles/registration_in_charge/components/view.dart new file mode 100644 index 0000000..a103af9 --- /dev/null +++ b/lib/screens/unit2/roles/registration_in_charge/components/view.dart @@ -0,0 +1,100 @@ +import 'package:azlistview/azlistview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:fluttericon/octicons_icons.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; + +import '../../../../../test_data.dart'; +import '../../../../../theme-data.dart/text-styles.dart'; + +class _AZItem extends ISuspensionBean { + final String title; + final String tag; + + _AZItem({required this.title, required this.tag}); + + @override + String getSuspensionTag() { + return tag; + } +} + +class ViewList extends StatefulWidget { + const ViewList({super.key}); + + @override + State createState() => _ViewListState(); +} + +class _ViewListState extends State { + List<_AZItem> convertedPersonList = []; + @override + void initState() { + addedPersons.sort( + (a, b) => a.lastname.toLowerCase().compareTo(b.lastname.toLowerCase())); + initList(addedPersons); + super.initState(); + } + + void initList(List persons) { + convertedPersonList = persons + .map((person) => _AZItem( + title: person.lastname + ' ' + person.name, + tag: person.lastname[0])) + .toList(); + SuspensionUtil.sortListBySuspensionTag(persons); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return AzListView( + data: addedPersons, + itemCount: addedPersons.length, + itemBuilder: (BuildContext context, int index) { + final person = convertedPersonList[index]; + return _buildListItem(person, true); + }, + physics: const BouncingScrollPhysics(), + indexBarItemHeight: blockSizeVertical * 3, + indexBarData: SuspensionUtil.getTagIndexList(addedPersons), + indexBarMargin: const EdgeInsets.all(0), + indexBarOptions: const IndexBarOptions( + selectItemDecoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey, + ), + selectTextStyle: + TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + needRebuild: true, + )); + } + + _buildListItem(_AZItem person, bool selected) { + return Card( + elevation: 0, + child: ListTile( + onTap: (() => setState(() { + selected = !selected; + })), + dense: true, + subtitle: Text( + "December 15 1994", + style: Theme.of(context).textTheme.caption, + ), + leading: Checkbox( + onChanged: (value) { + selected = value!; + setState(() {}); + print(selected); + }, + value: selected, + ), + title: Text( + person.title, + style: personInfo(), + ))); + } +} diff --git a/lib/screens/unit2/roles/registration_in_charge/home.dart b/lib/screens/unit2/roles/registration_in_charge/home.dart new file mode 100644 index 0000000..d778b69 --- /dev/null +++ b/lib/screens/unit2/roles/registration_in_charge/home.dart @@ -0,0 +1,88 @@ +import 'package:convex_bottom_bar/convex_bottom_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:fluttericon/iconic_icons.dart'; +import 'package:unit2/screens/unit2/roles/registration_in_charge/components/add.dart'; +import 'package:unit2/screens/unit2/roles/registration_in_charge/components/request_qr.dart'; +import 'package:unit2/screens/unit2/roles/registration_in_charge/components/sync.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/text_container.dart'; + +import 'components/view.dart'; + +class RegistrationInCharge extends StatefulWidget { + const RegistrationInCharge({super.key}); + + @override + State createState() => _RegistrationInChargeState(); +} + +class _RegistrationInChargeState extends State { + final List _pages = [ + const ViewList(), + const AddPerson(), + const SyncData(), + const RequestQR() + ]; + int currentIndex = 0; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text(registrationInChargeTitle), + backgroundColor: second, + centerTitle: true, + actions: [ + IconButton( + // ##SEARCH BUTTON + icon: const Icon(Icons.search), + color: Colors.white, + onPressed: () { + // Navigator.pushNamed(context, '/Registration Search'); + }, + ), + PopupMenuButton( + onSelected: (value) { + // SORT VIA DATE ADDED + if (value == 1) { + } + // SORT VIA LAST NAME + else if (value == 2) {} + }, + itemBuilder: (context) => [ + PopupMenuItem( + value: 1, + child: Row( + children: const [Text('Sort By Date Added')], + )), + PopupMenuItem( + value: 2, + child: Row( + children: const [Text('Sort by Lastname')], + )), + ]), + ], + ), + bottomNavigationBar: ConvexAppBar( + color: Colors.white70, + gradient: primaryGradient(), + style: TabStyle.react, + items: const [ + TabItem(icon: Entypo.home, title: "Home"), + TabItem(icon: Iconic.plus_circle, title: "Add"), + TabItem(icon: Iconic.loop, title: "Sync"), + TabItem(icon: FontAwesome.qrcode, title: "Request QR"), + ], + initialActiveIndex: 0, + onTap: (int i) { + setState(() { + currentIndex = i; + }); + }), + body: _pages[currentIndex], + ); + } +} diff --git a/lib/screens/unit2/signature/signature_pad.dart b/lib/screens/unit2/signature/signature_pad.dart new file mode 100644 index 0000000..2a4b404 --- /dev/null +++ b/lib/screens/unit2/signature/signature_pad.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:signature/signature.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class SignaturePad extends StatefulWidget { + const SignaturePad({super.key}); + + @override + State createState() => _SignaturePadState(); +} + +class _SignaturePadState extends State { + SignatureController? _signatureController; + + @override + void initState() { + _signatureController = SignatureController( + penStrokeWidth: 3, + penColor: Colors.black87, + ); + super.initState(); + } + + @override + void dispose() { + _signatureController!.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Create Signature"), + centerTitle: true, + backgroundColor: second, + automaticallyImplyLeading: true, + ), + body: Signature( + controller: _signatureController!, + backgroundColor: Colors.white, + ), + ); + } +} diff --git a/lib/screens/utils/formatters.dart b/lib/screens/utils/formatters.dart new file mode 100644 index 0000000..b9f78bb --- /dev/null +++ b/lib/screens/utils/formatters.dart @@ -0,0 +1 @@ +// TODO Implement this library. \ No newline at end of file diff --git a/lib/sevices/docsms/docsms_service.dart b/lib/sevices/docsms/docsms_service.dart new file mode 100644 index 0000000..f6bb665 --- /dev/null +++ b/lib/sevices/docsms/docsms_service.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; +import '../../model/docsms/document.dart'; + +class AutoReceiveDocumentServices{ + static final AutoReceiveDocumentServices _instance = AutoReceiveDocumentServices(); + static AutoReceiveDocumentServices get instance => _instance; + + Future getDocument(String documentId) async { + String path = Url.instance.getDocument(); + Document? document; + Map params = {"t1.id": documentId.toString()}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance.getRequest(param: params,path:path,headers:headers); + + if (response.statusCode == 200) { + Map data = json.decode(response.body); + if(data['message'].toString().toLowerCase() == "data successfully fetched."){ + document = Document.fromJson(data['data']); + }else{ + document = null; + } + } + } catch (e) { + throw (e.toString()); + } + return document; + } + +} \ No newline at end of file diff --git a/lib/sevices/login_service/auth_service.dart b/lib/sevices/login_service/auth_service.dart new file mode 100644 index 0000000..97720c9 --- /dev/null +++ b/lib/sevices/login_service/auth_service.dart @@ -0,0 +1,78 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'package:unit2/model/login_data/user_info/user_data.dart'; +import 'package:unit2/model/login_data/version_info.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../utils/urls.dart'; + +class AuthService { + static final AuthService _instance = AuthService(); + static AuthService get instance => _instance; + + Future getVersionInfo() async { + VersionInfo versionInfo = VersionInfo(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + HttpHeaders.authorizationHeader: 'UniT2', + 'X-User': "" + }; + try { + String path = Url.instance.latestApk(); + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + versionInfo = VersionInfo.fromJson(data['data']); + } + } catch (e) { + throw (e.toString()); + } + return versionInfo; + } + + Future> webLogin( + {String? username, String? password}) async { + Map body = {'username': username!, 'password': password!}; + Map baseHeaders = {'Content-Type': 'application/json'}; + Map responseStatus = {}; + String path = Url.instance.authentication(); + // try { + http.Response response = await Request.instance + .postRequest(path: path, param: {}, headers: baseHeaders, body: body); + Map data = jsonDecode(response.body); + responseStatus = data; + + return responseStatus; + // } catch (e) { + // throw (e.toString()); + // } + } + + Future> qrLogin({String? uuid, String? password}) async { + + Map responseStatus = {}; + Map body = { + 'uuid': uuid!, + 'password': password!, + "login_only": false, + "token": false + }; + Map baseHeaders = {'Content-Type': 'application/json'}; + String path = Url.instance.authentication(); + UserData? userData; + try { + http.Response response = await Request.instance + .postRequest(path: path, param: {}, headers: baseHeaders, body: body); + + Map data = jsonDecode(response.body); + responseStatus = data; + + } catch (e) { + throw (e.toString()); + } + return responseStatus; + } +} diff --git a/lib/sevices/passo/barangay.dart b/lib/sevices/passo/barangay.dart new file mode 100644 index 0000000..24490a1 --- /dev/null +++ b/lib/sevices/passo/barangay.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/barangay.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class BarangayServices { + static final BarangayServices _instance = BarangayServices(); + static BarangayServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(id) async { + String path = Url.instance.getBarangay(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "city_code": id.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => Brgy.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/building/additional_items_services.dart b/lib/sevices/passo/building/additional_items_services.dart new file mode 100644 index 0000000..b2a4441 --- /dev/null +++ b/lib/sevices/passo/building/additional_items_services.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; + +import '../../../utils/urls.dart'; + +class AdditionalItemsServices { + static final AdditionalItemsServices _instance = AdditionalItemsServices(); + static AdditionalItemsServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.additionalItems(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + print(result); + return result.map(((e) => AdditionalItems.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(AdditionalItems items) async { + String path = Url.instance.additionalItems(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: items.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future remove(id) async { + String path = Url.instance.additionalItems(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id.toString(), + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: params); + print(id); + if (response.statusCode == 200) { + print(response.body); + return response; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/building/general_description_services.dart b/lib/sevices/passo/building/general_description_services.dart new file mode 100644 index 0000000..17552c8 --- /dev/null +++ b/lib/sevices/passo/building/general_description_services.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class GeneralDescriptionServices { + static final GeneralDescriptionServices _instance = + GeneralDescriptionServices(); + static GeneralDescriptionServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future fetch(tempID) async { + String path = Url.instance.generalDescription(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('GenDescEdit'); + print(response.body); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = + GeneralDesc.fromJson(dataList[0] as Map); + + return result; + } else { + print(response.reasonPhrase); + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future update(GeneralDesc data, id) async { + String path = Url.instance.generalDescription(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id, + }; + http.Response? response; + try { + print(id); + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + print(response.body); + } catch (e) { + throw e.toString(); + } + return response; + } +} diff --git a/lib/sevices/passo/building/landref_services.dart b/lib/sevices/passo/building/landref_services.dart new file mode 100644 index 0000000..ef90ba5 --- /dev/null +++ b/lib/sevices/passo/building/landref_services.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandRefServices { + static final LandRefServices _instance = LandRefServices(); + static LandRefServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future fetch(tempID) async { + String path = Url.instance.landRef(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('land ref'); + print(response.statusCode); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = LandRef.fromJson(dataList[0] as Map); + + return result; + } else { + print(response.reasonPhrase); + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/building/location_landref_services.dart b/lib/sevices/passo/building/location_landref_services.dart new file mode 100644 index 0000000..b916aa8 --- /dev/null +++ b/lib/sevices/passo/building/location_landref_services.dart @@ -0,0 +1,68 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LocationLandrefServices { + static final LocationLandrefServices _instance = LocationLandrefServices(); + static LocationLandrefServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future update(BldgLoc data, id) async { + String path = Url.instance.bldgLocation(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future fetch(tempID) async { + String path = Url.instance.bldgLocation(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + + print('BldgLocEdit'); + print(response.body); + + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = BldgLoc.fromJson(dataList[0] as Map); + + return result; + } else { + print(response.reasonPhrase); + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/building/property_appraisal_services.dart b/lib/sevices/passo/building/property_appraisal_services.dart new file mode 100644 index 0000000..2000441 --- /dev/null +++ b/lib/sevices/passo/building/property_appraisal_services.dart @@ -0,0 +1,133 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:unit2/model/passo/property_appraisal.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import '../../../model/passo/property_appraisal_edit.dart'; + +class PropertyAppraisalServices { + static final PropertyAppraisalServices _instance = + PropertyAppraisalServices(); + static PropertyAppraisalServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future fetch() async { + final tempID = await SharedPreferences.getInstance(); + print('sds'); + print(tempID.getInt('tempid')! - 1); + final id = tempID.getInt('tempid')! - 1; + String path = Url.instance.propertyAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('Appraisal TEMPID'); + print(response.body); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = + PropertyAppraisal.fromJson(dataList[0] as Map); + return result; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future update(PropertyAppraisal appraisal, tempID) async { + String path = Url.instance.propertyAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + print(tempID); + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, + body: appraisal.toJson(), + headers: headers, + param: params); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future fetchEdit(id) async { + String path = Url.instance.propertyAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('Property_Apraisaledit'); + print(response.statusCode); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = + PropertyAppraisalEdit.fromJson(dataList[0] as Map); + + return result; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future updateAppraisal( + PropertyAppraisalEdit appraisal, tempID) async { + String path = Url.instance.propertyAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID, + }; + print(tempID); + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, + body: appraisal.toJson(), + headers: headers, + param: params); + } catch (e) { + log(e.toString()); + } + return response; + } +} diff --git a/lib/sevices/passo/building/property_assessment_services.dart b/lib/sevices/passo/building/property_assessment_services.dart new file mode 100644 index 0000000..3ac71ca --- /dev/null +++ b/lib/sevices/passo/building/property_assessment_services.dart @@ -0,0 +1,158 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/property_assessment.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class PropertyAssessmentServices { + static final PropertyAssessmentServices _instance = + PropertyAssessmentServices(); + static PropertyAssessmentServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('Assessment'); + print(response.statusCode); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => PropertyAssessment.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(PropertyAssessment assessment) async { + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: assessment.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future update(PropertyAssessment assessment, id) async { + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, + body: assessment.toJson(), + headers: headers, + param: params); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future fetchEdit(tempID) async { + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('Assessment'); + print(response.body); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = PropertyAssessmentEdit.fromJson( + dataList[0] as Map); + + return result; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future addEdit(PropertyAssessmentEdit assessment) async { + Map statusResponse = {}; + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: assessment.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future updateEdit( + PropertyAssessmentEdit assessment, id) async { + String path = Url.instance.propertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, + body: assessment.toJson(), + headers: headers, + param: params); + } catch (e) { + log(e.toString()); + } + return response; + } +} diff --git a/lib/sevices/passo/building/property_info_services.dart b/lib/sevices/passo/building/property_info_services.dart new file mode 100644 index 0000000..ac90a92 --- /dev/null +++ b/lib/sevices/passo/building/property_info_services.dart @@ -0,0 +1,137 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/bldg_loc.dart'; +import 'package:unit2/model/passo/general_description.dart'; +import 'package:unit2/model/passo/land_ref.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class PropertyInfoService { + static final PropertyInfoService _instance = PropertyInfoService(); + static PropertyInfoService get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.propertyInfo(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => PropertyInfo.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(PropertyInfo faas) async { + Map statusResponse = {}; + String path = Url.instance.propertyInfo(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: faas.toJson(), headers: headers); + } catch (e) { + throw e.toString(); + } + return response; + } + + Future update(PropertyInfo data, id) async { + String path = "${Url.instance.propertyInfo()}$id/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: {}); + } catch (e) { + throw e.toString(); + } + return response; + } + + Future updateBldg(BldgLoc data, id) async { + String path = Url.instance.bldgLocation(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + throw e.toString(); + } + return response; + } + + Future updateLandRef(LandRef data, id) async { + String path = Url.instance.landRef(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + throw e.toString(); + } + return response; + } + + Future updateGenDesc(GeneralDesc data, id) async { + String path = Url.instance.generalDescription(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + throw e.toString(); + } + return response; + } +} diff --git a/lib/sevices/passo/building/structural_material_services.dart b/lib/sevices/passo/building/structural_material_services.dart new file mode 100644 index 0000000..0da27f3 --- /dev/null +++ b/lib/sevices/passo/building/structural_material_services.dart @@ -0,0 +1,67 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/structural_materials_ii.dart'; +import 'package:unit2/model/passo/structureMaterial.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class StrucMaterialServices { + static final StrucMaterialServices _instance = StrucMaterialServices(); + static StrucMaterialServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future update(StructureMaterialsII data, id) async { + String path = Url.instance.structuralMaterials(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future fetch(id) async { + String path = Url.instance.structuralMaterials(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "bldgappr_details_id": id.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + print('StructureMaterialsII'); + print(response.body); + if (response.statusCode == 200) { + final jsonData = jsonDecode(response.body); + final dataList = jsonData['data'] as List; + final result = + StructureMaterials.fromJson(dataList[0] as Map); + + return result; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/class_components_services.dart b/lib/sevices/passo/class_components_services.dart new file mode 100644 index 0000000..8898ed4 --- /dev/null +++ b/lib/sevices/passo/class_components_services.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/class_components.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class ClassComponentService { + static final ClassComponentService _instance = ClassComponentService(); + static ClassComponentService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getClassComponents(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => ClassComponents.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_appraisal.dart b/lib/sevices/passo/land/land_appraisal.dart new file mode 100644 index 0000000..065e5ad --- /dev/null +++ b/lib/sevices/passo/land/land_appraisal.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../../utils/urls.dart'; + +class LandAppraisalServices { + static final LandAppraisalServices _instance = LandAppraisalServices(); + static LandAppraisalServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.getLandAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + print(result); + return result.map(((e) => LandAppr.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(LandAppr items) async { + String path = Url.instance.getLandAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: items.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future remove(id) async { + String path = Url.instance.getLandAppraisal(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id.toString(), + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: params); + print(id); + if (response.statusCode == 200) { + print(response.body); + return response; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_boundaries.dart b/lib/sevices/passo/land/land_boundaries.dart new file mode 100644 index 0000000..969d40c --- /dev/null +++ b/lib/sevices/passo/land/land_boundaries.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_property_boundaries.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandBoundariesService { + static final LandBoundariesService _instance = LandBoundariesService(); + static LandBoundariesService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getLandPropertyBoundaries(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandPropertyBoundaries.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future update(LandPropertyBoundaries data, id) async { + String path = Url.instance.getLandPropertyBoundaries(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + log(e.toString()); + } + return response; + } +} diff --git a/lib/sevices/passo/land/land_classification.dart b/lib/sevices/passo/land/land_classification.dart new file mode 100644 index 0000000..198b509 --- /dev/null +++ b/lib/sevices/passo/land/land_classification.dart @@ -0,0 +1,39 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/land_classification.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandClassificationService { + static final LandClassificationService _instance = + LandClassificationService(); + static LandClassificationService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getLandClassification(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandClassification.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_ext.dart b/lib/sevices/passo/land/land_ext.dart new file mode 100644 index 0000000..4d23162 --- /dev/null +++ b/lib/sevices/passo/land/land_ext.dart @@ -0,0 +1,136 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/land_ext.dart'; +import 'package:unit2/model/passo/property_assessment.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/property_assessment_edit.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandExtServices { + static final LandExtServices _instance = LandExtServices(); + static LandExtServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.getLandExt(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + print('Assessment'); + print(response.statusCode); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandExt.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(LandExt assessment) async { + Map statusResponse = {}; + String path = Url.instance.getLandExt(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: assessment.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future update(LandExt assessment, id) async { + String path = Url.instance.getLandExt(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, + body: assessment.toJson(), + headers: headers, + param: params); + } catch (e) { + log(e.toString()); + } + return response; + } + + // Future fetchEdit(tempID) async { + // http.Response response = await http.get(Uri.parse( + // '$baseUrl${Url.instance.getLandExt()}?bldgappr_details_id=$tempID')); + // print('Assessment'); + // print(response.body); + // if (response.statusCode == 200) { + // final jsonData = jsonDecode(response.body); + // final dataList = jsonData['data'] as List; + // final result = + // LandExtEdit.fromJson(dataList[0] as Map); + + // return result; + // } else { + // throw Exception(response.reasonPhrase); + // } + // } + + // Future addEdit(LandExtEdit assessment) async { + // http.Response? response; + // try { + // response = await http.post( + // Uri.parse("$baseUrl${Url.instance.getLandExt()}"), + // headers: { + // HttpHeaders.contentTypeHeader: "application/json", + // }, + // body: jsonEncode(assessment.toJson())); + // } catch (e) { + // log(e.toString()); + // } + // return response; + // } + + // Future updateEdit( + // LandExtEdit assessment, id) async { + // print(id); + // http.Response? response; + // try { + // response = await http.put(Uri.parse( + // // ignore: unnecessary_brace_in_string_interps + // "$baseUrl${Url.instance.getLandExt()}?bldgappr_details_id=${id}"), + // headers: { + // HttpHeaders.contentTypeHeader: "application/json", + // }, + // body: jsonEncode(assessment.toJson())); + // } catch (e) { + // log(e.toString()); + // } + // return response; + // } +} diff --git a/lib/sevices/passo/land/land_location.dart b/lib/sevices/passo/land/land_location.dart new file mode 100644 index 0000000..8a2fe5b --- /dev/null +++ b/lib/sevices/passo/land/land_location.dart @@ -0,0 +1,58 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/land_property_loc.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandLocationService { + static final LandLocationService _instance = LandLocationService(); + static LandLocationService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getLandPropertyLoc(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandPropertyLoc.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future update(LandPropertyLoc data, id) async { + String path = Url.instance.getLandPropertyLoc(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": id.toString(), + }; + http.Response? response; + try { + response = await Request.instance.putRequest( + path: path, body: data.toJson(), headers: headers, param: params); + } catch (e) { + log(e.toString()); + } + return response; + } +} diff --git a/lib/sevices/passo/land/land_other_improvements.dart b/lib/sevices/passo/land/land_other_improvements.dart new file mode 100644 index 0000000..d23652a --- /dev/null +++ b/lib/sevices/passo/land/land_other_improvements.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/model/passo/other_improvements.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../../utils/urls.dart'; + +class OtherImprovementServices { + static final OtherImprovementServices _instance = OtherImprovementServices(); + static OtherImprovementServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.getOtherImprovements(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": tempID, + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + print(result); + return result.map(((e) => OtherImprovements.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(OtherImprovements items) async { + String path = Url.instance.getOtherImprovements(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: items.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future remove(id) async { + String path = Url.instance.getOtherImprovements(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id, + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + print(id); + if (response.statusCode == 200) { + print(response.body); + return response; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_property_assessment.dart b/lib/sevices/passo/land/land_property_assessment.dart new file mode 100644 index 0000000..d8768bd --- /dev/null +++ b/lib/sevices/passo/land/land_property_assessment.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/additional_items.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/model/passo/land_property_assessment.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../../utils/urls.dart'; + +class LandPropertyAssessmentServices { + static final LandPropertyAssessmentServices _instance = + LandPropertyAssessmentServices(); + static LandPropertyAssessmentServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.getLandPropertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": tempID.toString(), + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + print(result); + return result.map(((e) => LandPropertyAssessment.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(LandPropertyAssessment items) async { + String path = Url.instance.getLandPropertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: items.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future remove(id) async { + String path = Url.instance.getLandPropertyAssessment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id.toString(), + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: params); + print(id); + if (response.statusCode == 200) { + print(response.body); + return response; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_property_owner.dart b/lib/sevices/passo/land/land_property_owner.dart new file mode 100644 index 0000000..83798ab --- /dev/null +++ b/lib/sevices/passo/land/land_property_owner.dart @@ -0,0 +1,55 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:unit2/model/passo/land_property_owner.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandServices { + static final LandServices _instance = LandServices(); + static LandServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getLandOwnerInfo(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandPropertyOwner.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(LandPropertyOwner land) async { + String path = Url.instance.getLandOwnerInfo(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: land.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } +} diff --git a/lib/sevices/passo/land/land_subclassification.dart b/lib/sevices/passo/land/land_subclassification.dart new file mode 100644 index 0000000..031c56e --- /dev/null +++ b/lib/sevices/passo/land/land_subclassification.dart @@ -0,0 +1,42 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/land_classification.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_subclassification.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandSubClassificationService { + static final LandSubClassificationService _instance = + LandSubClassificationService(); + static LandSubClassificationService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(cityCode, classCode) async { + String path = Url.instance.getLandSubClassification(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "city_code": cityCode.toString(), + "classification_id": classCode.toString() + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => LandSubClassification.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_trees_improvements.dart b/lib/sevices/passo/land/land_trees_improvements.dart new file mode 100644 index 0000000..29da425 --- /dev/null +++ b/lib/sevices/passo/land/land_trees_improvements.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/trees_improvements.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class LandTreesImprovementsServices { + static final LandTreesImprovementsServices _instance = + LandTreesImprovementsServices(); + static LandTreesImprovementsServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getTreesImprovements(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => TreesImprovements.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/land_value_adjustment.dart b/lib/sevices/passo/land/land_value_adjustment.dart new file mode 100644 index 0000000..8fda18f --- /dev/null +++ b/lib/sevices/passo/land/land_value_adjustment.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/land_appr.dart'; +import 'package:unit2/model/passo/land_value_adjustment.dart'; +import 'package:unit2/model/passo/other_improvements.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../../utils/urls.dart'; + +class ValueAdjustmentsServices { + static final ValueAdjustmentsServices _instance = ValueAdjustmentsServices(); + static ValueAdjustmentsServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch(tempID) async { + String path = Url.instance.getValueAdjustmentss(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "landappr_details_id": tempID, + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + print(result); + return result.map(((e) => ValueAdjustments.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } + + Future add(ValueAdjustments items) async { + String path = Url.instance.getValueAdjustmentss(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + http.Response? response; + try { + response = await Request.instance.postRequest( + param: {}, path: path, body: items.toJson(), headers: headers); + } catch (e) { + log(e.toString()); + } + return response; + } + + Future remove(id) async { + String path = Url.instance.getValueAdjustmentss(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map params = { + "id": id, + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + print(id); + if (response.statusCode == 200) { + print(response.body); + return response; + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/type_of_location.dart b/lib/sevices/passo/land/type_of_location.dart new file mode 100644 index 0000000..004e6d7 --- /dev/null +++ b/lib/sevices/passo/land/type_of_location.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/type_of_location.dart'; +import 'package:unit2/model/passo/type_of_road.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class TypeOfLocationServices { + static final TypeOfLocationServices _instance = TypeOfLocationServices(); + static TypeOfLocationServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getTypeOfLocation(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + print(response.body); + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => TypeOfLocation.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/land/type_of_road.dart b/lib/sevices/passo/land/type_of_road.dart new file mode 100644 index 0000000..51470ed --- /dev/null +++ b/lib/sevices/passo/land/type_of_road.dart @@ -0,0 +1,37 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/type_of_road.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class TypeOfRoadServices { + static final TypeOfRoadServices _instance = TypeOfRoadServices(); + static TypeOfRoadServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getTypeOfRoad(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + print(response.body); + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => TypeOfRoad.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/memoranda.dart b/lib/sevices/passo/memoranda.dart new file mode 100644 index 0000000..c29a6be --- /dev/null +++ b/lib/sevices/passo/memoranda.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/barangay.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/passo/memoranda.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class MemorandaServices { + static final MemorandaServices _instance = MemorandaServices(); + static MemorandaServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getMemoranda(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => Memoranda.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/municipality.dart b/lib/sevices/passo/municipality.dart new file mode 100644 index 0000000..2bb4850 --- /dev/null +++ b/lib/sevices/passo/municipality.dart @@ -0,0 +1,39 @@ +import 'dart:convert'; + +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/passo/city.dart'; +import 'package:unit2/model/passo/class_components.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class MunicipalityServices { + static final MunicipalityServices _instance = MunicipalityServices(); + static MunicipalityServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getMunicipality(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + print(response.body); + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => City.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/signatories_service.dart b/lib/sevices/passo/signatories_service.dart new file mode 100644 index 0000000..1d527f2 --- /dev/null +++ b/lib/sevices/passo/signatories_service.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +import 'package:unit2/model/passo/signatories.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class SignatoriesServices { + static final SignatoriesServices _instance = SignatoriesServices(); + static SignatoriesServices get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getSignatories(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + + print('Signatories'); + print(response.statusCode); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => Signatories.fromJson(e))).toList(); + } else { + print(response.reasonPhrase); + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/passo/unit_construct_services.dart b/lib/sevices/passo/unit_construct_services.dart new file mode 100644 index 0000000..39794e8 --- /dev/null +++ b/lib/sevices/passo/unit_construct_services.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:unit2/model/passo/unit_construct.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +class UnitConstructService { + static final UnitConstructService _instance = UnitConstructService(); + static UnitConstructService get instance => _instance; + + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> fetch() async { + String path = Url.instance.getUnitConstruct(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + final List result = jsonDecode(response.body)['data']; + + return result.map(((e) => UnitConstruct.fromJson(e))).toList(); + } else { + throw Exception(response.reasonPhrase); + } + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/profile/address_service.dart b/lib/sevices/profile/address_service.dart new file mode 100644 index 0000000..cded751 --- /dev/null +++ b/lib/sevices/profile/address_service.dart @@ -0,0 +1,161 @@ +import 'dart:convert'; + +import '../../model/profile/basic_information/adress.dart'; +import '../../utils/request.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class AddressService { + static final AddressService _instance = AddressService(); + static AddressService get instance => _instance; +////add + Future> add( + {required AddressClass address, + required int categoryId, + required String? details, + required int? blockNumber, + required int? lotNumber, + required String token, + required int profileId}) async { + Map _response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addressPath()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + _response = data['response']; + _response.addAll({'data': data['response']['data']}); + _response.addAll( + {'message': data['response']['message']}, + ); + _response.addAll( + {'success': true}, + ); + } else { + Map data = jsonDecode(response.body); + String message = data['response']['details']; + _response.addAll({'message': message}); + _response.addAll( + {'success': false}, + ); + } + return _response; + } catch (e) { + throw e.toString(); + } + } + + ////delete + Future delete( + {required int addressId, + required int profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.addressPath()}$profileId/"; + Map body = {"id": addressId}; + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success!; + } + + ////update + Future> update( + {required AddressClass address, + required int categoryId, + required String? details, + required int? blockNumber, + required int? lotNumber, + required String token, + required int profileId}) async { + Map _response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addressPath()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + }; + try { + http.Response response = await http.patch( + Uri.parse( + 'https://${Url.instance.host()}${Url.instance.addressPath()}$profileId/'), + headers: headers, + body: jsonEncode({ + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + })); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + _response = data['response']; + _response.addAll({'data': data['response']['data']}); + _response.addAll( + {'message': data['response']['message']}, + ); + _response.addAll( + {'success': true}, + ); + } else { + Map data = jsonDecode(response.body); + String message = data['response']['details']; + _response.addAll({'message': message}); + _response.addAll( + {'success': false}, + ); + } + + return _response; + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/profile/citizenship_services.dart b/lib/sevices/profile/citizenship_services.dart new file mode 100644 index 0000000..338bc74 --- /dev/null +++ b/lib/sevices/profile/citizenship_services.dart @@ -0,0 +1,107 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/basic_information/citizenship.dart'; + +import '../../utils/request.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class CitizenshipServices { + static final CitizenshipServices _instance = CitizenshipServices(); + static CitizenshipServices get instance => _instance; + + Future> add( + {required int profileId, + required String token, + required int countryId, + required bool naturalBorn}) async { + String path = "${Url.instance.citizenship()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map responseStatus = {}; + Map body = { + "country_id": countryId, + "natural_born": naturalBorn, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + responseStatus = data; + } else { + responseStatus.addAll({'success': false}); + } + return responseStatus; + } catch (e) { + throw e.toString(); + } + } + + Future> update( + {required int profileId, + required String token, + required Citizenship citizenship, + required int oldCountry}) async { + String path = "${Url.instance.citizenship()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "country_id": citizenship.country!.id, + "natural_born": citizenship.naturalBorn, + "_oldCountryId": oldCountry + }; + Map responseStatus = {}; + try { + http.Response response = await Request.instance + .putRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + responseStatus = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + responseStatus.addAll({'success': false}); + responseStatus.addAll({'message': message}); + } + return responseStatus; + } catch (e) { + throw e.toString(); + } + } + + Future delete( + {required int profileId, + required String token, + required countryId, + required bool naturalBorn}) async { + Map params = {"force_mode": "true"}; + String authtoken = "Token $token"; + String path = "${Url.instance.citizenship()}$profileId/"; + bool success = false; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = {"country_id": countryId, "natural_born": naturalBorn}; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success; + } +} diff --git a/lib/sevices/profile/contact_services.dart b/lib/sevices/profile/contact_services.dart new file mode 100644 index 0000000..f3fd302 --- /dev/null +++ b/lib/sevices/profile/contact_services.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; + +class ContactService { + static final ContactService _instance = ContactService(); + static ContactService get instance => _instance; + + Future> getServiceProvider( + {required int serviceTypeId}) async { + String path = Url.instance.getCommunicationProvider(); + Map params = {"service_type__id": serviceTypeId.toString()}; + List serviceProviders = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var element in data['data']) { + CommService commService = CommService.fromJson(element); + serviceProviders.add(commService); + } + } + } + } catch (e) { + throw e.toString(); + } + return serviceProviders; + } + +//// update + Future> update( + {required int profileId, + required String token, + required ContactInfo contactInfo}) async { + String path = "${Url.instance.contactPath()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "personid": profileId, + "contactinfoid": contactInfo.id, + "_numbermail": contactInfo.numbermail, + "_active": contactInfo.active, + "_primary": contactInfo.primary, + "_commServiceId": contactInfo.commService!.id + }; + Map responseStatus = {}; + try { + http.Response response = await Request.instance + .putRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + responseStatus = data; + } else { + responseStatus.addAll({'success': false}); + } + return responseStatus; + } catch (e) { + throw e.toString(); + } + } + + //// add + Future> add( + {required int profileId, + required String token, + required ContactInfo contactInfo}) async { + String path = "${Url.instance.contactPath()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map responseStatus = {}; + Map body = { + "personid": profileId, + "_numbermail": contactInfo.numbermail, + "_active": contactInfo.active, + "_primary": contactInfo.primary, + "_commServiceId": contactInfo.commService!.id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + responseStatus = data; + } else { + responseStatus.addAll({'success': false}); + } + return responseStatus; + } catch (e) { + throw e.toString(); + } + } + +////delete + Future deleteContact( + {required int profileId, + required String token, + required ContactInfo contactInfo}) async { + String path = "${Url.instance.deleteContact()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'mode': 'same-origin', + 'include': 'credentials', + 'Authorization': authToken + }; + bool success = false; + Map params = {"force_mode": "true"}; + Map body = { + "personid": profileId, + "contactinfoid": contactInfo.id, + "_numbermail": contactInfo.numbermail, + "_active": contactInfo.active, + "_primary": contactInfo.primary, + "_commServiceId": contactInfo.commService!.id + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/profile/education_services.dart b/lib/sevices/profile/education_services.dart new file mode 100644 index 0000000..05a86f5 --- /dev/null +++ b/lib/sevices/profile/education_services.dart @@ -0,0 +1,238 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/educational_background.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class EducationService { + static final EducationService _instance = EducationService(); + static EducationService get instace => _instance; +////get educational background + Future> getEducationalBackground( + int profileId, String token) async { + List educationalBackgrounds = []; + String authToken = "Token $token"; + String path = "${Url.instance.educationalBackground()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var education) { + EducationalBackground educationalBackground = + EducationalBackground.fromJson(education); + educationalBackgrounds.add(educationalBackground); + }); + } + } + } catch (e) { + throw e.toString(); + } + + return educationalBackgrounds; + } + + ////Add + Future> add( + {required EducationalBackground educationalBackground, + required String token, + required int profileId, + required List honors}) async { + String authtoken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + String path = '${Url.instance.educationalBackground()}$profileId/'; + Map statusResponse = {}; + Map body = { + "_level": educationalBackground.education!.level, + "_schoolId": educationalBackground.education?.school?.id, + "_schoolName": educationalBackground.education!.school!.name, + "_programId": educationalBackground.education?.course?.id, + "_programName": educationalBackground.education?.course?.program, + "_course": null, + "period_from": educationalBackground.periodFrom.toString(), + "period_to": educationalBackground.periodTo.toString(), + "units_earned": educationalBackground.unitsEarned, + "year_graduated": educationalBackground.yearGraduated, + "honors": honors.isEmpty ? [] : honors, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, param: {}, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////Edit + Future> edit( + {required EducationalBackground educationalBackground, + required String token, + required int profileId, + required List honors}) async { + String authtoken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + String path = '${Url.instance.educationalBackground()}$profileId/'; + Map statusResponse = {}; + Map body = { + "id": educationalBackground.id, + "_level": educationalBackground.education!.level, + "_schoolId": educationalBackground.education?.school?.id, + "_schoolName": educationalBackground.education!.school!.name, + "_programId": educationalBackground.education?.course?.id, + "_programName": educationalBackground.education?.course?.program, + "_course": null, + "period_from": educationalBackground.periodFrom.toString(), + "period_to": educationalBackground.periodTo.toString(), + "units_earned": educationalBackground.unitsEarned, + "year_graduated": educationalBackground.yearGraduated, + "honors": honors.isEmpty ? [] : honors, + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, param: {}, body: body, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + //// delete + Future delete( + {required int profileId, + required String token, + required EducationalBackground educationalBackground}) async { + String authToken = "Token $token"; + String path = "${Url.instance.educationalBackground()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + bool? success; + Map params = {"force_mode": "true"}; + Map body = { + "id": educationalBackground.id, + "_level": educationalBackground.education!.level, + "_schoolId": educationalBackground.education!.school!.id, + "education_id": educationalBackground.education!.id, + "period_from": educationalBackground.periodFrom, + "period_to": educationalBackground.periodTo, + "units_earned": educationalBackground.unitsEarned, + "year_graduated": educationalBackground.yearGraduated, + "honors": educationalBackground.honors + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw e.toString(); + } + return success!; + } + +//// get schools + Future> getSchools() async { + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + List schools = []; + String path = Url.instance.getSchools(); + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((school) { + School newSchool = School.fromJson(school); + schools.add(newSchool); + }); + } + } + } catch (e) { + throw e.toString(); + } + return schools; + } + + Future> getPrograms() async { + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + List programs = []; + String path = Url.instance.getPrograms(); + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((course) { + Course newCourse = Course.fromJson(course); + programs.add(newCourse); + }); + } + } + } catch (e) { + throw e.toString(); + } + return programs; + } + +////get honors + Future> getHonors() async { + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + List honors = []; + String path = Url.instance.getHonors(); + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((honor) { + Honor newHonor = Honor.fromJson(honor); + honors.add(newHonor); + }); + } + } + } catch (e) { + throw e.toString(); + } + return honors; + } +} diff --git a/lib/sevices/profile/eligibility_services.dart b/lib/sevices/profile/eligibility_services.dart new file mode 100644 index 0000000..d9a94ea --- /dev/null +++ b/lib/sevices/profile/eligibility_services.dart @@ -0,0 +1,203 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/attachment.dart'; +import 'package:unit2/model/profile/eligibility.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; + +class EligibilityService { + static final EligibilityService _instance = EligibilityService(); + static EligibilityService get instance => _instance; + + Future> getEligibilities( + int profileId, String token) async { + List eligibilities = []; + String authToken = "Token $token"; + String path = "${Url.instance.getEligibilities()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var cert) { + EligibityCert eligibility = EligibityCert.fromJson(cert); + eligibilities.add(eligibility); + }); + } + } + } catch (e) { + throw e.toString(); + } + return eligibilities; + } + + Future delete( + {required int eligibilityId, + required int profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.deleteEligibility()}$profileId/"; + Map body = {"eligibility_id": eligibilityId}; + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success!; + } + + Future> add( + {required EligibityCert eligibityCert, + required String token, + required int profileId}) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addEligibility()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + + Map body = { + 'eligibility_id': eligibityCert.eligibility!.id, + 'license_number': eligibityCert.licenseNumber, + 'exam_date': eligibityCert.examDate?.toString(), + 'validity_date': eligibityCert.validityDate?.toString(), + 'rating': eligibityCert.rating, + '_citymunCode': eligibityCert.examAddress?.cityMunicipality?.code, + '_countryId': eligibityCert.examAddress?.country!.id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + _response = data; + } else { + _response.addAll({'success': false}); + } + + return _response; + } catch (e) { + throw e.toString(); + } + } + + Future> update( + {required EligibityCert eligibityCert, + required String token, + required int profileId, + required int oldEligibility}) async { + Map? response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addEligibility()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + + Map body = { + 'eligibility_id': eligibityCert.eligibility!.id, + 'license_number': eligibityCert.licenseNumber, + 'exam_date': eligibityCert.examDate?.toString(), + 'validity_date': eligibityCert.validityDate?.toString(), + 'rating': eligibityCert.rating, + '_citymunCode': eligibityCert.examAddress?.cityMunicipality?.code, + '_countryId': eligibityCert.examAddress?.country!.id, + '_oldEligibilityId': oldEligibility + }; + try { + http.Response res = await Request.instance + .putRequest(path: path, body: body, headers: headers, param: {}); + if (res.statusCode == 200) { + Map data = jsonDecode(res.body); + response = data; + } else { + response.addAll({'success': false}); + } + + return response; + } catch (e) { + throw e.toString(); + } + } + + + + Future deleteAttachment( + {required Attachment attachment, + required int moduleId, + required String profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.attachments()}$profileId/"; + Map? body; + try{ + body = { + "attachment_module": moduleId, + attachment: [ + { + "id": attachment.id, + "created_at": attachment.createdAt, + "source": attachment.source, + "filename": attachment.filename, + "category": { + "id": attachment.category?.id, + "subclass": { + "id": attachment.category?.subclass?.id, + "name": attachment.category?.subclass?.name, + "attachment_class": { + "id": attachment.category?.subclass?.attachmentClass?.id, + "name": attachment.category?.subclass?.attachmentClass?.name + } + }, + "description": attachment.category?.description + } + } + ] + }; + }catch(e){ + print("body error"+e.toString()); + } + + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + // try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + // } catch (e) { + // throw (e.toString()); + // } + return success!; + } +} diff --git a/lib/sevices/profile/family_services.dart b/lib/sevices/profile/family_services.dart new file mode 100644 index 0000000..276607a --- /dev/null +++ b/lib/sevices/profile/family_services.dart @@ -0,0 +1,207 @@ +import 'dart:convert'; + +import 'package:unit2/utils/request.dart'; + +import '../../model/profile/family_backround.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class FamilyService { + static final FamilyService _instance = FamilyService(); + static FamilyService get instance => _instance; + + Future> getFamilies( + int profileId, String token) async { + List families = []; + String authToken = "Token $token"; + String path = "${Url.instance.getFamilies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var family) { + FamilyBackground familyBackground = + FamilyBackground.fromJson(family); + families.add(familyBackground); + }); + } + } + } catch (e) { + throw e.toString(); + } + return families; + } + + Future> add( + {required int profileId, + required String token, + required int relationshipId, + required FamilyBackground? family}) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = "${Url.instance.getFamilies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "relation_type_id": relationshipId, + "company_address": family?.companyAddress, + "company_contact_number": family?.companyContactNumber, + "first_name": family!.relatedPerson!.firstName, + "middle_name": family.relatedPerson!.middleName, + "last_name": family.relatedPerson!.lastName, + "name_extension": family.relatedPerson?.nameExtension, + "birthdate": family.relatedPerson!.birthdate.toString(), + "sex": family.relatedPerson!.sex, + "blood_type": family.relatedPerson?.bloodType, + "civil_status": family.relatedPerson?.civilStatus, + "height": family.relatedPerson?.heightM, + "weight": family.relatedPerson?.weightKg, + "position_id": family.position?.id, + "agency_id": family.company?.id, + "_positionName": family.position?.title, + "_agencyName": family.company?.name, + "_agencyCatId": family.company?.category?.id, + "_privateEntity": family.company?.privateEntity, + "maidenMiddleName": family.relatedPerson?.maidenName?.middleName, + "maidenLastName": family.relatedPerson?.maidenName?.lastName, + "gender": family.relatedPerson!.gender, + "deceased": family.relatedPerson!.deceased, + }; + try { + http.Response response = await Request.instance + .postRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + _response = data; + } else { + _response.addAll({'success': false}); + } + } catch (e) { + throw (e.toString()); + } + return _response; + } +//// Add Emergency + Future> addEmergency( + {required int profileId, + required String token, + required int relatedPersonId, + required String? numberMail, + required int? contactInfoId, + required String requestType, + }) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = Url.instance.addEmergency(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { "personid": profileId, "related_personid": relatedPersonId, "request_type": requestType, "number_mail": numberMail, "contactinfoid": contactInfoId }; + try { + http.Response response = await Request.instance + .postRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + _response = data; + print(_response.toString()); + } else { + _response.addAll({'success': false}); + } + } catch (e) { + throw (e.toString()); + } + return _response; + } + ////Update + Future> update( + {required int profileId, + required String token, + required int relationshipId, + required FamilyBackground family}) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = "${Url.instance.getFamilies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "relation_type_id": relationshipId, + "related_person_id": family.relatedPerson!.id, + "company_address": family.companyAddress, + "company_contact_number": family.companyContactNumber, + "first_name": family.relatedPerson!.firstName, + "middle_name": family.relatedPerson!.middleName!.isEmpty?null:family.relatedPerson!.middleName!, + "last_name": family.relatedPerson!.lastName, + "name_extension": family.relatedPerson?.nameExtension, + "birthdate": family.relatedPerson!.birthdate.toString(), + "sex": family.relatedPerson!.sex, + "blood_type": family.relatedPerson?.bloodType, + "civil_status": family.relatedPerson?.civilStatus, + "height": family.relatedPerson!.heightM, + "weight": family.relatedPerson!.weightKg, + "position_id": family.position?.id, + "agency_id": family.company?.id, + "_positionName": family.position?.title, + "_agencyName": family.company?.name, + "_agencyCatId": family.company?.category?.id, + "_privateEntity": family.company?.privateEntity, + "maidenMiddleName": family.relatedPerson?.maidenName?.middleName, + "maidenLastName": family.relatedPerson?.maidenName?.lastName, + "gender": family.relatedPerson!.gender, + "deceased": family.relatedPerson!.deceased, + }; + try { + http.Response response = await Request.instance + .putRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + _response = data; + } else { + _response.addAll({'success': false}); + } + } catch (e) { + throw (e.toString()); + } + return _response; + } +////delete + Future delete( + {required int personRelatedId, + required int profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.getFamilies()}$profileId/"; + Map body = {"related_person_id": personRelatedId}; + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success!; + } + + +} diff --git a/lib/sevices/profile/identification_services.dart b/lib/sevices/profile/identification_services.dart new file mode 100644 index 0000000..36650c4 --- /dev/null +++ b/lib/sevices/profile/identification_services.dart @@ -0,0 +1,125 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/basic_information/identification_information.dart'; +import 'package:http/http.dart' as http; +import '../../utils/request.dart'; +import '../../utils/urls.dart'; + +class IdentificationServices { + static final IdentificationServices _instance = IdentificationServices(); + static IdentificationServices get instance => _instance; + + Future> add( + {required Identification identification, + required int profileId, + required String token}) async { + Map? responseData = {}; + String authToken = "Token $token"; + String path = "${Url.instance.identifications()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "agency_id": identification.agency!.id, + "identification_number": identification.identificationNumber, + "date_issued": identification.dateIssued == null + ? null + : identification.dateIssued.toString(), + "expiration_date": identification.expirationDate == null + ? null + : identification.expirationDate.toString(), + "as_pdf_reference": identification.asPdfReference, + "_agencyName": identification.agency!.name, + "_agencyCatId": identification.agency!.category!.id, + "_privateEntity": identification.agency!.privateEntity, + "_citymunCode": identification.issuedAt?.cityMunicipality?.code, + "_countryId": identification.issuedAt!.country!.id + }; + try { + http.Response response = await Request.instance + .postRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + responseData = data; + } else { + responseData.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return responseData; + } + + ////delete + Future delete( + {required int identificationId, + required String token, + required int profileId}) async { + bool success = false; + String authToken = "Token $token"; + String path = "${Url.instance.identifications()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map params = {"force_mode": "true"}; + Map body = { + "id": identificationId, + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } + } catch (e) { + throw (e.toString()); + } + return success; + } + + Future> update( + {required Identification identification, + required int profileId, + required String token}) async { + Map? responseData = {}; + String authToken = "Token $token"; + String path = "${Url.instance.identifications()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "id":identification.id, + "agency_id": identification.agency!.id, + "identification_number": identification.identificationNumber, + "date_issued": identification.dateIssued == null + ? null + : identification.dateIssued.toString(), + "expiration_date": identification.expirationDate == null + ? null + : identification.expirationDate.toString(), + "as_pdf_reference": identification.asPdfReference, + "_agencyName": identification.agency!.name, + "_agencyCatId": identification.agency!.category!.id, + "_privateEntity": identification.agency!.privateEntity, + "_citymunCode":identification.issuedAt!.country!.id == 175? identification.issuedAt?.cityMunicipality?.code:null, + "_countryId": identification.issuedAt!.country!.id + }; + try { + http.Response response = await Request.instance + .putRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + responseData = data; + } else { + responseData.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return responseData; + } +} diff --git a/lib/sevices/profile/learningDevelopment_service.dart b/lib/sevices/profile/learningDevelopment_service.dart new file mode 100644 index 0000000..c8775d3 --- /dev/null +++ b/lib/sevices/profile/learningDevelopment_service.dart @@ -0,0 +1,281 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/text_container.dart'; + +import '../../model/profile/learning_development.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class LearningDevelopmentServices { + static final LearningDevelopmentServices _instance = + LearningDevelopmentServices(); + static LearningDevelopmentServices get instance => _instance; + + Future> getLearningDevelopments( + int profileId, String token) async { + List learningsAndDevelopments = []; + String authToken = "Token $token"; + String path = "${Url.instance.learningAndDevelopments()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var learnings) { + LearningDevelopement learningDevelopement = + LearningDevelopement.fromJson(learnings); + learningsAndDevelopments.add(learningDevelopement); + }); + } + } + } catch (e) { + throw e.toString(); + } + return learningsAndDevelopments; + } + + ////Add + Future> add( + {required LearningDevelopement learningDevelopement, + required String token, + required int profileId}) async { + String authtoken = "Token $token"; + String path = '${Url.instance.learningAndDevelopments()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map statusResponse = {}; + try { + Map body = { + "training_conduct_id": learningDevelopement.conductedTraining?.id, + "total_hours_attended": + learningDevelopement.totalHoursAttended.toString(), + "sponsor_id": learningDevelopement.sponsoredBy?.id, + "sponsor_name": learningDevelopement.sponsoredBy?.name, + "sponsor_category": learningDevelopement.sponsoredBy?.category?.id, + "sponsor_private": learningDevelopement.sponsoredBy?.privateEntity, + "training_id": learningDevelopement.conductedTraining?.title?.id, + "training_title": learningDevelopement.conductedTraining?.title?.title, + "topic_id": learningDevelopement.conductedTraining?.topic?.id, + "topic_title": learningDevelopement.conductedTraining?.topic?.title, + "conductor_id": learningDevelopement.conductedTraining?.conductedBy?.id, + "conductor_name": + learningDevelopement.conductedTraining?.conductedBy?.name, + "conductor_category": + learningDevelopement.conductedTraining?.conductedBy?.category?.id!, + "conductor_private": + learningDevelopement.conductedTraining?.conductedBy?.privateEntity, + "venue_city_municipality": learningDevelopement + .conductedTraining?.venue?.cityMunicipality?.code, + "venue_barangay": + learningDevelopement.conductedTraining?.venue?.barangay?.code, + "learning_development_type": + learningDevelopement.conductedTraining?.learningDevelopmentType?.id, + "from_date": + learningDevelopement.conductedTraining?.fromDate?.toString(), + "to_date": learningDevelopement.conductedTraining?.toDate?.toString(), + "total_hours": learningDevelopement.conductedTraining?.totalHours, + "locked": false, + "venue_country": + learningDevelopement.conductedTraining!.venue!.country!.id + }; + http.Response response = await Request.instance + .postRequest(path: path, param: {}, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + return statusResponse; + } catch (e) { + throw e.toString(); + } + } + + ////Add + Future> update( + {required LearningDevelopement learningDevelopement, + required String token, + required int profileId}) async { + String authtoken = "Token $token"; + String path = '${Url.instance.learningAndDevelopments()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map statusResponse = {}; + try { + Map body = { + "training_conduct_id": learningDevelopement.conductedTraining?.id, + "total_hours_attended": + learningDevelopement.totalHoursAttended.toString(), + "sponsor_id": learningDevelopement.sponsoredBy?.id, + "sponsor_name": learningDevelopement.sponsoredBy?.name, + "sponsor_category": learningDevelopement.sponsoredBy?.category?.id, + "sponsor_private": learningDevelopement.sponsoredBy?.privateEntity, + "training_id": learningDevelopement.conductedTraining?.title?.id, + "training_title": learningDevelopement.conductedTraining?.title?.title, + "topic_id": learningDevelopement.conductedTraining?.topic?.id, + "topic_title": learningDevelopement.conductedTraining?.topic?.title, + "conductor_id": learningDevelopement.conductedTraining?.conductedBy?.id, + "conductor_name": + learningDevelopement.conductedTraining?.conductedBy?.name, + "conductor_category": + learningDevelopement.conductedTraining?.conductedBy?.category?.id!, + "conductor_private": + learningDevelopement.conductedTraining?.conductedBy?.privateEntity, + "venue_city_municipality": learningDevelopement + .conductedTraining?.venue?.cityMunicipality?.code, + "venue_barangay": + learningDevelopement.conductedTraining?.venue?.barangay?.code, + "learning_development_type": + learningDevelopement.conductedTraining?.learningDevelopmentType?.id, + "from_date": + learningDevelopement.conductedTraining?.fromDate?.toString(), + "to_date": learningDevelopement.conductedTraining?.toDate?.toString(), + "total_hours": learningDevelopement.conductedTraining?.totalHours, + "locked": learningDevelopement.conductedTraining?.locked, + "venue_country": + learningDevelopement.conductedTraining!.venue!.country!.id + }; + http.Response response = await Request.instance + .putRequest(path: path, param: {}, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + return statusResponse; + } catch (e) { + throw e.toString(); + } + } + + ////Delete + Future delete( + {required int profileId, + required String token, + required int? sponsorId, + required double totalHours, + required int trainingId}) async { + bool? success; + Map params = {"force_mode": "true"}; + String authToken = "Token $token"; + String path = '${Url.instance.learningAndDevelopments()}$profileId/'; + Map body = { + "sponsor_id": sponsorId, + "total_hours_attended": totalHours, + "training_conduct_id": trainingId + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw e.toString(); + } + return success!; + } + + Future> getConductedTrainings( + {required String key, required int page}) async { + List trainings = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + Map params = { + "title__title___ilike": key, + "page": page.toString() + }; + + String path = Url.instance.conductedTrainings(); + try { + http.Response response = await Request.instance + .getRequest(path: path, param: params, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var element) { + ConductedTraining training = ConductedTraining.fromJson(element); + trainings.add(training); + }); + } + } + } catch (e) { + throw e.toString(); + } + return trainings; + } + + Future> getLearningDevelopmentType() async { + List types = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + String path = Url.instance.learningAndDevelopmentType(); + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var element) { + LearningDevelopmentType type = + LearningDevelopmentType.fromJson(element); + types.add(type); + }); + } + } + } catch (e) { + throw e.toString(); + } + return types; + } + + Future> getTrainingTopics() async { + List topics = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + String path = Url.instance.learningAndDevelopmentTopics(); + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var element) { + LearningDevelopmentType type = + LearningDevelopmentType.fromJson(element); + topics.add(type); + }); + } + } + } catch (e) { + throw e.toString(); + } + return topics; + } +} diff --git a/lib/sevices/profile/non_academic_services.dart b/lib/sevices/profile/non_academic_services.dart new file mode 100644 index 0000000..fb08bf8 --- /dev/null +++ b/lib/sevices/profile/non_academic_services.dart @@ -0,0 +1,143 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:unit2/bloc/profile/other_information/non_academic_recognition.dart/non_academic_recognition_bloc.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../model/profile/other_information/non_acedimic_recognition.dart'; +import '../../utils/urls.dart'; + +class NonAcademicRecognitionServices { + static final NonAcademicRecognitionServices _instance = + NonAcademicRecognitionServices(); + static NonAcademicRecognitionServices get instance => _instance; +////GET + Future> getNonAcademicRecognition( + int profileId, String token) async { + List nonAcademicRecognitions = []; + String authToken = "Token $token"; + String path = "${Url.instance.getNonAcademicRecognition()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var recognition) { + NonAcademicRecognition nonAcademicRecognition = + NonAcademicRecognition.fromJson(recognition); + nonAcademicRecognitions.add(nonAcademicRecognition); + }); + } + } + } catch (e) { + throw e.toString(); + } + return nonAcademicRecognitions; + } + +////ADD + Future> add( + {required String token, + required int profileId, + required NonAcademicRecognition nonAcademicRecognition}) async { + String authToken = "Token $token"; + String path = "${Url.instance.getNonAcademicRecognition()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "title": nonAcademicRecognition.title, + "presenter_id": nonAcademicRecognition.presenter?.id, + "_presenterName": nonAcademicRecognition.presenter!.name, + "_presenterCatId": nonAcademicRecognition.presenter!.category!.id, + "_privateEntity": nonAcademicRecognition.presenter!.privateEntity, + }; + + Map statusResponse = {}; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, param: {}, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({"success": false}); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////UPDATE + Future> update( + {required NonAcademicRecognition nonAcademicRecognition, + required int profileId, + required String token}) async { + String authToken = "Token $token"; + String path = "${Url.instance.getNonAcademicRecognition()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map statusResponse = {}; + Map body = { + "id": nonAcademicRecognition.id, + "title": nonAcademicRecognition.title, + "presenter_id": nonAcademicRecognition.presenter?.id, + "_presenterName": nonAcademicRecognition.presenter!.name, + "_presenterCatId": nonAcademicRecognition.presenter!.category!.id, + "_privateEntity": nonAcademicRecognition.presenter!.privateEntity + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + +////DELETE + Future delete( + {required String title, + required int id, + required String token, + required int profileId}) async { + String authToken = "Token $token"; + Map params = {"force_mode": "true"}; + String path = "${Url.instance.getNonAcademicRecognition()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + bool success = false; + Map body = { + "id": id, + "title": title, + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/profile/orgmembership_services.dart b/lib/sevices/profile/orgmembership_services.dart new file mode 100644 index 0000000..424646e --- /dev/null +++ b/lib/sevices/profile/orgmembership_services.dart @@ -0,0 +1,95 @@ +import 'dart:convert'; + +import 'package:unit2/utils/request.dart'; + +import '../../model/profile/other_information/organization_memberships.dart'; +import 'package:http/http.dart' as http; + +import '../../model/utils/agency.dart'; +import '../../utils/urls.dart'; + +class OrganizationMembershipServices { + static final OrganizationMembershipServices _instance = + OrganizationMembershipServices(); + static OrganizationMembershipServices get instance => _instance; + + Future> getOrgMemberships( + int profileId, String token) async { + List orgMemberships = []; + String authToken = "Token $token"; + String path = "${Url.instance.getOrgMemberShips()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var org) { + OrganizationMembership organizationMembership = + OrganizationMembership.fromJson(org); + orgMemberships.add(organizationMembership); + }); + } + } + } catch (e) { + throw e.toString(); + } + return orgMemberships; + } + Future>add({required Agency? agency,required String token, required String profileId})async{ + String authToken = "Token $token"; + String path = "${Url.instance.getOrgMemberShips()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map statusResponse = {}; + Map body = { + "agency_id": agency?.id, + "_agencyName": agency!.name, + "_agencyCatId": agency.category!.id, + "_privateEntity": agency.privateEntity + }; + try{ + http.Response response = await Request.instance.postRequest(path: path,body: body,headers: headers,param: {}); + if(response.statusCode == 201){ + Map data = jsonDecode(response.body); + statusResponse = data; + }else{ + statusResponse.addAll({"success":false}); + } + }catch(e){ + throw e.toString(); + } + return statusResponse; + + } + + Future delete({required Agency agency, required int profileId, required String token})async{ + bool success = false; + Map params = {"force_mode": "true"}; + String authToken = "Token $token"; + String path = "${Url.instance.getOrgMemberShips()}$profileId/"; + Map body ={ + "agency_id": agency.id + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try{ + http.Response response = await Request.instance.deleteRequest(path: path, headers: headers, body: body, param: params); + if(response.statusCode == 200){ + Map data = jsonDecode(response.body); + success = data["success"]; + } + }catch(e){ + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/profile/profile_other_info.dart b/lib/sevices/profile/profile_other_info.dart new file mode 100644 index 0000000..8945835 --- /dev/null +++ b/lib/sevices/profile/profile_other_info.dart @@ -0,0 +1,137 @@ +import 'dart:convert'; + +import 'package:unit2/screens/profile/components/basic_information/profile_other_info.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; + +import '../../utils/request.dart'; +class ProfileOtherInfoServices{ + static final ProfileOtherInfoServices _instance = ProfileOtherInfoServices(); + + static ProfileOtherInfoServices get instace => _instance; + + Future>getReligions({String? token})async{ + String path = Url.instance.getReligions(); + List religions = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var e) { + religions.add(ProfileOtherInfo.fromJson(e)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return religions; + } + Future>getEthnicity({String? token})async{ + String path = Url.instance.getEthnicity(); + List ethnicity = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var e) { + ethnicity.add(ProfileOtherInfo.fromJson(e)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return ethnicity; + } + + Future>getDisability({required token})async{ + String path = Url.instance.getDisability(); + List disabilities = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var e) { + disabilities.add(ProfileOtherInfo.fromJson(e)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return disabilities; + } + Future>getGenders({required token})async{ + String path = Url.instance.getGenders(); + List genders = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var e) { + genders.add(ProfileOtherInfo.fromJson(e)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return genders; + } + + Future>getIndigency({required String? token})async{ + String path = Url.instance.getIndigency(); + List indigencies = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var e) { + indigencies.add(ProfileOtherInfo.fromJson(e)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return indigencies; + } + + +} \ No newline at end of file diff --git a/lib/sevices/profile/profile_service.dart b/lib/sevices/profile/profile_service.dart new file mode 100644 index 0000000..af057b1 --- /dev/null +++ b/lib/sevices/profile/profile_service.dart @@ -0,0 +1,140 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/profile/basic_info.dart'; +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/model/profile/basic_information/citizenship.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/model/profile/basic_information/identification_information.dart'; +import 'package:unit2/model/profile/profileInfomation.dart'; +import 'package:unit2/utils/urls.dart'; +import '../../model/profile/basic_information/primary-information.dart'; +import '../../utils/request.dart'; + +class ProfileService { + static final ProfileService _instance = ProfileService(); + static ProfileService get instance => _instance; + + Future getProfile(String token, int id) async { + String url = Url.instance.profileInformation(); + String path = url + id.toString(); + ProfileInformation? profileInformation0; + + List addresses = []; + List identificationInformation = []; + List contactInformation = []; + List citizenships = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': "Token $token" + }; + Map param = {"basic": "true"}; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: param, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + + // get all contacts + if (data['data']['basic_information']['contact_information'] != null) { + data['data']['basic_information']['contact_information'] + .forEach((var contact) { + ContactInfo contactInfo = + ContactInfo.fromJson(contact['contact_info']); + contactInformation.add(contactInfo); + }); + } + + // get all addresses + if (data['data']['basic_information']['addresses'] != null) { + data['data']['basic_information']['addresses'].forEach((var address) { + MainAdress mainAdress = MainAdress.fromJson(address); + addresses.add(mainAdress); + }); + } + + // get all identifications + if (data['data']['basic_information']['identification_records'] != + null) { + data['data']['basic_information']['identification_records']! + .forEach((var identity) { + Identification identification = Identification.fromJson(identity); + identificationInformation.add(identification); + }); + } + if(data['data']['basic_information']['citizenships'] != null){ + data['data']['basic_information']['citizenships']! + .forEach((var citizenship) { + Citizenship newCitizenShip = Citizenship.fromJson(citizenship); + citizenships.add(newCitizenShip); + }); + } + + BasicInfo basicInfo = BasicInfo( + contactInformation: contactInformation, + identifications: identificationInformation, + citizenships: citizenships, + addresses: addresses); + + ProfileInformation profileInformation = ProfileInformation( + basicInfo: basicInfo, + ); + profileInformation0 = profileInformation; + } + } catch (e) { + throw (e.toString()); + } + return profileInformation0; + } + + ////Update Profile info + Future> updateBasicProfileInfo( + {required String token, + required int profileId, + required Profile profileInfo, + required int? genderId, + required int? indigencyId, + required int? disabilityId, + required int? ethnicityId, + required int? reqligionId}) async { + String authtoken = "Token $token"; + String path = Url.instance.updatePersonalInfor(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map? statusResponse = {}; + Map body = { + "profile_id": profileId, + "first_name": profileInfo.firstName, + "middle_name": profileInfo.middleName!.isEmpty?null:profileInfo.middleName, + "last_name": profileInfo.lastName, + "name_extension": profileInfo.nameExtension, + "birthdate": profileInfo.birthdate.toString(), + "sex": profileInfo.sex, + "blood_type": profileInfo.bloodType, + "civil_status": profileInfo.civilStatus, + "height": profileInfo.heightM, + "weight": profileInfo.weightKg, + "ethnicity_id": ethnicityId, + "disability_id": disabilityId, + "gender_id": genderId, + "religion_id": reqligionId, + "ip_id": indigencyId, + "title_prefix": profileInfo.titlePrefix, + "title_suffix": profileInfo.titleSuffix + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + return statusResponse; + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/sevices/profile/references_services.dart b/lib/sevices/profile/references_services.dart new file mode 100644 index 0000000..e30e827 --- /dev/null +++ b/lib/sevices/profile/references_services.dart @@ -0,0 +1,136 @@ + + + +import 'dart:convert'; + +import 'package:unit2/utils/request.dart'; + +import '../../model/profile/references.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; +class ReferencesServices{ + static final ReferencesServices _instance = ReferencesServices(); + static ReferencesServices get instace => _instance; + + Future> getRefences(int profileId, String token)async{ + +List references = []; + String authToken = "Token $token"; + String path = "${Url.instance.reference()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try{ + http.Response response = await Request.instance.getRequest(path: path,param: {},headers: headers); + if(response.statusCode == 200){ + Map data = jsonDecode(response.body); + if(data['data'] != null){ + data['data'].forEach((var ref){ + PersonalReference reference = PersonalReference.fromJson(ref); + references.add(reference); + }); + } + } + }catch(e){ + throw e.toString(); + } + return references; + } + Future>addReference({required PersonalReference ref, required String token, required int profileId})async{ + String authToken = "Token $token"; + String path = "${Url.instance.reference()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map responseStatus ={}; + bool overseas = ref.address!.country !=null?true:false; + Map body = { + "first_name": ref.firstName, + "middle_name": ref.middleName, + "last_name": ref.lastName, + "contact_no":ref.contactNo, + "_addressCatId": ref.address!.addressCategory!.id, + "_areaClass": "Village", + "_citymunCode": overseas?null: ref.address?.cityMunicipality?.code, + "_brgyCode": overseas?null:ref.address?.barangay?.code, + "_countryId": overseas?ref.address!.country!.id:175 + }; + try{ + http.Response response = await Request.instance.postRequest(path: path,body: body,param: {},headers: headers); + if(response.statusCode == 201){ + Map data = jsonDecode(response.body); + responseStatus = data; + }else{ + responseStatus.addAll({'success':false}); + } + return responseStatus; + }catch(e){ + throw e.toString(); + } +} +Future> update({required PersonalReference ref,required String token, required int profileId})async{ + String authToken = "Token $token"; + String path = "${Url.instance.reference()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map responseStatus ={}; + bool overseas = ref.address!.country!.id != 175; + Map body = { + "id":ref.id, + "related_person_id": profileId, + "first_name": ref.firstName, + "middle_name": ref.middleName, + "last_name": ref.lastName, + "contact_no":ref.contactNo, + "_addressCatId": ref.address!.addressCategory!.id, + "_areaClass": "Village", + "_citymunCode": overseas?null: ref.address?.cityMunicipality?.code, + "_brgyCode": overseas?null:ref.address?.barangay?.code, + "_countryId": overseas?ref.address!.country!.id:175 + }; + try{ + http.Response response = await Request.instance.putRequest(path: path,body: body,param: {},headers: headers); + if(response.statusCode == 200){ + Map data = jsonDecode(response.body); + responseStatus = data; + }else{ + responseStatus.addAll({'success':false}); + } + return responseStatus; + }catch(e){ + throw e.toString(); + } +} + +Futuredelete({required int profileId, required String token, required int id })async{ + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.reference()}$profileId/"; + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try{ + http.Response response = await Request.instance.deleteRequest(path: path, headers: headers, body: {"id":id}, param: params); + if(response.statusCode == 200){ + Map data = jsonDecode(response.body); + success=data['success']; + }else{ + success = false; + } + return success!; + }catch(e){ + throw e.toString(); + } + +} + +} + + + diff --git a/lib/sevices/profile/volunatary_services.dart b/lib/sevices/profile/volunatary_services.dart new file mode 100644 index 0000000..e655744 --- /dev/null +++ b/lib/sevices/profile/volunatary_services.dart @@ -0,0 +1,160 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../model/profile/voluntary_works.dart'; +import '../../utils/urls.dart'; + +class VoluntaryService { + static final VoluntaryService _instance = VoluntaryService(); + static VoluntaryService get instance => _instance; + + Future> getVoluntaryWorks( + int profileId, String token) async { + List voluntaryWorks = []; + String authToken = "Token $token"; + String path = "${Url.instance.getVoluntaryWorks()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var work) { + VoluntaryWork voluntaryWork = VoluntaryWork.fromJson(work); + voluntaryWorks.add(voluntaryWork); + }); + } + } + } catch (e) { + throw (e.toString()); + } + + return voluntaryWorks; + } + + Future> add( + {required VoluntaryWork voluntaryWork, + required int profileId, + required String token}) async { + Map? responseData = {}; + String authToken = "Token $token"; + String path = "${Url.instance.getVoluntaryWorks()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "position_id": voluntaryWork.position?.id, + "agency_id": voluntaryWork.agency?.id, + "address_id": voluntaryWork.address?.id, + "from_date": voluntaryWork.fromDate.toString(), + "to_date": voluntaryWork.toDate == null?null:voluntaryWork.toDate.toString(), + "total_hours": voluntaryWork.totalHours, + "_positionName": voluntaryWork.position!.title, + "_agencyName": voluntaryWork.agency!.name, + "_agencyCatId": voluntaryWork.agency!.category!.id, + "_privateEntity": voluntaryWork.agency!.privateEntity, + "_citymunCode": voluntaryWork.address?.cityMunicipality?.code, + "_countryId": voluntaryWork.address?.country?.id + }; + try { + http.Response response = await Request.instance + .postRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + responseData = data; + } else { + responseData.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return responseData; + } + +////update + Future> update( + {required VoluntaryWork voluntaryWork, + required int profileId, + required String token, + required int oldPosId, + required int oldAgencyId, + required String oldFromDate}) async { + Map? responseData = {}; + String authToken = "Token $token"; + String path = "${Url.instance.getVoluntaryWorks()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "position_id": voluntaryWork.position?.id, + "agency_id": voluntaryWork.agency?.id, + "address_id": voluntaryWork.address!.id, + "from_date": voluntaryWork.fromDate.toString(), + "to_date": voluntaryWork.toDate == null?null:voluntaryWork.toDate.toString(), + "total_hours": voluntaryWork.totalHours, + "_positionName": voluntaryWork.position!.title, + "_agencyName": voluntaryWork.agency!.name, + "_agencyCatId": voluntaryWork.agency!.category!.id, + "_privateEntity": voluntaryWork.agency!.privateEntity, + "_citymunCode": voluntaryWork.address?.cityMunicipality?.code, + "_countryId": voluntaryWork.address!.country!.id, + "_oldPosId": oldPosId, + "_oldAgencyId": oldAgencyId, + "_oldFromDate": oldFromDate + }; + try { + http.Response response = await Request.instance + .putRequest(param: {}, path: path, body: body, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + responseData = data; + } else { + responseData.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return responseData; + } + + ////delete + Future delete( + {required int agencyId, + required int positionId, + required String fromDate, + required String token, + required int profileId}) async { + bool success = false; + String authToken = "Token $token"; + String path = "${Url.instance.getVoluntaryWorks()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map params = {"force_mode": "true"}; + Map body = { + "agency_id": agencyId, + "position_id": positionId, + "from_date": fromDate, + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } + } catch (e) { + throw (e.toString()); + } + return success; + } +} diff --git a/lib/sevices/profile/work_history_services.dart b/lib/sevices/profile/work_history_services.dart new file mode 100644 index 0000000..d227099 --- /dev/null +++ b/lib/sevices/profile/work_history_services.dart @@ -0,0 +1,443 @@ +import 'dart:convert'; + +import 'package:intl/intl.dart'; +import 'package:unit2/model/profile/work_history.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/utils/agency_position.dart'; +import 'package:unit2/model/utils/position.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../utils/urls.dart'; + +class WorkHistoryService { + static final WorkHistoryService _instance = WorkHistoryService(); + static WorkHistoryService get instance => _instance; + +////get all workhistories + Future> getWorkExperiences( + int profileId, String token) async { + List workExperiences = []; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + String path = Url.instance.workhistory() + profileId.toString(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var workHistory) { + workExperiences.add(WorkHistory.fromJson(workHistory)); + }); + } + } + } catch (e) { + throw e.toString(); + } + return workExperiences; + } + +////delete workhistory + Future delete( + {required int profileId, + required String token, + required WorkHistory work}) async { + bool? success; + Map params = {"force_mode": "true"}; + String authToken = "Token $token"; + String path = "${Url.instance.deleteWorkHistory()}$profileId/"; + Map body = { + "id": work.id, + "position_id": work.position!.id, + "agency_id": work.agency!.id, + "from_date": work.fromDate?.toString(), + "to_date": work.toDate?.toString(), + // "monthly_salary": work.monthlysalary, + // "appointment_status": work.statusAppointment, + // "salary_step": work.sgstep, + // "salary_grade": work.salarygrade, + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw e.toString(); + } + return success!; + } + + ////edit work history + // Future> update({required WorkHistory oldWorkHistory, required WorkHistory newWorkHistory, required String token, required String profileId})async{ + // Map? statusResponse={}; + // String authtoken = "Token $token"; + // String path = '${Url.instance.workhistory()}$profileId/'; + // Map headers = { + // 'Content-Type': 'application/json; charset=UTF-8', + // 'Authorization': authtoken + // }; + // Map body = { + // "id":newWorkHistory.id, + // "position_id":newWorkHistory.position!.id, + // "agency_id":newWorkHistory.agency!.id, + // "from_date":newWorkHistory.fromDate?.toString(), + // "to_date":newWorkHistory.toDate?.toString(), + // "monthly_salary":newWorkHistory.monthlysalary, + // "appointment_status":newWorkHistory.statusAppointment, + // "salary_grade":newWorkHistory.salarygrade, + // "sg_step":newWorkHistory.sgstep, + // "_positionName":newWorkHistory.position!.title!, + // "_agencyName":newWorkHistory.agency!.name!, + // "_agencyCatId":newWorkHistory.agency!.category!.id!, + // "_privateEntity":newWorkHistory.agency!.privateEntity, + // "oldPosId":oldWorkHistory.position!.id, + // "_oldAgencyId":oldWorkHistory.agency!.id, + // "oldFromDate":oldWorkHistory.fromDate?.toString(), + // }; + + // try{ + // http.Response response = await Request.instance.putRequest(path: path, headers: headers, body: body, param: {}); + // if(response.statusCode == 200 ){ + // Map data = jsonDecode(response.body); + // statusResponse = data; + // }else{ + // statusResponse.addAll({'success':false}); + // } + // return statusResponse; + // }catch(e){ + // throw e.toString(); + // } + // } + + ////Add work history + Future> add( + {required WorkHistory workHistory, + required String token, + required int profileId, + required bool isPrivate, + required String? accomplishment, + required String? actualDuties}) async { + String authtoken = "Token $token"; + String path = '${Url.instance.workhistory()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = {}; + Map statusResponse = {}; + String fromDate = DateFormat('yyyy-MM-dd').format(workHistory.fromDate!); + String? toDate = workHistory.toDate == null + ? null + : DateFormat('yyyy-MM-dd').format(workHistory.toDate!); + + if (workHistory.toDate == null) { + body = { + "a_category_id ": workHistory.agency?.category?.id == null + ? "" + : workHistory.agency!.category!.id.toString(), + "a_name": + workHistory.agency?.name == null ? "" : workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null + ? "" + : workHistory.agency!.privateEntity.toString(), + "accomplishment": accomplishment ?? "", + "actual_duties ": actualDuties!, + "agency_id": workHistory.agency?.id == null + ? "" + : workHistory.agency!.id.toString(), + "from_date": fromDate, + "monthly_salary": workHistory.monthlysalary == null + ? "" + : workHistory.monthlysalary.toString(), + "position_id": workHistory.position?.id == null + ? "" + : workHistory.position!.id.toString(), + "position_name": workHistory.position?.title == null + ? "" + : workHistory.position!.title!, + "s_fname": workHistory.supervisor?.firstname == null + ? "" + : workHistory.supervisor!.firstname!, + "s_lname": workHistory.supervisor?.lastname == null + ? "" + : workHistory.supervisor!.lastname!, + "s_mname": workHistory.supervisor?.middlename == null + ? "" + : workHistory.supervisor!.middlename!, + "s_office": workHistory.supervisor?.stationName == null + ? "" + : workHistory.supervisor!.stationName!, + "salary_grade": workHistory.salarygrade == null + ? "" + : workHistory.salarygrade.toString(), + "sg_step": + workHistory.sgstep == null ? "" : workHistory.sgstep.toString(), + 'status_appointment': workHistory.statusAppointment ?? "", + }; + } else { + body = { + "a_category_id ": workHistory.agency?.category?.id == null + ? "" + : workHistory.agency!.category!.id.toString(), + "a_name": + workHistory.agency?.name == null ? "" : workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null + ? "" + : workHistory.agency!.privateEntity.toString(), + "accomplishment": accomplishment ?? "", + "actual_duties ": actualDuties!, + "agency_id": workHistory.agency?.id == null + ? "" + : workHistory.agency!.id.toString(), + "from_date": fromDate, + "monthly_salary": workHistory.monthlysalary == null + ? "" + : workHistory.monthlysalary.toString(), + "position_id": workHistory.position?.id == null + ? "" + : workHistory.position!.id.toString(), + "position_name": workHistory.position?.title == null + ? "" + : workHistory.position!.title!, + "s_fname": workHistory.supervisor?.firstname == null + ? "" + : workHistory.supervisor!.firstname!, + "s_lname": workHistory.supervisor?.lastname == null + ? "" + : workHistory.supervisor!.lastname!, + "s_mname": workHistory.supervisor?.middlename == null + ? "" + : workHistory.supervisor!.middlename!, + "s_office": workHistory.supervisor?.stationName == null + ? "" + : workHistory.supervisor!.stationName!, + "salary_grade": workHistory.salarygrade == null + ? "" + : workHistory.salarygrade.toString(), + "sg_step": + workHistory.sgstep == null ? "" : workHistory.sgstep.toString(), + 'status_appointment': workHistory.statusAppointment ?? "", + "to_date": toDate!, + }; + } + + var request = http.MultipartRequest( + 'POST', + Uri.parse( + '${Url.instance.prefixHost()}://${Url.instance.host()}$path')); + request.fields.addAll(body); + request.headers.addAll(headers); + try { + http.StreamedResponse response = await request.send(); + final steamResponse = await response.stream.bytesToString(); + Map data = jsonDecode(steamResponse); + if (response.statusCode == 201) { + statusResponse = data; + } else { + String message = data['response']['details']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future> update( + {required WorkHistory workHistory, + required String token, + required int profileId, + required bool isPrivate}) async { + String authtoken = "Token $token"; + String path = '${Url.instance.workhistory()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + + Map body = {}; + Map statusResponse = {}; + String fromDate = DateFormat('yyyy-MM-dd').format(workHistory.fromDate!); + String? toDate = workHistory.toDate == null + ? null + : DateFormat('yyyy-MM-dd').format(workHistory.toDate!); + if (workHistory.toDate == null) { + body = { + "a_category_id ": workHistory.agency?.category?.id == null + ? "" + : workHistory.agency!.category!.id.toString(), + "a_name": + workHistory.agency?.name == null ? "" : workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null + ? "" + : workHistory.agency!.privateEntity.toString(), + "accomplishment": workHistory.accomplishment == null + ? "" + : workHistory.accomplishment!.first.accomplishment!, + "actual_duties ": workHistory.actualDuties == null + ? "" + : workHistory.actualDuties!.first.description, + "agency_id": workHistory.agency?.id == null + ? "" + : workHistory.agency!.id.toString(), + "from_date": fromDate, + "monthly_salary": workHistory.monthlysalary == null + ? "" + : workHistory.monthlysalary.toString(), + "position_id": workHistory.position?.id == null + ? "" + : workHistory.position!.id.toString(), + "position_name": workHistory.position?.title == null + ? "" + : workHistory.position!.title!, + "s_fname": workHistory.supervisor?.firstname == null + ? "" + : workHistory.supervisor!.firstname!, + "s_lname": workHistory.supervisor?.lastname == null + ? "" + : workHistory.supervisor!.lastname!, + "s_mname": workHistory.supervisor?.middlename == null + ? "" + : workHistory.supervisor!.middlename!, + "s_office": workHistory.supervisor?.stationName == null + ? "" + : workHistory.supervisor!.stationName!, + "salary_grade": workHistory.salarygrade == null + ? "" + : workHistory.salarygrade.toString(), + "sg_step": + workHistory.sgstep == null ? "" : workHistory.sgstep.toString(), + 'status_appointment': workHistory.statusAppointment ?? "", + }; + } else { + body = { + "a_category_id ": workHistory.agency?.category?.id == null + ? "" + : workHistory.agency!.category!.id.toString(), + "a_name": + workHistory.agency?.name == null ? "" : workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null + ? "" + : workHistory.agency!.privateEntity.toString(), + "accomplishment": workHistory.accomplishment == null + ? "" + : workHistory.accomplishment!.first.accomplishment!, + "actual_duties ": workHistory.actualDuties == null + ? "" + : workHistory.actualDuties!.first.description, + "agency_id": workHistory.agency?.id == null + ? "" + : workHistory.agency!.id.toString(), + "from_date": fromDate, + "monthly_salary": workHistory.monthlysalary == null + ? "" + : workHistory.monthlysalary.toString(), + "position_id": workHistory.position?.id == null + ? "" + : workHistory.position!.id.toString(), + "position_name": workHistory.position?.title == null + ? "" + : workHistory.position!.title!, + "s_fname": workHistory.supervisor?.firstname == null + ? "" + : workHistory.supervisor!.firstname!, + "s_lname": workHistory.supervisor?.lastname == null + ? "" + : workHistory.supervisor!.lastname!, + "s_mname": workHistory.supervisor?.middlename == null + ? "" + : workHistory.supervisor!.middlename!, + "s_office": workHistory.supervisor?.stationName == null + ? "" + : workHistory.supervisor!.stationName!, + "salary_grade": workHistory.salarygrade == null + ? "" + : workHistory.salarygrade.toString(), + "sg_step": + workHistory.sgstep == null ? "" : workHistory.sgstep.toString(), + 'status_appointment': workHistory.statusAppointment ?? "", + "to_date": toDate!, + }; + } + + var request = http.MultipartRequest( + 'PUT', + Uri.parse( + '${Url.instance.prefixHost()}://${Url.instance.host()}$path')); + request.fields.addAll(body); + request.headers.addAll(headers); + // try { + http.StreamedResponse response = await request.send(); + final steamResponse = await response.stream.bytesToString(); + Map data = jsonDecode(steamResponse); + if (response.statusCode == 201) { + statusResponse = data; + } else { + String message = data['response']['details']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + // } catch (e) { + // throw e.toString(); + // } + return statusResponse; + } + +////get agency position + Future> getAgencyPosition() async { + List agencyPositions = []; + String path = Url.instance.getPositions(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var agencyPosition) { + PositionTitle position = PositionTitle.fromJson(agencyPosition); + agencyPositions.add(position); + }); + } + } + } catch (e) { + throw (e.toString()); + } + return agencyPositions; + } + +//get appointment status + List getAppointmentStatusList() { + return [ + AppoinemtStatus(value: "Appointed", label: "Appointed"), + AppoinemtStatus(value: "Casual", label: "Casual"), + AppoinemtStatus( + value: "Contact of Service", label: "Contract of Service"), + AppoinemtStatus(value: "Coterminous", label: "Coterminous"), + AppoinemtStatus(value: "Elected", label: "Elected"), + AppoinemtStatus(value: "Job Order", label: "Job Order"), + AppoinemtStatus(value: "Permanent", label: "Permanent"), + AppoinemtStatus(value: "Elected", label: "Elected"), + ]; + } +} diff --git a/lib/sevices/roles/est_point_person/est_point_person_role_assignment_services.dart b/lib/sevices/roles/est_point_person/est_point_person_role_assignment_services.dart new file mode 100644 index 0000000..eed7064 --- /dev/null +++ b/lib/sevices/roles/est_point_person/est_point_person_role_assignment_services.dart @@ -0,0 +1,163 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/assigned_role.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import 'package:http/http.dart' as http; + +import '../../../model/profile/basic_information/primary-information.dart'; +import '../../../model/rbac/role_under.dart'; + +class EstPointPersonRoleAssignment { + static final EstPointPersonRoleAssignment _instance = + EstPointPersonRoleAssignment(); + static EstPointPersonRoleAssignment get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getAssignedRoles( + {required int webuserId}) async { + List assignedRoles = []; + String path = Url.instance.getRoleAssignment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map param = { +"created_by__id": webuserId.toString() + }; + try { + http.Response response = await Request.instance + .getRequest(param: param, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var role in data['data']) { + AssignedRole newRole = AssignedRole.fromJson(role); + assignedRoles.add(newRole); + } + } + } + } catch (e) { + throw e.toString(); + } + return assignedRoles; + } + Future> getRolesUnder({required int roleId}) async { + List rolesUnder = []; + String path = Url.instance.getRolesUnder(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map param={"role_under_main__id":roleId.toString()}; + try { + http.Response response = await Request.instance + .getRequest(param: param, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var roleUnd in data['data']) { + RolesUnder newRoleUnder = RolesUnder.fromJson(roleUnd); + rolesUnder.add(newRoleUnder); + } + } + } + } catch (e) { + throw e.toString(); + } + return rolesUnder; + } + + Future deleteAssignedRole({required int roleId}) async { + bool success = false; + String path = "${Url.instance.getRoleAssignment()}$roleId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } + ////Add + Future> add({ + required int userId, + required int? assignerId, + required List roles, + }) async { + String path = Url.instance.getRoleAssignment(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "user_id": userId, + "roles": roles, + "assigner_user_id": assignerId, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future searchUser( + {required int page, required String name, required String lastname}) async { + String path = Url.instance.searchUsers(); + Profile? user; + Map params = { + "profile__last_name__icontains": lastname, + "profile__first_name__icontains": name, + "page": page.toString(), + "is_paginated": "true", + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + for(var profile in data['data']) { + int websuerId = profile['webuserid']; + Profile newUser = Profile.fromJson(profile['profile']); + newUser.webuserId = websuerId; + user= newUser; + break; + } + } + + return user; + } + +} diff --git a/lib/sevices/roles/pass_check_services.dart b/lib/sevices/roles/pass_check_services.dart new file mode 100644 index 0000000..3b076a6 --- /dev/null +++ b/lib/sevices/roles/pass_check_services.dart @@ -0,0 +1,265 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:audioplayers/audioplayers.dart'; +import 'package:flutter/services.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/roles/pass_check/agency_area_type.dart'; +import 'package:unit2/model/roles/pass_check/assign_role_area_type.dart'; +import 'package:unit2/model/roles/pass_check/barangay_assign_area.dart'; +import 'package:unit2/model/roles/pass_check/passer_info.dart'; +import 'package:unit2/utils/global.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../model/roles/pass_check/purok_assign_area.dart'; +import '../../model/roles/pass_check/station_assign_area.dart'; +import '../../utils/urls.dart'; + +class PassCheckServices { + static final PassCheckServices _instance = PassCheckServices(); + static PassCheckServices get instance => _instance; + + Future> getPassCheckArea( + {required int roleId, required int userId}) async { + String path = Url.instance.getAssignAreas(); + Map params = { + "assigned_role__role__id": roleId.toString(), + "assigned_role__user__id": userId.toString() + }; + List? statusResponse; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, headers: headers, path: path); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + AssignRoleAreaType assignRoleAreaType = AssignRoleAreaType.fromJson( + data['data'][0]['assigned_role_area_type']); + ////station + if (assignRoleAreaType.areaTypeName.toLowerCase() == "station") { + List assignedArea = []; + data['data'][0]['assigned_area'].forEach((element) { + StationAssignArea stationAssignArea = + StationAssignArea.fromJson(element); + ChildStationInfo headStation = ChildStationInfo( + id: stationAssignArea.area!.id, + stationName: stationAssignArea.area!.stationName, + acroym: stationAssignArea.area!.acronym, + motherStation: true); + ChildStationInfo childStationInfo = ChildStationInfo( + id: stationAssignArea.area!.id, + stationName: stationAssignArea.area!.stationName, + acroym: stationAssignArea.area!.acronym, + motherStation: false); + assignedArea.add(headStation); + assignedArea.add(childStationInfo); + if (stationAssignArea.area?.childStationInfo != null) { + for (var element in stationAssignArea.area!.childStationInfo!) { + ChildStationInfo newStationInfo = ChildStationInfo( + id: element.id, + stationName: element.stationName, + acroym: element.acroym, + motherStation: false); + assignedArea.add(newStationInfo); + } + } + }); + + statusResponse = assignedArea; + } + ////registration in-chage + if (assignRoleAreaType.areaTypeName.toLowerCase() == + "registration in-charge") { + List assignedArea = []; + data['data'][0]['assigned_area'].forEach((element) { + StationAssignArea stationAssignArea = + StationAssignArea.fromJson(element); + ChildStationInfo headStation = ChildStationInfo( + id: stationAssignArea.area!.id, + stationName: stationAssignArea.area!.stationName, + acroym: stationAssignArea.area!.acronym, + motherStation: true); + ChildStationInfo childStationInfo = ChildStationInfo( + id: stationAssignArea.area!.id, + stationName: stationAssignArea.area!.stationName, + acroym: stationAssignArea.area!.acronym, + motherStation: false); + assignedArea.add(headStation); + assignedArea.add(childStationInfo); + if (stationAssignArea.area?.childStationInfo != null) { + for (var element in stationAssignArea.area!.childStationInfo!) { + ChildStationInfo newStationInfo = ChildStationInfo( + id: element.id, + stationName: element.stationName, + acroym: element.acroym, + motherStation: false); + assignedArea.add(newStationInfo); + } + } + }); + statusResponse = assignedArea; + } + ////Barangay + if (assignRoleAreaType.areaTypeName.toLowerCase() == "baranggay") { + List assignedArea = []; + data['data'][0]['assigned_area'].forEach((var element) { + BaragayAssignArea baragayAssignArea = + BaragayAssignArea.fromJson(element['area']); + assignedArea.add(baragayAssignArea); + }); + statusResponse = assignedArea; + } + ////PUROK + if (assignRoleAreaType.areaTypeName.toLowerCase() == 'purok') { + List assignedArea = []; + data['data'][0]['assigned_area'].forEach((var element) { + Purok purok = Purok.fromJson(element['area']); + assignedArea.add(purok); + }); + statusResponse = assignedArea; + } + ////AGENCY + if (assignRoleAreaType.areaTypeName.toLowerCase() == 'agency') { + List assignedArea = []; + data['data'][0]['assigned_area'].forEach((var element) { + AgencyAssignedArea agencyAssignedArea = + AgencyAssignedArea.fromJson(element); + assignedArea.add(agencyAssignedArea); + }); + statusResponse = assignedArea; + } + } + } catch (e) { + throw e.toString(); + } + return statusResponse!; + } + + Future getPasserInfo( + {required String uuid, required String token}) async { + PasserInfo? passerInfo; + String path = Url.instance.getPasserInfo(); + String authtoken = "Token $token"; + Map params = {"uuid": uuid}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map body = jsonDecode(response.body); + passerInfo = PasserInfo.fromJson(body['data'][0]); + } + } catch (e) { + throw (e.toString()); + } + return passerInfo; + } + + Future performPostLogs( + {required String passerId, + required int chekerId, + required String io, + required bool otherInputs, + String? destination, + double? temp, + int? stationId, + String? cpId, + required int roleid}) async { + String path = Url.instance.postLogs(); + bool success; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + Map body; + if (otherInputs) { + if (roleid == 41 || roleid == 13 || roleid == 17 || roleid == 22) { + if (io == "i") { + print("1"); + body = { + "station_id": stationId, + "temperature": temp, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } else { + print("2"); + body = { + "station_id": stationId, + "destination": destination, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } + } else { + print("3"); + if (io == "i") { + body = { + "cp_id": cpId, + "temperature": temp, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } else { + print("4"); + body = { + "cp_id": cpId, + "destination": destination, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } + } + } else { + print("5"); + if (roleid == 41 || roleid == 13 || roleid == 17 || roleid == 22) { + body = { + "station_id": stationId, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } else { + print("6"); + body = { + "cp_id": cpId, + "temperature": temp, + "passer": passerId, + "checkedby_user_id": chekerId, + "io": io + }; + } + } + try { + http.Response response = await Request.instance + .postRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 201) { + success = true; + } else { + success = false; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} + +Future setFailedAudio(AudioPlayer audioPlayer) async { + AudioCache player = AudioCache(); + + final url = await player.load("ScanFailed.mp3"); + audioPlayer.play(AssetSource(url.path)); +} diff --git a/lib/sevices/roles/rbac_operations/agency_services.dart b/lib/sevices/roles/rbac_operations/agency_services.dart new file mode 100644 index 0000000..5445652 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/agency_services.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:unit2/screens/profile/components/other_information/org_membership/add_modal.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import '../../../model/utils/agency.dart'; +import 'package:http/http.dart' as http; + +class AgencyServices { + static final AgencyServices _instance = AgencyServices(); + static AgencyServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getAgencies() async { + List agencies = []; + String path = Url.instance.agencies(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var element in data['data']) { + Agency newAgency = Agency.fromJson(element); + agencies.add(newAgency); + } + } + } + } catch (e) { + throw e.toString(); + } + return agencies; + } + Future>add({required Agency agency})async{ + Map statusResponse = {}; + String path = Url.instance.postAgencies(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "name":agency.name, + "category_id":agency.category!.id, + "private_entity":agency.privateEntity, + "contact_info":null, + }; + try{ + http.Response response = await Request.instance.postRequest(param: {},path: path, body: body,headers: headers); + if(response.statusCode == 201){ + Map data = jsonDecode(response.body); + statusResponse = data; + }else{ + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + }catch(e){ + throw e.toString(); + } + return statusResponse; + } +} diff --git a/lib/sevices/roles/rbac_operations/module_objects_services.dart b/lib/sevices/roles/rbac_operations/module_objects_services.dart new file mode 100644 index 0000000..87e9890 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/module_objects_services.dart @@ -0,0 +1,98 @@ +import 'dart:convert'; + +import 'package:unit2/model/login_data/user_info/module.dart'; +import 'package:http/http.dart' as http; +import '../../../model/rbac/rbac_rbac.dart'; +import '../../../utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacModuleObjectsServices { + static final RbacModuleObjectsServices _instance = + RbacModuleObjectsServices(); + static RbacModuleObjectsServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + Future> getModuleObjects() async { + List moduleObjects = []; + String path = Url.instance.getModuleObjects(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var modObj in data['data']) { + ModuleObjects newModObj = ModuleObjects.fromJson(modObj); + moduleObjects.add(newModObj); + } + } + } + } catch (e) { + throw e.toString(); + } + return moduleObjects; + } + + ////Add + Future> add({ + required int assignerId, + required int? moduleId, + required List objectsId, + }) async { + String path = Url.instance.getModuleObjects(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "module_id": moduleId, + "objects": objectsId, + "assigner_user_id": assignerId + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deleteRbacModuleObject({required int moduleObjectId}) async { + bool success = false; + String path = "${Url.instance.getModuleObjects()}$moduleObjectId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/module_services.dart b/lib/sevices/roles/rbac_operations/module_services.dart new file mode 100644 index 0000000..76ea4a1 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/module_services.dart @@ -0,0 +1,146 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacModuleServices { + static final RbacModuleServices _instance = RbacModuleServices(); + static RbacModuleServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRbacModule() async { + List modules = []; + String path = Url.instance.getModules(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var rbac in data['data']) { + RBAC newModule = RBAC.fromJson(rbac); + modules.add(newModule); + } + } + } + } catch (e) { + throw e.toString(); + } + + return modules; + } + ////Add + Future> add( + {required String name, + required String? slug, + required String? short, + required int id}) async { + String path = Url.instance.getModules(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "fontawesome_icon":"mobile", + "created_by_id": id, + "updated_by_id": id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////Update + Future> update({ + required int moduleId, + required String name, + required String? slug, + required String? short, + required int? createdBy, + required int updatedBy, + }) async { + String path = "${Url.instance.getModules()}$moduleId/"; + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": createdBy, + "updated_by_id": updatedBy, + "fontawesome_icon":"mobile", + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deleteRbacModule({required int moduleId}) async { + bool success = false; + String path = "${Url.instance.getModules()}$moduleId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/object_services.dart b/lib/sevices/roles/rbac_operations/object_services.dart new file mode 100644 index 0000000..7e61543 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/object_services.dart @@ -0,0 +1,144 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacObjectServices { + static final RbacObjectServices _instance = RbacObjectServices(); + static RbacObjectServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRbacObjects() async { + List objects = []; + String path = Url.instance.getObject(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var rbac in data['data']) { + RBAC newRbac = RBAC.fromJson(rbac); + objects.add(newRbac); + } + } + } + } catch (e) { + throw e.toString(); + } + + return objects; + } + ////Add + Future> add( + {required String name, + required String? slug, + required String? short, + required int id}) async { + String path = Url.instance.getObject(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": id, + "updated_by_id": id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': "Error Adding Object"}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////Update + Future> update({ + required int objectId, + required String name, + required String? slug, + required String? short, + required int? createdBy, + required int updatedBy, + }) async { + String path = "${Url.instance.getObject()}$objectId/"; + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": createdBy, + "updated_by_id": updatedBy + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': "Error Updating Object"}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deleteRbacRole({required int objectId}) async { + bool success = false; + String path = "${Url.instance.getObject()}$objectId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/operation_services.dart b/lib/sevices/roles/rbac_operations/operation_services.dart new file mode 100644 index 0000000..f737dc7 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/operation_services.dart @@ -0,0 +1,144 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacOperationServices { + static final RbacOperationServices _instance = RbacOperationServices(); + static RbacOperationServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRbacOperations() async { + List roles = []; + String path = Url.instance.getOperations(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var role in data['data']) { + RBAC newRole = RBAC.fromJson(role); + roles.add(newRole); + } + } + } + } catch (e) { + throw e.toString(); + } + + return roles; + } + ////Add + Future> add( + {required String name, + required String? slug, + required String? short, + required int id}) async { + String path = Url.instance.getOperations(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": id, + "updated_by_id": id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////Update + Future> update({ + required int operationId, + required String name, + required String? slug, + required String? short, + required int? createdBy, + required int updatedBy, + }) async { + String path = "${Url.instance.getRbacOperations()}$operationId/"; + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": createdBy, + "updated_by_id": updatedBy + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future delete({required int operation}) async { + bool success = false; + String path = "${Url.instance.getRbacOperations()}$operation/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/permission_service.dart b/lib/sevices/roles/rbac_operations/permission_service.dart new file mode 100644 index 0000000..aa49ba5 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/permission_service.dart @@ -0,0 +1,100 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/permission.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacPermissionServices { + static final RbacPermissionServices _instance = RbacPermissionServices(); + static RbacPermissionServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRbacPermission() async { + List permissions = []; + String path = Url.instance.getPersmissions(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var rbac in data['data']) { + RBACPermission newRbac = RBACPermission.fromJson(rbac); + permissions.add(newRbac); + } + } + } + } catch (e) { + throw e.toString(); + } + + return permissions; + } + + + ////Add + Future> add({ + required int assignerId, + required int? objectId, + required List operationsId, + }) async { + String path = Url.instance.getPersmissions(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "object_id": objectId, + "operations": operationsId, + "assigner_user_id": assignerId + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deletePermission ({required int permissionId}) async { + bool success = false; + String path = "${Url.instance.getPersmissions()}$permissionId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/role_assignment_services.dart b/lib/sevices/roles/rbac_operations/role_assignment_services.dart new file mode 100644 index 0000000..b9d6eae --- /dev/null +++ b/lib/sevices/roles/rbac_operations/role_assignment_services.dart @@ -0,0 +1,137 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/assigned_role.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import 'package:http/http.dart' as http; + +import '../../../model/profile/basic_information/primary-information.dart'; + +class RbacRoleAssignmentServices { + static final RbacRoleAssignmentServices _instance = + RbacRoleAssignmentServices(); + static RbacRoleAssignmentServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getAssignedRoles( + {required String firstname, required String lastname}) async { + List assignedRoles = []; + String path = Url.instance.getRoleAssignment(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map param = { + "user__first_name__icontains": firstname, + "user__last_name__icontains": lastname + }; + try { + http.Response response = await Request.instance + .getRequest(param: param, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var role in data['data']) { + AssignedRole newRole = AssignedRole.fromJson(role); + assignedRoles.add(newRole); + } + } + } + } catch (e) { + throw e.toString(); + } + return assignedRoles; + } + + Future deleteAssignedRole({required int roleId}) async { + bool success = false; + String path = "${Url.instance.getRoleAssignment()}$roleId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } + ////Add + Future> add({ + required int userId, + required int? assignerId, + required List roles, + }) async { + String path = Url.instance.getRoleAssignment(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "user_id": userId, + "roles": roles, + "assigner_user_id": assignerId, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future searchUser( + {required int page, required String name, required String lastname}) async { + String path = Url.instance.searchUsers(); + Profile? user; + Map params = { + "profile__last_name__icontains": lastname, + "profile__first_name__icontains": name, + "page": page.toString(), + "is_paginated": "true", + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + for(var profile in data['data']) { + int websuerId = profile['webuserid']; + Profile newUser = Profile.fromJson(profile['profile']); + newUser.webuserId = websuerId; + user= newUser; + break; + } + } + + return user; + } + +} diff --git a/lib/sevices/roles/rbac_operations/role_extend_services.dart b/lib/sevices/roles/rbac_operations/role_extend_services.dart new file mode 100644 index 0000000..b5c0fc9 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/role_extend_services.dart @@ -0,0 +1,96 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/role_extend.dart'; +import 'package:unit2/model/rbac/role_under.dart'; +import 'package:http/http.dart' as http; +import '../../../utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacRoleExtendServices { + static final RbacRoleExtendServices _instance = RbacRoleExtendServices(); + static RbacRoleExtendServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRolesExtend() async { + List rolesextend = []; + String path = Url.instance.getRoleExtend(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + // try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var roleExt in data['data']) { + RolesExtend newRoleExtend = RolesExtend.fromJson(roleExt); + rolesextend.add(newRoleExtend); + } + } + } + // } catch (e) { + // throw e.toString(); + // } + return rolesextend; + } + + ////Add + Future> add({ + required int? roleId, + required List rolesExtendsId, + }) async { + String path = Url.instance.getRoleExtend(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "role_main_id": roleId, + "roles_extend": rolesExtendsId, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future delete({required int roleExtendId}) async { + bool success = false; + String path = "${Url.instance.getRoleExtend()}$roleExtendId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/role_module_services.dart b/lib/sevices/roles/rbac_operations/role_module_services.dart new file mode 100644 index 0000000..27a0779 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/role_module_services.dart @@ -0,0 +1,100 @@ +import 'dart:convert'; + +import 'package:unit2/model/login_data/user_info/module.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/rbac/role_module.dart'; +import '../../../model/rbac/rbac_rbac.dart'; +import '../../../utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacRoleModuleServices { + static final RbacRoleModuleServices _instance = + RbacRoleModuleServices(); + static RbacRoleModuleServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRoleModules() async { + List roleModules = []; + String path = Url.instance.getRoleModules(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var roleMod in data['data']) { + RoleModules newRoleMod = RoleModules.fromJson(roleMod); + roleModules.add(newRoleMod); + } + } + } + } catch (e) { + throw e.toString(); + } + return roleModules; + } + + ////Add + Future> add({ + required int assignerId, + required int? roleId, + required List moduleIds, + }) async { + String path = Url.instance.getRoleModules(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "role_id": roleId, + "modules": moduleIds, + "assigner_user_id": assignerId + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deleteRbacRoleModule({required int moduleObjectId}) async { + bool success = false; + String path = "${Url.instance.getRoleModules()}$moduleObjectId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/role_services.dart b/lib/sevices/roles/rbac_operations/role_services.dart new file mode 100644 index 0000000..08a689c --- /dev/null +++ b/lib/sevices/roles/rbac_operations/role_services.dart @@ -0,0 +1,146 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/sevices/profile/education_services.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacRoleServices { + static final RbacRoleServices _instance = RbacRoleServices(); + static RbacRoleServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRbacRoles() async { + List roles = []; + String path = Url.instance.getRbacRoles(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var role in data['data']) { + RBAC newRole = RBAC.fromJson(role); + roles.add(newRole); + } + } + } + } catch (e) { + throw e.toString(); + } + + return roles; + } + +////Add + Future> add( + {required String name, + required String? slug, + required String? short, + required int id}) async { + String path = Url.instance.getRbacRoles(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": id, + "updated_by_id": id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + ////Update + Future> update({ + required int roleId, + required String name, + required String? slug, + required String? short, + required int? createdBy, + required int updatedBy, + }) async { + String path = "${Url.instance.getRbacRoles()}$roleId/"; + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String? newSlug = slug?.replaceAll(" ", "-"); + Map body = { + "name": name, + "slug": newSlug?.toLowerCase(), + "shorthand": short, + "created_by_id": createdBy, + "updated_by_id": updatedBy + }; + try { + http.Response response = await Request.instance + .putRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future deleteRbacRole({required int roleId}) async { + bool success = false; + String path = "${Url.instance.getRbacRoles()}$roleId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/roles_under_services.dart b/lib/sevices/roles/rbac_operations/roles_under_services.dart new file mode 100644 index 0000000..719dab4 --- /dev/null +++ b/lib/sevices/roles/rbac_operations/roles_under_services.dart @@ -0,0 +1,96 @@ +import 'dart:convert'; + +import 'package:unit2/model/rbac/role_under.dart'; +import 'package:http/http.dart' as http; +import '../../../utils/request.dart'; +import '../../../utils/urls.dart'; + +class RbacRoleUnderServices { + static final RbacRoleUnderServices _instance = RbacRoleUnderServices(); + static RbacRoleUnderServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getRolesUnder() async { + List rolesUnder = []; + String path = Url.instance.getRolesUnder(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var roleUnd in data['data']) { + RolesUnder newRoleUnder = RolesUnder.fromJson(roleUnd); + rolesUnder.add(newRoleUnder); + } + } + } + } catch (e) { + throw e.toString(); + } + return rolesUnder; + } + + ////Add + Future> add({ + required int? roleId, + required List rolesId, + }) async { + String path = Url.instance.getRolesUnder(); + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + Map body = { + "role_main_id": roleId, + "roles_under": rolesId, + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + + Future deleteRbacRoleUnder({required int roleUnderId}) async { + bool success = false; + String path = "${Url.instance.getRolesUnder ()}$roleUnderId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .deleteRequest(path: path, headers: headers, body: {}, param: {}); + if (response.statusCode == 200) { + success = true; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/sevices/roles/rbac_operations/station_services.dart b/lib/sevices/roles/rbac_operations/station_services.dart new file mode 100644 index 0000000..977a1ee --- /dev/null +++ b/lib/sevices/roles/rbac_operations/station_services.dart @@ -0,0 +1,138 @@ +import 'dart:convert'; +import 'package:unit2/model/utils/position.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; +import '../../../model/rbac/rbac_station.dart'; +import '../../../model/rbac/station_type.dart'; +import '../../../model/roles/pass_check/station_assign_area.dart'; + +class RbacStationServices { + static final RbacStationServices _instance = RbacStationServices(); + static RbacStationServices get instance => _instance; + String xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; + String xClientKeySecret = "unitcYqAN7GGalyz"; + + Future> getStations({required String agencyId}) async { + List stations = []; + String path = Url.instance.getStation(); + Map param = {"government_agency_id": agencyId.toString()}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + try { + http.Response response = await Request.instance + .getRequest(param: param, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var station in data['data']) { + RbacStation area = RbacStation.fromJson(station); + stations.add(area); + } + } + } + } catch (e) { + throw e.toString(); + } + return stations; + } + + Future> getStationTypes() async { + String path = Url.instance.getStationType(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + List stationTypes = []; + + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var st in data['data']) { + StationType stationType = StationType.fromJson(st); + stationTypes.add(stationType); + } + } + } + } catch (e) { + throw e.toString(); + } + return stationTypes; + } + + Future> getPositionTitle() async { + String path = Url.instance.getPositionTitle(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + List positions = []; + + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var pos in data['data']) { + PositionTitle posTitle = PositionTitle.fromJson(pos); + positions.add(posTitle); + } + } + } + } catch (e) { + throw e.toString(); + } + return positions; + } + + Future> addStation( + {required RbacStation station}) async { + Map statusResponse = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientKeySecret + }; + String path = Url.instance.postStation(); + + try { + Map body = { + "station_name": station.stationName, + "acronym": station.acronym, + "station_type_id": station.stationType?.id, + "_station_type_name": station.stationType?.id != null?null:station.stationType?.typeName, + "parent_station_id": station.parentStation, + "hierarchy_order_no": station.hierarchyOrderNo, + "agency_id": station.governmentAgency!.agencyid, + "is_location_under_parent": station.islocationUnderParent, + "head_position": station.headPosition, + "code": station.code, + "full-code": station.fullcode, + "main_parent_station_id": station.mainParentStation, + "description": station.description, + "ishospital": station.ishospital, + }; + http.Response response = await Request.instance + .postRequest(param: {}, body: body, headers: headers,path: path); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + Map data = jsonDecode(response.body); + String message = data['message']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } +} diff --git a/lib/sevices/roles/rbac_services.dart b/lib/sevices/roles/rbac_services.dart new file mode 100644 index 0000000..da172e4 --- /dev/null +++ b/lib/sevices/roles/rbac_services.dart @@ -0,0 +1,218 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart'; +import 'package:unit2/model/rbac/permission.dart'; +import 'package:unit2/model/rbac/rbac.dart'; +import 'package:unit2/utils/request.dart'; + +import '../../model/profile/basic_information/primary-information.dart'; +import '../../model/rbac/new_permission.dart'; +import '../../utils/global.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class RbacServices { + static final RbacServices _instance = RbacServices(); + static RbacServices get instance => _instance; + Future> getModules() async { + List modules = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + String path = Url.instance.getModules(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((var module) { + print(module); + RBAC newModule = RBAC.fromJson(module); + modules.add(newModule); + }); + } + } catch (e) { + throw e.toString(); + } + return modules; + } + + Future> getObjects() async { + List objects = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + String path = Url.instance.getObject(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((var object) { + RBAC newObject = RBAC.fromJson(object); + objects.add(newObject); + }); + } + } catch (e) { + throw e.toString(); + } + return objects; + } + + Future> getRole() async { + List roles = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + String path = Url.instance.getRoles(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((var role) { + RBAC newRole = RBAC.fromJson(role); + roles.add(newRole); + }); + } + } catch (e) { + throw e.toString(); + } + return roles; + } + + Future> getPermission() async { + List permissions = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + String path = Url.instance.getPersmissions(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((var permission) { + RBACPermission newPermission = RBACPermission.fromJson(permission); + permissions.add(newPermission); + }); + } + } catch (e) { + throw e.toString(); + } + return permissions; + } + + Future> getOperations() async { + List operations = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + String path = Url.instance.getOperations(); + try { + http.Response response = await Request.instance + .getRequest(path: path, headers: headers, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((var operation) { + RBAC newOperation = RBAC.fromJson(operation); + operations.add(newOperation); + }); + } + } catch (e) { + throw e.toString(); + } + return operations; + } + + Future> searchUser( + {required int page, required String name, required String token}) async { + List users = []; + String path = Url.instance.searchUsers(); + String authtoken = "Token $token"; + Map params = { + "profile__last_name__icontains": name, + "page": page.toString(), + "is_paginated": "true", + }; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + data['data'].forEach((profile) { + int websuerId = profile['webuserid']; + Profile newUsers = Profile.fromJson(profile['profile']); + newUsers.webuserId = websuerId; + users.add(newUsers); + }); + } + + return users; + } + + Future> assignRBAC( + {required int assigneeId, + required int assignerId, + required RBAC? selectedRole, + required RBAC? selectedModule, + required List permissionId, + required List newPermissions}) async { + bool success = false; + String path = Url.instance.assignRbac(); + Map responseStatus = {}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'X-Client-Key': xClientKey, + 'X-Client-Secret': xClientSecret + }; + Map body = { + "assignee_user_id": assigneeId, + "assigner_user_id": assignerId, + "role_id": selectedRole?.id, + "_new_role_name": selectedRole?.name, + "_new_role_slug": selectedRole?.slug, + "_new_role_shorthand": selectedRole?.shorthand, + "module_id": selectedModule?.id, + "_new_module_name": selectedModule?.name, + "_new_module_slug": selectedModule?.slug, + "_new_module_shorthand": selectedModule?.shorthand, + "_new_module_icon": null, + "permission_ids": permissionId, + "_new_permissions": newPermissions, + "assigned_areas": [] + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, param: {}, body: body, headers: headers); + Map data = jsonDecode(response.body); + if (response.statusCode == 201) { + success = true; + String message = data['message']; + responseStatus.addAll({"success": success, "message": message}); + } else { + success = false; + String message = data['message']; + responseStatus.addAll({"success": success, "message": message}); + } + } catch (e) { + throw e.toString(); + } + + return responseStatus; + } +} diff --git a/lib/sevices/skillshobbies_services.dart b/lib/sevices/skillshobbies_services.dart new file mode 100644 index 0000000..f998dcc --- /dev/null +++ b/lib/sevices/skillshobbies_services.dart @@ -0,0 +1,129 @@ +import 'dart:convert'; + +import 'package:unit2/utils/request.dart'; + +import '../model/profile/other_information/skills_and_hobbies.dart'; +import '../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class SkillsHobbiesServices { + static final SkillsHobbiesServices _instance = SkillsHobbiesServices(); + static SkillsHobbiesServices get instance => _instance; +////GET + Future> getSkillsHobbies( + int profileId, String token) async { + List skillsAndHobbies = []; + String authToken = "Token $token"; + String path = "${Url.instance.skillsHobbies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data']['skill_hobby'] != null) { + data['data']['skill_hobby'].forEach((var hobby) { + SkillsHobbies skillsHobby = SkillsHobbies.fromJson(hobby); + skillsAndHobbies.add(skillsHobby); + }); + } + } + } catch (e) { + throw e.toString(); + } + return skillsAndHobbies; + } + +////ADD + Future> add( + {required List skillsHobbies, + required int profileId, + required String token}) async { + String authToken = "Token $token"; + String path = "${Url.instance.skillsHobbies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + List> skillsHobbiesBody=[]; + for(var element in skillsHobbies){ + skillsHobbiesBody.add({"id":element.id,"name":element.name}); + } + Map body = {"skill_hobby": skillsHobbiesBody}; + Map statusResponse = {}; + try { + http.Response response = await Request.instance + .postRequest(path: path, param: {}, headers: headers, body: body); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + statusResponse = data; + } else { + statusResponse.addAll({'success': false}); + } + } catch (e) { + throw e.toString(); + } + return statusResponse; + } + + Future delete( + {required int profileId, + required String token, + required List skillsHobbies}) async { + String authToken = "Token $token"; + bool success = false; + String path = "${Url.instance.skillsHobbies()}$profileId/"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map params = {"force_mode": "true"}; + + Map body = { + "skill_hobby": [{"id":skillsHobbies[0].id, "name":skillsHobbies[0].name}] + + }; + // try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } + // } catch (e) { + // throw e.toString(); + // } + return success; + } + + ////GET ALL + Future> getAllSkillsHobbies() async { + List skillsAndHobbies = []; + String path = Url.instance.getAllSkillsHobbies(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance.getRequest( + param: {}, + path: path, + headers: headers, + ); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var element) { + SkillsHobbies skillsHobbies = SkillsHobbies.fromJson(element); + skillsAndHobbies.add(skillsHobbies); + }); + } + } + } catch (e) { + throw e.toString(); + } + return skillsAndHobbies; + } +} diff --git a/lib/sevices/sos/sos_service.dart b/lib/sevices/sos/sos_service.dart new file mode 100644 index 0000000..0cb0697 --- /dev/null +++ b/lib/sevices/sos/sos_service.dart @@ -0,0 +1,125 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; +import 'package:location/location.dart'; +import 'package:platform_device_id/platform_device_id.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/utils/request.dart'; +import '../../model/sos/session.dart'; +import '../../utils/urls.dart'; + +class SosService{ + static final SosService _instance = SosService(); + static SosService get instance => _instance; + DateFormat todayFormat = DateFormat("yMdHms"); + Future getUserLocation() async { + Location location = Location(); + LocationData? locationData; + bool serviceEnabled = false; + PermissionStatus permissionGranted; + + serviceEnabled = await location.serviceEnabled(); + if (!serviceEnabled) { + serviceEnabled = await location.requestService(); + if (!serviceEnabled) { + return null; + } + } + permissionGranted = await location.hasPermission(); + if (permissionGranted == PermissionStatus.denied) { + permissionGranted = await location.requestPermission(); + if (permissionGranted != PermissionStatus.granted) { + return null; + } + } + try{ + LocationData newLocationData = await location.getLocation(); + locationData = newLocationData; + return locationData; + }catch(e){ + throw e.toString(); + } + } + Future initPlatformState() async { + String? deviceId; + try { + deviceId = await PlatformDeviceId.getDeviceId; + } on PlatformException { + deviceId = 'Failed to get deviceId.'; + } + return deviceId!; + } + + +Future requestSos({required LocationData location, required String mobile1, + String? mobile2, required String msg, required String requestedDate}) async { + var body; + String deviceId = await initPlatformState(); + String sessionToken = + deviceId.toString() + todayFormat.format(DateTime.now()); + String path = Url.instance.sosRequest(); + SessionData? sessionData; + + if(mobile2 != null){ + body = { + "mobile_id": deviceId.toString(), + "mobile_gps": + "${location.latitude.toString()},${location.longitude.toString()}", + "mobile1": mobile1, + "mobile2": mobile2, + "respondent_message": msg, + "session_token": sessionToken, + "pushedbutton_date": requestedDate + }; + }else{ + body = { + "mobile_id": deviceId.toString(), + "mobile_gps": + "${location.latitude.toString()},${location.longitude.toString()}", + "mobile1": mobile1, + "respondent_message": msg, + "session_token": sessionToken, + "pushedbutton_date": requestedDate + }; + } + + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + try { + http.Response response = await Request.instance.postRequest(path: path,body: body,headers: headers); + if (response.statusCode == 201) { + var body = jsonDecode(response.body); + SessionData newSessionData = SessionData.fromJson(body['data']); + sessionData = newSessionData; + } + + }on Error catch (e) { + throw (e.toString()); + } + return sessionData!; + } + + + Future checkAcknowledgement(String sessionToken) async { + String path = Url.instance.sosRequest(); + SessionData? sessionData; + try { + http.Response response = await Request.instance.getRequest(path: path,param:{"session_token":sessionToken} ); + if (response.statusCode == 200) { + var body = jsonDecode(response.body); + SessionData newSessionData = SessionData.fromJson(body['data'][0]); + + sessionData = newSessionData; + + } + } on Error + catch (e) { + throw (e.toString()); + } + return sessionData!; + } +} \ No newline at end of file diff --git a/lib/test_data.dart b/lib/test_data.dart new file mode 100644 index 0000000..566f446 --- /dev/null +++ b/lib/test_data.dart @@ -0,0 +1,106 @@ +import 'package:azlistview/azlistview.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:fluttericon/font_awesome5_icons.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; +import 'package:fluttericon/rpg_awesome_icons.dart'; +import 'package:unit2/model/login_data/user_info/role.dart'; + +List levels = ['Establishments', 'Office']; +List establishments = ['Provincial Government of Agusan del Norte']; +List checkPointAreas = [ + 'Agusan Up', + 'Bids and Awards Committee', + 'Cabadbaran District Hospital', + 'Commision on Audit' +]; + +final List genders = ["MALE", "FEMALE"]; +final List regions = [ + "Region I", + "Region II", + "Region III", + "Region IV", + "Region V" +]; +final List barangays = [ + "Ambago", + "Lingayao", + "Obrero", + "Bading", + "Limaha", + "Peqeno" +]; +final List puroks = [ + "Ambago", + "Lingayao", + "Obrero", + "Bading", + "Limaha", + "Peqeno" +]; + +final List municipalities = [ + "Buenavista", + "Butuan City", + "Carmen", + "Cabadbaran", + "Jabonga" +]; +final List provinces = [ + "Agusan del Norte", + "Agusan del Sur", + "Surigao del Norte", + "Surigao del Sur" +]; + +List addedPersons = [ + Person(name: "Nav", lastname: "Acuin"), + Person(name: "Jhonny", lastname: "Agoy"), + Person(name: "Philip", lastname: "Amaw"), + Person(name: "Jojo", lastname: "Asus"), + Person(name: "Naruto", lastname: "Acer"), + Person(name: "Agata", lastname: "Azarcon"), + Person(name: "Nav", lastname: "Amen"), + Person(name: "Cristine", lastname: "Albarina"), + Person(name: "Nav", lastname: "Zcuin"), + Person(name: "Jhonny", lastname: "Zgoy"), + Person(name: "Philip", lastname: "Zmaw"), + Person(name: "Jojo", lastname: "Zsus"), + Person(name: "Naruto", lastname: "Zcer"), + Person(name: "Agata", lastname: "Zzarcon"), + Person(name: "Nav", lastname: "Zmen"), + Person(name: "Cristine", lastname: "Zlbarina"), + Person(name: "Nav", lastname: "Bcuin"), + Person(name: "Jhonny", lastname: "Tgoy"), + Person(name: "Philip", lastname: "Smaw"), + Person(name: "Jojo", lastname: "Dsus"), + Person(name: "Naruto", lastname: "Fcer"), + Person(name: "Agata", lastname: "Ezarcon"), + Person(name: "Nav", lastname: "Cmen"), + Person(name: "Cristine", lastname: "Blbarina"), +]; + +class Person extends ISuspensionBean { + final String name; + final String lastname; + Person({required this.name, required this.lastname}); + + @override + String getSuspensionTag() { + return lastname[0]; + } +} + +// List roles = [ +// Roles(name: 'QR scanner', icon: FontAwesome.qrcode), +// Roles(name: "Security", icon: FontAwesome5.user_shield), +// Roles(name: "Establishment point person", icon: FontAwesome.building_filled), +// Roles(name: "Registration in charge", icon: FontAwesome.user_plus), +// Roles(name: 'Super admin', icon: FontAwesome5.user_lock), +// Roles(name: "Purok president", icon: FontAwesome5.user_tie), +// Roles(name: "Check point inchage", icon: FontAwesome5.hand_paper), +// Roles(name: "Health officer", icon: RpgAwesome.health_decrease), + +// ]; + + diff --git a/lib/theme-data.dart/box_shadow.dart b/lib/theme-data.dart/box_shadow.dart new file mode 100644 index 0000000..1df168d --- /dev/null +++ b/lib/theme-data.dart/box_shadow.dart @@ -0,0 +1,8 @@ + import 'package:flutter/material.dart'; + +BoxDecoration box1(){ + return const BoxDecoration( + boxShadow: [BoxShadow(color: Colors.black12,spreadRadius: 5,blurRadius: 5)] , + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(3))); +} \ No newline at end of file diff --git a/lib/theme-data.dart/btn-style.dart b/lib/theme-data.dart/btn-style.dart new file mode 100644 index 0000000..89f7e86 --- /dev/null +++ b/lib/theme-data.dart/btn-style.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +ButtonStyle mainBtnStyle(Color background, Color borderColor, Color overlay) { + return ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(background), + overlayColor: MaterialStateProperty.all(overlay), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25.0), + side: BorderSide( + width: 2, + color: borderColor, + )))); +} + +ButtonStyle secondaryBtnStyle( + Color background, Color borderColor, Color overlay) { + return ButtonStyle( + elevation: MaterialStateProperty.all(0), + backgroundColor: MaterialStateProperty.all(background), + overlayColor: MaterialStateProperty.all(overlay), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + side: BorderSide( + width: 2, + color: borderColor, + )))); +} diff --git a/lib/theme-data.dart/colors.dart b/lib/theme-data.dart/colors.dart new file mode 100644 index 0000000..6fe66a9 --- /dev/null +++ b/lib/theme-data.dart/colors.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +const primary = Color(0xff99191a); +const second = Color(0xffd92828); +const third = Color(0xffeb8b1e); +const fourth = Color(0xfff6c359); +const fifth = Color(0xfffdfefd); +const success = Color(0xffa5d6a7); +const success2 = Color(0xff66bb6a); +const primary2 = Color(0xff039be5); + +LinearGradient primaryGradient() { + return const LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + colors: [second, Color(0xffFF5151)]); +} diff --git a/lib/theme-data.dart/form-style.dart b/lib/theme-data.dart/form-style.dart new file mode 100644 index 0000000..22d1e79 --- /dev/null +++ b/lib/theme-data.dart/form-style.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +InputDecoration normalTextFieldStyle(String labelText, String hintText) { + return InputDecoration( + contentPadding: EdgeInsets.fromLTRB(12, 6, 6, 6), + floatingLabelBehavior: FloatingLabelBehavior.auto, + labelText: labelText, + labelStyle: const TextStyle(color: Colors.grey), + hintText: hintText, + hintStyle: const TextStyle( + color: Colors.grey, + ), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, + color: Colors.black87, + ), + borderRadius: BorderRadius.circular(5), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Colors.grey, + width: 1, + ), + borderRadius: BorderRadius.circular(5), + ), + disabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, + color: Colors.grey, + ), + borderRadius: BorderRadius.circular(5), + ), + errorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: Colors.red, + width: 1, + ), + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + focusedErrorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: Colors.red, + width: 1, + ), + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + filled: false); +} + + + +InputDecoration loginTextFieldStyle() { + return InputDecoration( + floatingLabelBehavior: FloatingLabelBehavior.never, + prefixIcon: const Icon( + Icons.person, + color: primary, + ), + labelText: 'Username', + hintText: 'Enter your username...', + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 2, + color: Colors.black87, + ), + borderRadius: BorderRadius.circular(5), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Colors.black87, + width: 1, + ), + borderRadius: BorderRadius.circular(5), + ), + errorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: Colors.red, + width: 2, + ), + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + focusedErrorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: Colors.red, + width: 2, + ), + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + filled: false); +} diff --git a/lib/theme-data.dart/text-styles.dart b/lib/theme-data.dart/text-styles.dart new file mode 100644 index 0000000..aa14dd8 --- /dev/null +++ b/lib/theme-data.dart/text-styles.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/utils/global.dart'; + +TextStyle titleTextStyle() { + return TextStyle( + fontSize: blockSizeVertical * 2.5, fontWeight: FontWeight.w500); +} + +TextStyle personInitials() { + return TextStyle( + fontSize: blockSizeVertical * 2, + fontWeight: FontWeight.w500, + color: Colors.white); +} + +TextStyle personInfo() { + return TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black54, + fontSize: blockSizeVertical * 2.5); +} diff --git a/lib/utils/alerts.dart b/lib/utils/alerts.dart new file mode 100644 index 0000000..b10f049 --- /dev/null +++ b/lib/utils/alerts.dart @@ -0,0 +1,109 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; + +confirmAlert(context, Function() yes,String title, String subtitle) { + AwesomeDialog( + context: context, + dialogType: DialogType.question, + borderSide: const BorderSide( + color: Colors.green, + width: 0, + ), + width: blockSizeHorizontal * 90, + buttonsBorderRadius: const BorderRadius.all( + Radius.circular(2), + ), + dismissOnTouchOutside: false, + dismissOnBackKeyPress: false, + // onDismissCallback: (type) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text('Dismissed by $type'), + // ), + // ); + // }, + headerAnimationLoop: false, + animType: AnimType.bottomSlide, + title: title, + desc: subtitle, + btnOkText: "Yes", + btnCancelText: "No", + showCloseIcon: false, + btnCancelOnPress: () {}, + btnOkOnPress: yes, + ).show(); +} + +confirmAlertWithCancel(context, Function() yes,Function() no,String title, String subtitle,) { + AwesomeDialog( + context: context, + dialogType: DialogType.question, + borderSide: const BorderSide( + color: Colors.green, + width: 0, + ), + width: blockSizeHorizontal * 90, + buttonsBorderRadius: const BorderRadius.all( + Radius.circular(2), + ), + dismissOnTouchOutside: false, + dismissOnBackKeyPress: false, + // onDismissCallback: (type) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text('Dismissed by $type'), + // ), + // ); + // }, + headerAnimationLoop: false, + animType: AnimType.bottomSlide, + title: title, + desc: subtitle, + btnOkText: "Yes", + btnCancelText: "No", + showCloseIcon: false, + btnCancelOnPress: no, + btnOkOnPress: yes, + ).show(); +} + + +errorAlert(context, title, description,Function() func) { + AwesomeDialog( + width: blockSizeHorizontal * 90, + context: context, + dialogType: DialogType.error, + animType: AnimType.scale, + headerAnimationLoop: false, + title: title, + desc: description, + btnOk: SizedBox(height: 50,child: ElevatedButton(onPressed:func, style: mainBtnStyle(primary, Colors.transparent, second), child: const Text("OK")), ) + ).show(); +} +successAlert(context, title, description,Function() func) { + AwesomeDialog( + width: blockSizeHorizontal * 90, + context: context, + dialogType: DialogType.success, + animType: AnimType.scale, + headerAnimationLoop: false, + title: title, + desc: description, + btnOk: SizedBox(height: 50,child: ElevatedButton(style: mainBtnStyle(success2, Colors.transparent, success), onPressed: func, child: const Text("OK")), ) + ).show(); +} +okAlert(context,title,description){ + AwesomeDialog( + width: blockSizeHorizontal * 90, + context: context, + dialogType: DialogType.error, + animType: AnimType.scale, + headerAnimationLoop: false, + title: title, + desc: description, + btnOkOnPress: () {}, + ).show(); +} diff --git a/lib/utils/app_router.dart b/lib/utils/app_router.dart new file mode 100644 index 0000000..27bc4a2 --- /dev/null +++ b/lib/utils/app_router.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unit2/bloc/passo/bulding/property_info/property_info_bloc.dart'; +import 'package:unit2/bloc/profile/profile_bloc.dart'; +import 'package:unit2/bloc/role/pass_check/pass_check_bloc.dart'; +import 'package:unit2/bloc/sos/sos_bloc.dart'; +import 'package:unit2/model/passo/property_info.dart'; +import 'package:unit2/screens/passo/passo_dashboard.dart'; +import 'package:unit2/screens/passo/building_home.dart'; +import 'package:unit2/screens/sos/index.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/dashboard.dart'; +import 'package:unit2/screens/unit2/homepage.dart/components/menu.dart'; +import 'package:unit2/screens/unit2/login/login.dart'; +import 'package:unit2/screens/unit2/roles/rbac/rbac.dart'; +import 'package:unit2/utils/global_context.dart'; +import '../bloc/rbac/rbac_bloc.dart'; +import '../bloc/user/user_bloc.dart'; +import '../screens/profile/profile.dart'; +import '../screens/unit2/basic-info/basic-info.dart'; +import '../screens/unit2/homepage.dart/components/drawer-screen.dart'; +import '../screens/unit2/login/qr_login.dart'; +import '../screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart'; + +class AppRouter { + Route onGenerateRoute(RouteSettings routeSettings) { + switch (routeSettings.name) { + case '/': + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(GetApkVersion()); + return MaterialPageRoute(builder: (_) { + return const UniT2Login(); + }); + case '/module-screen': + // BlocProvider.of( NavigationService.navigatorKey.currentContext!).add(LoadLoggedInUser()); + return MaterialPageRoute(builder: (_) { + return const DrawerScreen(); + }); + case '/basic-info': + return MaterialPageRoute(builder: (_) { + return const BasicInfo(); + }); + case '/qr-login': + return MaterialPageRoute(builder: (_) { + return const QRLogin(); + }); + case '/profile': + ProfileArguments arguments = + routeSettings.arguments as ProfileArguments; + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(LoadProfile(token: arguments.token, userID: arguments.userID)); + return MaterialPageRoute(builder: (_) { + return const ProfileInfo(); + }); + case '/sos': + return MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (_) => SosBloc()..add(LoadUserLocation()), + child: const SosScreen(), + ); + }); + case '/pass-check': + PassCheckArguments arguments = + routeSettings.arguments as PassCheckArguments; + return MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (context) => PassCheckBloc() + ..add(GetPassCheckAreas( + roleId: arguments.roleId, userId: arguments.userId)), + child: QRCodeScannerSettings( + roleId: arguments.roleId, + userId: arguments.userId, + ), + ); + }); + case '/passo-home': + return MaterialPageRoute(builder: (BuildContext context) { + return PassoDashBoard(); + }); + // BlocProvider.of( NavigationService.navigatorKey.currentContext!).add(LoadLoggedInUser()); + // return MaterialPageRoute(builder: (_) { + // return const PassoHome(); + // }); + case '/rbac': + return MaterialPageRoute(builder: (BuildContext context) { + return BlocProvider( + create: (_) => RbacBloc()..add(SetRbacScreen()), + child: const RBACScreen(), + ); + }); + default: + return MaterialPageRoute(builder: (context) { + return Container(); + }); + } + } +} diff --git a/lib/utils/attachment_services.dart b/lib/utils/attachment_services.dart new file mode 100644 index 0000000..d09e6ba --- /dev/null +++ b/lib/utils/attachment_services.dart @@ -0,0 +1,154 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/request_permission.dart'; +import 'package:unit2/utils/urls.dart'; + +import '../model/profile/attachment.dart'; +import 'package:http/http.dart' as http; + +class AttachmentServices { + static final AttachmentServices _instance = AttachmentServices(); + static AttachmentServices get instance => _instance; + + Future> getCategories() async { + List attachmentCategories = []; + String path = Url.instance.attachmentCategories(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + for (var cat in data['data']) { + AttachmentCategory newCat = AttachmentCategory.fromJson(cat); + attachmentCategories.add(newCat); + } + } + } catch (e) { + throw e.toString(); + } + return attachmentCategories; + } + + Future> attachment( + {required String categoryId, + required String module, + required List paths, + required String token, + required String profileId}) async { + String authtoken = "Token $token"; + Map headers = {'Authorization': authtoken}; + String path = Url.instance.attachments(); + Map? response = {}; + Map body = { + "attachment_category_id": categoryId.toString(), + "attachment_module": module.toString() + }; + + try { + var request = http.MultipartRequest( + 'POST', Uri.parse('https://${Url.instance.host()}$path$profileId/')); + request.fields.addAll(body); + request.headers.addAll(headers); + paths.forEach((element) async { + request.files + .add(await http.MultipartFile.fromPath('attachments', element)); + }); + + http.StreamedResponse res = await request.send(); + final steamResponse = await res.stream.bytesToString(); + Map data = jsonDecode(steamResponse); + if (res.statusCode == 201) { + response = data; + } else { + String message = data['response']['details']; + response.addAll({'message': message}); + response.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } + return response; + } + + Future deleteAttachment( + {required Attachment attachment, + required int moduleId, + required String profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.attachments()}$profileId/"; + Map? body; + body = { + "attachment_module": moduleId, + "attachments": [ + { + "id": attachment.id, + "created_at": attachment.createdAt?.toString(), + "source": attachment.source, + "filename": attachment.filename, + "category": { + "id": attachment.category?.id, + "subclass": { + "id": attachment.category?.subclass?.id, + "name": attachment.category?.subclass?.name, + "attachment_class": { + "id": attachment.category?.subclass?.attachmentClass?.id, + "name": attachment.category?.subclass?.attachmentClass?.name + } + }, + "description": attachment.category?.description + } + } + ] + }; + + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success!; + } + + Future downloadAttachment( + {required String filename, + required String source, + required String downLoadDir}) async { + bool success = false; + var dio = Dio(); + Response response; + try { + if (await requestPermission(Permission.storage)) { + response = await dio.download(source, "$downLoadDir/$filename"); + if (response.statusCode == 200) { + success = true; + } + } + return success; + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/utils/cpu_architecture.dart b/lib/utils/cpu_architecture.dart new file mode 100644 index 0000000..d0245da --- /dev/null +++ b/lib/utils/cpu_architecture.dart @@ -0,0 +1,44 @@ + import 'dart:async'; +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:unit2/model/login_data/version_info.dart'; +import 'package:system_info2/system_info2.dart'; +Future getCPUArchitecture() async { + String downloadURL = ""; + String cpuArchitecture = SysInfo.kernelArchitecture; + VersionInfo? apkVersion; + Dio dio = Dio(); + const String apkUrl = 'https://unitylb1.agusandelnorte.gov.ph/unit2/api/sys/apk_version/latest/'; + try { + Response response = await dio.get(apkUrl, + options: Options( + receiveTimeout: 20000, + receiveDataWhenStatusError: true, + responseType: ResponseType.json, + followRedirects: false, + validateStatus: (status) { + return status! < 500; + })); + if (response.statusCode == 200) { + apkVersion = VersionInfo.fromJson(response.data['data']); + if (cpuArchitecture.toUpperCase() == 'ARM' || + cpuArchitecture.toUpperCase() == 'MIPS') { + downloadURL = apkVersion.armeabiv7aDownloadUrl!; + } else if (cpuArchitecture.toUpperCase() == 'I686' || + cpuArchitecture.toUpperCase() == 'UNKNOWN' || + cpuArchitecture.toUpperCase() == 'X86_64') { + downloadURL = apkVersion.x8664DownloadUrl!; + } else if (cpuArchitecture.toUpperCase() == 'AARCH64') { + downloadURL = apkVersion.arm64v8aDownloadUrl!; + } + } + } on TimeoutException catch (_) { + throw TimeoutException("Connection timeout"); + } on SocketException catch (_) { + throw const SocketException("Connection timeout"); + } on DioError catch (_) { + throw DioErrorType.connectTimeout; + } + return downloadURL; + } \ No newline at end of file diff --git a/lib/utils/custom_dropdown_button.dart b/lib/utils/custom_dropdown_button.dart new file mode 100644 index 0000000..308c72b --- /dev/null +++ b/lib/utils/custom_dropdown_button.dart @@ -0,0 +1,149 @@ +// import 'package:dropdown_button2/dropdown_button2.dart'; +// import 'package:flutter/material.dart'; + +// class CustomDropdownButton2 extends StatelessWidget { +// final String hint; +// final String? value; +// final List dropdownItems; +// final ValueChanged? onChanged; +// final DropdownButtonBuilder? selectedItemBuilder; +// final Alignment? hintAlignment; +// final Alignment? valueAlignment; +// final double? buttonHeight, buttonWidth; +// final EdgeInsetsGeometry? buttonPadding; +// final BoxDecoration? buttonDecoration; +// final int? buttonElevation; +// final Widget? icon; +// final double? iconSize; +// final Color? iconEnabledColor; +// final Color? iconDisabledColor; +// final double? itemHeight; +// final EdgeInsetsGeometry? itemPadding; +// final double? dropdownHeight, dropdownWidth; +// final EdgeInsetsGeometry? dropdownPadding; +// final BoxDecoration? dropdownDecoration; +// final int? dropdownElevation; +// final Radius? scrollbarRadius; +// final double? scrollbarThickness; +// final bool? scrollbarAlwaysShow; +// final Offset offset; + +// const CustomDropdownButton2({ +// required this.hint, +// required this.value, +// required this.dropdownItems, +// required this.onChanged, +// this.selectedItemBuilder, +// this.hintAlignment, +// this.valueAlignment, +// this.buttonHeight, +// this.buttonWidth, +// this.buttonPadding, +// this.buttonDecoration, +// this.buttonElevation, +// this.icon, +// this.iconSize, +// this.iconEnabledColor, +// this.iconDisabledColor, +// this.itemHeight, +// this.itemPadding, +// this.dropdownHeight, +// this.dropdownWidth, +// this.dropdownPadding, +// this.dropdownDecoration, +// this.dropdownElevation, +// this.scrollbarRadius, +// this.scrollbarThickness, +// this.scrollbarAlwaysShow, +// this.offset = const Offset(0, 0), +// Key? key, +// }) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// return DropdownButtonHideUnderline( +// child: DropdownButton2( +// //To avoid long text overflowing. +// isExpanded: true, +// hint: Container( +// alignment: hintAlignment, +// child: Text( +// hint, +// overflow: TextOverflow.ellipsis, +// maxLines: 1, +// style: TextStyle( +// fontSize: 14, +// color: Theme.of(context).hintColor, +// ), +// ), +// ), +// value: value, +// items: dropdownItems +// .map((item) => DropdownMenuItem( +// value: item, +// child: Container( +// alignment: valueAlignment, +// child: Text( +// item, +// overflow: TextOverflow.ellipsis, +// maxLines: 1, +// style: const TextStyle( +// fontSize: 14, +// ), +// ), +// ), +// )) +// .toList(), +// onChanged: onChanged, +// selectedItemBuilder: selectedItemBuilder, +// buttonStyleData: ButtonStyleData( +// height: buttonHeight ?? 40, +// width: buttonWidth ?? 140, +// padding: buttonPadding ?? const EdgeInsets.only(left: 14, right: 14), +// decoration: buttonDecoration ?? +// BoxDecoration( +// borderRadius: BorderRadius.circular(14), +// border: Border.all( +// color: Colors.black45, +// ), +// ), +// elevation: buttonElevation, +// ), +// iconStyleData: IconStyleData( +// icon: icon ?? const Icon(Icons.arrow_forward_ios_outlined), +// iconSize: iconSize ?? 12, +// iconEnabledColor: iconEnabledColor, +// iconDisabledColor: iconDisabledColor, +// ), +// dropdownStyleData: DropdownStyleData( +// //Max height for the dropdown menu & becoming scrollable if there are more items. If you pass Null it will take max height possible for the items. +// maxHeight: dropdownHeight ?? 200, +// width: dropdownWidth ?? 140, +// padding: dropdownPadding, +// decoration: dropdownDecoration ?? +// BoxDecoration( +// borderRadius: BorderRadius.circular(14), +// ), +// elevation: dropdownElevation ?? 8, +// //Null or Offset(0, 0) will open just under the button. You can edit as you want. +// offset: offset, +// //Default is false to show menu below button +// isOverButton: false, +// scrollbarTheme: ScrollbarThemeData( +// radius: scrollbarRadius ?? const Radius.circular(40), +// thickness: scrollbarThickness != null +// ? MaterialStateProperty.all(scrollbarThickness!) +// : null, +// thumbVisibility: scrollbarAlwaysShow != null +// ? MaterialStateProperty.all(scrollbarAlwaysShow!) +// : null, +// ), +// ), +// menuItemStyleData: MenuItemStyleData( +// height: itemHeight ?? 40, +// padding: itemPadding ?? const EdgeInsets.only(left: 14, right: 14), +// ), +// ), +// ); +// } +// } \ No newline at end of file diff --git a/lib/utils/formatters.dart b/lib/utils/formatters.dart new file mode 100644 index 0000000..4db4cd8 --- /dev/null +++ b/lib/utils/formatters.dart @@ -0,0 +1,24 @@ + import 'package:flutter/services.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; + +var mobileFormatter = MaskTextInputFormatter( + mask: "+63 (###) ###-####", + filter: {"#": RegExp(r"^[1-9][0-9]*$")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + var landLineFormatter = MaskTextInputFormatter( + mask: "(###) ###-###", + filter: {"#": RegExp(r"^[0-9]")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + class UpperCaseTextFormatter extends TextInputFormatter { + @override + TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + return TextEditingValue( + text: newValue.text.toUpperCase(), + selection: newValue.selection, + ); + } +} \ No newline at end of file diff --git a/lib/utils/global.dart b/lib/utils/global.dart new file mode 100644 index 0000000..0b427f7 --- /dev/null +++ b/lib/utils/global.dart @@ -0,0 +1,19 @@ +import 'package:hive/hive.dart'; + +double screenWidth = 0; +double screenHeight = 0; +double blockSizeHorizontal = 0; +double blockSizeVertical = 0; +double safeAreaHorizontal = 0; +double safeAreaVertical = 0; +double safeBlockHorizontal = 0; +double safeBlockVertical = 0; + +const xClientKey = "unitK3CQaXiWlPReDsBzmmwBZPd9Re1z"; +const xClientSecret = "unitcYqAN7GGalyz"; + + + +//// hive boxes +Box? CREDENTIALS; +Box? SOS; \ No newline at end of file diff --git a/lib/utils/global_context.dart b/lib/utils/global_context.dart new file mode 100644 index 0000000..6b7b74d --- /dev/null +++ b/lib/utils/global_context.dart @@ -0,0 +1,6 @@ +import 'package:flutter/material.dart'; + +class NavigationService { + static GlobalKey navigatorKey = + GlobalKey(); +} diff --git a/lib/utils/internet_time_out.dart b/lib/utils/internet_time_out.dart new file mode 100644 index 0000000..b4a0359 --- /dev/null +++ b/lib/utils/internet_time_out.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; + +import '../theme-data.dart/colors.dart'; + +class TimeOutError extends StatelessWidget { + const TimeOutError({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/timeout.svg', + height: 200.0, + width: 200.0, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 25, + ), + const Text( + 'Connection Timeout! Pls check your internet connectivity.', + textAlign: TextAlign.center,), + + const SizedBox( + height: 25, + ), + SizedBox( + height: 50, + child: ElevatedButton.icon( + style: mainBtnStyle( + primary, Colors.transparent, primary.withOpacity(.5)), + onPressed:(){ + }, + icon: const Icon( + Icons.refresh, + color: Colors.white, + ), + label: const Text( + "try again", + style: TextStyle(color: Colors.white), + )), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/utils/location_utilities.dart b/lib/utils/location_utilities.dart new file mode 100644 index 0000000..e52c10b --- /dev/null +++ b/lib/utils/location_utilities.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/location/city.dart'; +import 'package:unit2/model/location/country.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/location/provinces.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import '../model/location/region.dart'; + +class LocationUtils { + static final LocationUtils _instance = LocationUtils(); + static LocationUtils get instance => _instance; + + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + + Future> getCountries() async { + List countries = []; + String path = Url.instance.getCounties(); + + try{ + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var country) { + Country newCOuntry = Country.fromJson(country); + countries.add(newCOuntry); + }); + } + } + }catch(e){ + throw(e.toString()); + } + return countries; + } + + Future> getRegions() async { + List regions = []; + String path = Url.instance.getRegions(); + + try{ + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var region) { + Region newRegion = Region.fromJson(region); + regions.add(newRegion); + }); + } + } + }catch(e){ + throw(e.toString()); + } + return regions; + } + + Future> getProvinces({required String regionCode}) async { + List provinces = []; + String path = Url.instance.getProvinces() + regionCode; + + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var province) { + Province newProvince = Province.fromJson(province); + provinces.add(newProvince); + }); + } + } catch (e) { + throw (e.toString()); + } + return provinces; + } + + Future> getCities({required String code}) async { + List cities = []; + String path = Url.instance.getCities() + code; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var city) { + CityMunicipality cityMun = CityMunicipality.fromJson(city); + cities.add(cityMun); + }); + } + } catch (e) { + throw (e.toString()); + } + return cities; + } + + Future> getBarangay({required String code}) async { + List barangays = []; + String path = Url.instance.getBarangays() + code; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var city) { + Barangay barangay = Barangay.fromJson(city); + barangays.add(barangay); + }); + } + } catch (e) { + throw (e.toString()); + } + return barangays; + } + Future>getAddressCategory()async{ + List categories = []; + String path = Url.instance.getAddressCategory(); + try{ + http.Response response = await Request.instance.getRequest(path: path,param: {},headers:headers ); + Map data = jsonDecode(response.body); + if(data['data'] != null){ + data['data'].forEach((var cat){ + categories.add(AddressCategory.fromJson(cat)); + }); + } + categories; + return categories; + }catch(e){ + throw e.toString(); + } + } + + +} diff --git a/lib/utils/profile_utilities.dart b/lib/utils/profile_utilities.dart new file mode 100644 index 0000000..929ac1a --- /dev/null +++ b/lib/utils/profile_utilities.dart @@ -0,0 +1,174 @@ +import 'dart:convert'; + +import 'package:unit2/model/location/country.dart'; +import 'package:http/http.dart' as http; +import 'package:unit2/model/location/region.dart'; +import 'package:unit2/model/utils/eligibility.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; + +import '../model/profile/basic_information/contact_information.dart'; +import '../model/profile/family_backround.dart'; +import '../model/utils/agency.dart'; +import '../model/utils/category.dart'; +import '../model/utils/position.dart'; + +class ProfileUtilities { + static final ProfileUtilities _instance = ProfileUtilities(); + static ProfileUtilities get instance => _instance; + + Future> getEligibilities() async { + List eligibilities = []; + String path = Url.instance.eligibilities(); + + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var eligibility) { + Eligibility newEligibilities = Eligibility.fromJson(eligibility); + eligibilities.add(newEligibilities); + }); + } + } + } catch (e) { + throw (e.toString()); + } + return eligibilities; + } + +////get agency position + Future> getAgencyPosition() async { + List agencyPositions = []; + String path = Url.instance.getPositions(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var agencyPosition) { + PositionTitle position = PositionTitle.fromJson(agencyPosition); + agencyPositions.add(position); + }); + } + } + } catch (e) { + throw (e.toString()); + } + return agencyPositions; + } + + ////get agencies + Future> getAgecies() async { + List agencies = []; + String path = Url.instance.getAgencies(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(path: path, param: {}, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var agency) { + Agency newAgency = Agency.fromJson(agency); + agencies.add(newAgency); + }); + } + } + } catch (e) { + throw e.toString(); + } + return agencies; + } + +////get agency category + Future> agencyCategory() async { + List agencyCategory = []; + String path = Url.instance.getAgencyCategory(); + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + data['data'].forEach((var agency) { + Category category = Category.fromJson(agency); + agencyCategory.add(category); + }); + } + } + } catch (e) { + throw e.toString(); + } + return agencyCategory; + } + +//// get service type + Future> getServiceType() async { + List serviceTypes = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + String path = Url.instance.getServiceTypes(); + + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var element in data['data']) { + ServiceType newServiceType = ServiceType.fromJson(element); + serviceTypes.add(newServiceType); + } + } + } + } catch (e) { + throw e.toString(); + } + return serviceTypes; + } + + //// get relationship type + Future> getRelationshipType() async { + List relationshipTypes= []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + String path = Url.instance.getRelationshipTypes(); + + try { + http.Response response = await Request.instance + .getRequest(param: {}, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var element in data['data']) { + Relationship relationship = Relationship.fromJson(element); + if(relationship.category=="personal reference"){ + relationshipTypes.add(relationship); + } + + } + } + } + } catch (e) { + throw e.toString(); + } + return relationshipTypes; + } +} diff --git a/lib/utils/qr_scanner.dart b/lib/utils/qr_scanner.dart new file mode 100644 index 0000000..003161d --- /dev/null +++ b/lib/utils/qr_scanner.dart @@ -0,0 +1,17 @@ +import 'package:barcode_scan2/barcode_scan2.dart'; +import 'package:unit2/utils/scanner.dart'; + +Future qrScanner() async { + String? result; + try { + ScanResult afterScan = await QRCodeBarCodeScanner.instance.scanner(); + if (afterScan.type == ResultType.Barcode) { + result = afterScan.rawContent; + return result; + } + } catch (e) { + throw e.toString(); + } + + return null; +} diff --git a/lib/utils/request.dart b/lib/utils/request.dart new file mode 100644 index 0000000..d75fcdc --- /dev/null +++ b/lib/utils/request.dart @@ -0,0 +1,225 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:http/http.dart'; +import 'package:unit2/utils/text_container.dart'; +import 'package:unit2/utils/urls.dart'; + +class Request { + static final Request _instance = Request(); + static Request get instance => _instance; + int requestTimeout = 25; + String host = Url.instance.host(); + + Future getRequest( + {String? path, + Map? headers, + Map? param}) async { + Response response; + try { + response = await get(Uri.https(host, path!, param), headers: headers) + .timeout(Duration(seconds: requestTimeout)); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + debugPrint("get request error: $e"); + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (onError); + } + return response; + } + + Future postRequest( + {String? path, + Map? headers, + Map? body, + Map? param}) async { + Response response; + try { + response = await post(Uri.https(host, path!, param), + headers: headers, body: jsonEncode(body)) + .timeout(Duration(seconds: requestTimeout)); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + debugPrint("post request error: $e"); + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (e.toString()); + } + return response; + } + + Future putRequest( + {required String path, + required Map? headers, + required Map? body, + required Map? param}) async { + Response response; + try { + response = await put(Uri.https(host, path, param), + headers: headers, body: jsonEncode(body)); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + debugPrint("post request error: $e"); + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (e.toString()); + } + return response; + } + + Future patch( + {required String path, + required Map? headers, + required Map? body, + required Map? param}) async { + Response response; + try { + response = await patch( + path: host + path, headers: headers, body: body, param: param); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + debugPrint("post request error: $e"); + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (e.toString()); + } + return response; + } + + Future deleteRequest( + {required String path, + required Map? headers, + required Map? body, + required Map? param}) async { + Response response; + try { + response = await delete(Uri.https(host, path, param), + headers: headers, body: jsonEncode(body)) + .timeout(Duration(seconds: requestTimeout)); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (e.toString()); + } + return response; + } +} diff --git a/lib/utils/request_permission.dart b/lib/utils/request_permission.dart new file mode 100644 index 0000000..1d3355c --- /dev/null +++ b/lib/utils/request_permission.dart @@ -0,0 +1,14 @@ + +import 'package:permission_handler/permission_handler.dart'; + +Future requestPermission(Permission permission) async { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result == PermissionStatus.granted) { + return true; + } + } + return false; +} \ No newline at end of file diff --git a/lib/utils/router.dart b/lib/utils/router.dart new file mode 100644 index 0000000..0f7fa3a --- /dev/null +++ b/lib/utils/router.dart @@ -0,0 +1,78 @@ +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter_bloc/flutter_bloc.dart'; +// import 'package:go_router/go_router.dart'; +// import 'package:unit2/bloc/bloc/user_bloc.dart'; +// import 'package:unit2/model/login_data/user_info/user_data.dart'; +// import 'package:unit2/screens/unit2/login/qr_login.dart'; +// import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/scan.dart'; +// import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart'; +// import 'package:unit2/screens/unit2/signature/signature_pad.dart'; +// import 'package:unit2/utils/global_context.dart'; +// import 'package:unit2/utils/scanner.dart'; +// import '../screens/docsms/components/doc_info_tile.dart'; +// import '../screens/docsms/request_receipt.dart'; +// import '../screens/sos/add_mobile.dart'; +// import '../screens/sos/request_sos.dart'; +// import '../screens/unit2/login/login.dart'; +// import '../screens/unit2/homepage.dart/components/drawer-screen.dart'; +// import '../screens/unit2/profile/profile.dart'; +// import '../screens/unit2/roles/registration_in_charge/home.dart'; + +// final GoRouter goRouter = GoRouter(routes: [ +// GoRoute( +// path: '/', +// name: 'login', +// builder: (context, state) { +// return BlocProvider( +// create: (context) => UserBloc()..add(GetApkVersion()), +// child: const UniT2Login(), +// ); +// }, +// routes: [ +// // GoRoute( +// // name: 'qr-login', +// // path: 'qr-login', +// // builder: ((context, state) => const QRLogin())), +// GoRoute( +// name: 'home', +// path: 'home', +// builder: (context, state) { +// UserData userData = state.extra as UserData; +// return BlocProvider.value( +// value: UserBloc()..add((LoadLoggedInUser(userData: userData))), +// child: const DrawerScreen(), +// ); +// }, +// routes: [ +// GoRoute( +// name: 'profile', +// path: 'profile', +// builder: (context, state) { +// UserData userData = state.extra as UserData; +// return BlocProvider.value( +// value: UserBloc() +// ..add((LoadLoggedInUser(userData: userData))), +// child: const Profile(), +// ); +// }, +// routes: [ +// GoRoute( +// name: 'signature', +// path: 'signature', +// builder: (context, state) => const SignaturePad(), +// ) +// ]) +// ]), +// GoRoute( +// name: 'add-mobile', +// path: 'add-moble', +// builder: (context, state) => AddMobile(), +// routes: [ +// GoRoute( +// name: 'request-sos', +// path: 'request-sos', +// builder: (context, state) => const RequestSOS(), +// ) +// ]), +// ]), +// ]); diff --git a/lib/utils/scanner.dart b/lib/utils/scanner.dart new file mode 100644 index 0000000..25501f6 --- /dev/null +++ b/lib/utils/scanner.dart @@ -0,0 +1,36 @@ +import 'package:barcode_scan2/barcode_scan2.dart'; + +class QRCodeBarCodeScanner { + static final QRCodeBarCodeScanner _instance = QRCodeBarCodeScanner(); + static QRCodeBarCodeScanner get instance => _instance; + final _selectedCamera = -1; + final bool _useAutoFocus = true; + static final _possibleFormats = BarcodeFormat.values.toList() + ..removeWhere((e) => e == BarcodeFormat.unknown); + ScanResult scanResult = ScanResult(); + + List selectedFormats = [..._possibleFormats]; + + Future scanner() async { + ScanOptions options = ScanOptions( + strings: { + "cancel": "Back", + "flash_on": "Flash on", + "flash_off": "Flash off", + }, + restrictFormat: selectedFormats, + useCamera: _selectedCamera, +// autoEnableFlash: _autoEnableFlash, + android: AndroidOptions( +// aspectTolerance: _aspectTolerance, + useAutoFocus: _useAutoFocus, + ), + ); + try { + scanResult = await BarcodeScanner.scan(options: options); + } on Error catch (e) { + throw (e.toString()); + } + return scanResult; + } +} diff --git a/lib/utils/screen_info.dart b/lib/utils/screen_info.dart new file mode 100644 index 0000000..a536655 --- /dev/null +++ b/lib/utils/screen_info.dart @@ -0,0 +1,9 @@ +import 'package:unit2/utils/global.dart'; + +bool isMobile() { + if (screenWidth > 500.00) { + return false; + } else { + return true; + } +} diff --git a/lib/utils/text_container.dart b/lib/utils/text_container.dart new file mode 100644 index 0000000..79be6de --- /dev/null +++ b/lib/utils/text_container.dart @@ -0,0 +1,118 @@ +const String addMobile = "Enter your mobile number(s)"; +const String addMobileCaption = + "These mobile numbers will be used to contact you if you request an emergency response. Please provide at least one active number"; +const String mobileNumberRequired = "You must add atleast one mobile"; +const String numericValidator = "Please a number only"; +const String mobile1 = "Mobile number 1"; +const String mobile2 = "Mobile number 2"; +const String currentLocation = "Your current location"; +const String noModule = "No Module Assign"; +const String noModuleSubTitle = + "Please contact the admin if you want to access a module."; +const String submit = "SUBMIT"; +const String login = "LOGIN"; +const String sOSTitle = "Request SOS"; +const String sOSReceivedMessage = + "your SOS request has been received. Please wait for respondent's acknowledgement."; +const String unit2ModuleScreen = "uniT Dashboard"; +const String welcome = "Welcome to!"; +const String unitApp = 'uniT-App'; +const String loginToContinue = "Please login to continue."; +const String loginViaQr = "Login via QR code"; +const String emergencyReponseLabel = " Request Emergency Response "; +const String requestSOS = "Request SOS"; +const String qrScannerTitle = "QR-Code Scanner"; +const String establishment = "Establishment"; +const String checkpointArea = "Checkpoint Area"; +const String scanMode = 'Scan Mode'; +const String registrationInChargeTitle = "Registration In Charge"; +const String basicInformation = "Basic Information"; +const String address = "Address"; +const String syncTitle = "Sync Data"; +const String syncSubTittle = "Press Sync button to get latest data available"; +const String syncNow = "SYNC NOW"; +const String documentId = "Document ID"; +const String documentTitle = "Document Title"; +const String documentSubject = "Document Subject"; +const String documentType = "Document Type"; +const String registerToContinue = "Create your password to register"; +const String sourceRemarks = "Source Remarks"; +const String remarksRequired = "Remarks is required"; +const String enterRemarks = "Enter your remarks"; +const String departmentRequired = "Department is required"; +const String substationRequired = "Substation is required"; +const String requestAutoReceipt = "Request Auto Receipt"; +const String messageRequired = "Message is required"; +const String sosMessage = "SOS message ..."; +const String sosReceived = "SOS Received!"; +const String cancelRequest = "Cancel Request"; +const String usernameRequired = "Username is required"; +const String passwordRequired = "Password is required"; +const String enterPassword = "Enter Password ..."; +const String confirmPassword = "Confirm Password"; +const String enterConfirmPassword = "Enter Confirm Password ..."; +const String register = "Register"; +const String signature = "Signature pad"; +const String tapToScanQR = "TAP TO SCAN QR CODE"; +const String incoming = "INCOMING"; +const String setQRScannerSettings = "Set QR Scanner Settings"; +const String includeOtherInputs = "Include other inputs?"; +const String includeOtherInputsSubTitle = + "Inputs such as body temperature, etc."; +const String incomingORoutgoing = "Incoming or Outgoing?"; +const String incomingORoutgoingSubTitle = + "incoming for entrance outgoing for exit."; +const String fieldIsRequired = "This field is required"; +const String selectLevel = "Select level"; +const String selectEstablishment = "Select Establishment"; +const String timeoutError = "Internet timeout! Please Check your connection"; +const String formatError = "Invalid Error"; +const String httpError = "Error getting requested data"; +const String onError = "Something went wrong! Please try again."; +const String adressScreenTitle = "Addresses"; +const String citizenshipScreenTitle = "Citizenship"; +const String contactScreenTitle = "Contact Information"; +const String identificationScreenTitle = "Identifications"; +const String idNumberText = "ID number"; +const String privateText = 'private'; +const String governmentText = "government"; +const String primaryInformationScreenTitle = "Primary Information"; +const String lastname = "lastname"; +const String firstname = "firstname"; +const String middlename = "middlename"; +const String extensionName = 'extension-name'; +const String birthDat = 'bday'; +const String sex = 'sex'; +const String bloodType = 'bloodtype'; +const String civilStatus = 'civil-status'; +const String gender = 'gender'; +const String height = 'height'; +const String width = 'width'; +const String prefixSuffix = 'prefix&suffix'; +const String nonAcademicRecTitle = "Non Academic Recognition"; +const String orgMembershipTitle = "Organization Membership"; +const String skillAndHobbiesTitle = "Skills and Hobbies"; +const String educationScreenTitle = "Educational Background"; +const String honorsText = 'Honors'; +const String elibilityScreenTitle = "Eligibility"; +const String licenseNumber = "LicenseNumber"; +const String rating = "Rating"; +const String familyBackgroundScreenTitle = "Family Background"; +const String fatherText = "Father"; +const String fullname = "Full name"; +const String incaseOfEmergency = "Incase of emergency"; +const String motherText = 'Mother'; +const String spouseText = "Spouse"; +const String childrenText = "Children"; +const String otherRelatedText = "Other related person"; +const String learningAndDevelopmentScreenTitle = "Learning and Development"; +const String duration = "Duration"; +const String type = "Type"; +const String referencesScreenTitle = "Personal References"; +const String mobileOrPhone = "phone / mobile number"; +const String voluntaryScreenTitle = "Voluntary Work & Civic"; +const String numberOfHours = "Worked/Involved for"; +const String workHistoryScreenTitle = "Work History"; +const String present = "present"; +// + diff --git a/lib/utils/url_launcher_file_downloader.dart b/lib/utils/url_launcher_file_downloader.dart new file mode 100644 index 0000000..ac3155f --- /dev/null +++ b/lib/utils/url_launcher_file_downloader.dart @@ -0,0 +1,16 @@ +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + + Future launchInBrowser(String url) async { + final UrlLauncherPlatform launcher = UrlLauncherPlatform.instance; + if (!await launcher.launch( + url, + useSafariVC: false, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: {}, + )) { + throw Exception('Could not launch $url'); + } + } \ No newline at end of file diff --git a/lib/utils/urls.dart b/lib/utils/urls.dart new file mode 100644 index 0000000..20385fe --- /dev/null +++ b/lib/utils/urls.dart @@ -0,0 +1,461 @@ +class Url { + static final Url _instance = Url(); + + static Url get instance => _instance; + + String host() { + // return '192.168.10.183:3000'; + return 'agusandelnorte.gov.ph'; + // return "192.168.10.219:3000"; + // return "192.168.10.241"; + // return "192.168.10.221:3004"; + // return "playweb.agusandelnorte.gov.ph"; + // return 'devapi.agusandelnorte.gov.ph:3004'; + } + + String prefixHost() { + return "https"; + // return "http"; + } + + String authentication() { + return '/api/account/auth/login/'; + } + + String profileInformation() { + return 'api/jobnet_app/profile/pds/'; + } + + + String latestApk() { + return "/api/system_app/apk_version/latest"; + } + + ////SOS paths + String sosRequest() { + return "/api/sos_app/sos_request/"; + } + + //// DOCSMS paths + String getDocument() { + return "/api/web_app/public/document_viewer/"; + } + +////ELIGIBILITIES PATHS + String eligibilities() { + return "/api/jobnet_app/eligibilities/"; + } + + String getEligibilities() { + return "/api/jobnet_app/profile/pds/eligibility/"; + } + + String addEligibility() { + return "/api/jobnet_app/profile/pds/eligibility/"; + } + + String deleteEligibility() { + return "/api/jobnet_app/profile/pds/eligibility/"; + } + + String updateEligibility() { + return "/api/jobnet_app/profile/pds/eligibility/"; + } + +//// work history paths + String workhistory() { + return "/api/jobnet_app/profile/pds/work_experience/"; + } + + String deleteWorkHistory() { + return "/api/jobnet_app/profile/pds/work/"; + } + + String getPositions() { + return "/api/jobnet_app/positions/"; + } + + String getAgencies() { + return "/api/jobnet_app/agencies/"; + } + + String getAgencyCategory() { + return "api/jobnet_app/agency_categories/"; + } + + String identifications() { + return "/api/jobnet_app/profile/pds/basic/identification/"; + } + +////educational background paths + String educationalBackground() { + return "/api/jobnet_app/profile/pds/education/"; + } + + String getSchools() { + return "/api/jobnet_app/schools/"; + } + + String getPrograms() { + return "api/jobnet_app/education_programs/"; + } + + String getHonors() { + return "/api/jobnet_app/honors"; + } + +//// learning and development paths + + String learningAndDevelopments() { + return "api/jobnet_app/profile/pds/learning_development/"; + } + + String conductedTrainings() { + return "api/jobnet_app/conducted_trainings/"; + } + + String learningAndDevelopmentType() { + return "api/jobnet_app/learning_development/"; + } + + String learningAndDevelopmentTopics() { + return "api/jobnet_app/training_topics/"; + } + +//// references paths + String reference() { + return "/api/jobnet_app/profile/pds/personal_reference/"; + } + +////voluntary works + String getVoluntaryWorks() { + return "/api/jobnet_app/profile/pds/voluntary_work/"; + } + +//// skills hobbies + String skillsHobbies() { + return "/api/jobnet_app/profile/pds/other/skill_hobby/"; + } + + String getAllSkillsHobbies() { + return "/api/jobnet_app/skill_hobby/"; + } + +//// orgmemberships + String getOrgMemberShips() { + return "/api/jobnet_app/profile/pds/other/org_membership/"; + } + +////non academic recognition + String getNonAcademicRecognition() { + return "/api/jobnet_app/profile/pds/other/non_acad_recognition/"; + } + +////citizenship + String citizenship() { + return "/api/jobnet_app/profile/pds/basic/citizenship/"; + } + +////family paths + String getFamilies() { + return "/api/jobnet_app/profile/pds/family/"; + } + + String addEmergency() { + return "/api/profile_app/person_emergency/"; + } + + String getRelationshipTypes() { + return "/api/jobnet_app/relationship_types"; + } + + String updatePersonalInfor() { + return "/api/jobnet_app/profile/pds/basic/personal/"; + } + +//// contacts path + String getServiceTypes() { + return "/api/jobnet_app/comm_service_type/"; + } + + String attachments() { + return "/api/jobnet_app/profile/attachment/"; + } + +//// address path + String addressPath() { + return "/api/jobnet_app/profile/pds/basic/address/"; + } + + String contactPath() { + return "/api/jobnet_app/profile/pds/basic/contact/"; + } + + String getCommunicationProvider() { + return "/api/jobnet_app/comm_services/"; + } + + String deleteContact() { + return "/api/jobnet_app/profile/pds/basic/contact/"; + } + +////profile other info + String getReligions() { + return "/api/profile_app/religion/"; + } + + String getEthnicity() { + return "/api/profile_app/ethnicity/"; + } + + String getDisability() { + return "api/profile_app/disability/"; + } + + String getIndigency() { + return "/api/profile_app/indigenous/"; + } + + String getGenders() { + return "/api/profile_app/gender/"; + } + +/////ROLES +// pass check + String getAssignAreas() { + return "/api/account/auth/assigned_role_area/"; + } + + String getPasserInfo() { + return "/api/profile_app/person_basicinfo/"; + } + + String postLogs() { + return "/api/unit2_app/monitoring/pass_check/"; + } + + String passCheck() { + return "/api/unit2_app/monitoring/pass_check"; + } +////rbac + + String getRbacRoles() { + return "/api/account/auth/roles/"; + } + + String searchUsers() { + return "/api/hrms_app/employee_details/"; + } + + String assignRbac() { + return "/api/account/auth/rbac/"; + } + +////rbac operations + String getRbacOperations() { + return "/api/account/auth/operations/"; + } + + String getPersmissions() { + return "/api/account/auth/permissionrbac/"; + } + + String getRoles() { + return "/api/account/auth/roles/"; + } + + String getOperations() { + return "/api/account/auth/operations/"; + } + + String getModules() { + return "/api/account/auth/modules/"; + } + + String getObject() { + return "/api/account/auth/objects/"; + } + + String getModuleObjects() { + return "/api/account/auth/moduleobject/"; + } + + String agencies() { + return "/api/jobnet_app/agencies/"; + } + + String postAgencies() { + return "/api/profile_app/agencies/"; + } + + String getRoleModules() { + return "/api/account/auth/rolemodules/"; + } + + String getRolesUnder() { + return "/api/account/auth/rolesunder/"; + } + + String getRoleExtend() { + return "/api/account/auth/rolesextend/"; + } + + String getStation() { + return "/api/hrms_app/station/"; + } + + String postStation() { + return "/api/hrms_app/stations/"; + } + + String getRoleAssignment() { + return "api/account/auth/role_assignment/"; + } + + String getStationType() { + return "/api/hrms_app/station_type/"; + } + + String getPositionTitle() { + return "/api/hrms_app/position_title/"; + } + + //// location utils path + String getCounties() { + return "/api/jobnet_app/countries/"; + } + + String getRegions() { + return "/api/web_app/location/region/"; + } + + String getProvinces() { + return "api/web_app/location/province/"; + } + + String getCities() { + return "/api/web_app/location/citymun/"; + } + + String getBarangays() { + return "/api/web_app/location/barangay/"; + } + + String getAddressCategory() { + return "/api/jobnet_app/address_categories/"; + } + + ////passo path + + String additionalItems() { + return "/api/rptass_app/additional_items/"; + } + + String generalDescription() { + return "/api/rptass_app/bldgappr_gendesc/"; + } + + String landRef() { + return "/api/rptass_app/bldgappr_landref/"; + } + + String bldgLocation() { + return "/api/rptass_app/bldgappr_location/"; + } + + String propertyAppraisal() { + return "/api/rptass_app/property_appraisal/"; + } + + String propertyAssessment() { + return "/api/rptass_app/property_assessment/"; + } + + String propertyInfo() { + return "/api/rptass_app/bldgappr_details/"; + } + + String structuralMaterials() { + return "/api/rptass_app/structural_materials/"; + } + + String getBarangay() { + return "/api/rptass_app/agusan_barangay/"; + } + + String getClassComponents() { + return "/api/rptass_app/class_components/"; + } + + String getMunicipality() { + return "/api/rptass_app/agusan_city/"; + } + + String getSignatories() { + return "/api/rptass_app/signatories/"; + } + + String getUnitConstruct() { + return "/api/rptass_app/unitconstruct_values/"; + } + + String getMemoranda() { + return "/api/rptass_app/bldg_memoranda/"; + } + + String getLandOwnerInfo() { + return "/api/rptass_app/landappr_details/"; + } + + String getLandAppraisal() { + return "/api/rptass_app/landappr/"; + } + + String getLandClassification() { + return "/api/rptass_app/appraisal_classification/"; + } + + String getLandSubClassification() { + return "/api/rptass_app/appraisal_subclassification/"; + } + + String getLandPropertyLoc() { + return "/api/rptass_app/landappr_propertyloc/"; + } + + String getLandPropertyBoundaries() { + return "/api/rptass_app/landappr_prptybounderies/"; + } + + String getOtherImprovements() { + return "/api/rptass_app/landappr_plants_trees/"; + } + + String getTreesImprovements() { + return "/api/rptass_app/appraisal_improvement_price/"; + } + + String getValueAdjustmentss() { + return "/api/rptass_app/landappr_value_adjustment/"; + } + + String getTypeOfRoad() { + return "/api/rptass_app/appraisal_road_type/"; + } + + String getTypeOfLocation() { + return "/api/rptass_app/appraisal_location_type/"; + } + + String getLandPropertyAssessment() { + return "/api/rptass_app/landappr_property_assessment/"; + } + + String getLandExt() { + return '/api/rptass_app/landappr_propertyass_extn/'; + } + + String attachmentCategories() { + return "/api/jobnet_app/attachment_categories/"; + } +} diff --git a/lib/utils/validators.dart b/lib/utils/validators.dart new file mode 100644 index 0000000..532e915 --- /dev/null +++ b/lib/utils/validators.dart @@ -0,0 +1,23 @@ +import 'package:form_builder_validators/form_builder_validators.dart'; +import '../utils/text_container.dart'; + +final mobileNumberValidator = FormBuilderValidators.compose([ + FormBuilderValidators.equalLength(11), + FormBuilderValidators.required(errorText: mobileNumberRequired), + FormBuilderValidators.numeric(errorText: numericValidator) +]); +final numericRequired = FormBuilderValidators.compose([ + FormBuilderValidators.required(errorText: "This field is required"), + FormBuilderValidators.numeric(errorText: numericValidator) +]); + +final registerPasswordValidator = FormBuilderValidators.compose([ + FormBuilderValidators.required(errorText: "Password is required"), + FormBuilderValidators.minLength(6, + errorText: "Password must be equal or greater than 6 characters"), +]); + +final integerAndNumeric = FormBuilderValidators.compose([ + FormBuilderValidators.integer(radix: 10, errorText: "Enter a number"), + FormBuilderValidators.numeric(errorText: "Enter a number") +]); diff --git a/lib/widgets/Leadings/add_leading.dart b/lib/widgets/Leadings/add_leading.dart new file mode 100644 index 0000000..b053d1a --- /dev/null +++ b/lib/widgets/Leadings/add_leading.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; + +class AddLeading extends StatelessWidget { + final Function() onPressed; + const AddLeading({super.key, required this.onPressed}); + + @override + Widget build(BuildContext context) { + return IconButton(onPressed: onPressed, icon: const Icon(Icons.add)); + } +} \ No newline at end of file diff --git a/lib/widgets/Leadings/close_leading.dart b/lib/widgets/Leadings/close_leading.dart new file mode 100644 index 0000000..f4ea312 --- /dev/null +++ b/lib/widgets/Leadings/close_leading.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/placeholder.dart'; + +class CloseLeading extends StatelessWidget { + final Function() onPressed; + const CloseLeading({super.key, required this.onPressed}); + + @override + Widget build(BuildContext context) { + return IconButton(onPressed: onPressed, icon: const Icon(Icons.close)); + } +} \ No newline at end of file diff --git a/lib/widgets/costum_divider.dart b/lib/widgets/costum_divider.dart new file mode 100644 index 0000000..14bf211 --- /dev/null +++ b/lib/widgets/costum_divider.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class CostumDivider extends StatelessWidget { + const CostumDivider({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Divider( + color: Colors.grey.withOpacity(.5), + height: 1, + thickness: 1, + ); + } +} diff --git a/lib/widgets/custom_switch.dart b/lib/widgets/custom_switch.dart new file mode 100644 index 0000000..907993f --- /dev/null +++ b/lib/widgets/custom_switch.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:toggle_switch/toggle_switch.dart'; + +class CostumToggleSwitch extends StatelessWidget { + final List activeBGColors; + final List icons; +final int initialLabelIndex; + final void Function(int?)? onToggle; + final List labels; + const CostumToggleSwitch( + {Key? key, + required this.activeBGColors, + required this.icons, + required this.onToggle, + required this.labels, + required this.initialLabelIndex + + }) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(15), + height: 80, + child: ToggleSwitch( + minWidth: 150.0, + cornerRadius: 25.0, + activeBgColors: [ + [Colors.green[800]!], + [Colors.red[800]!] + ], + activeFgColor: Colors.white, + inactiveBgColor: Colors.grey, + inactiveFgColor: Colors.white, + initialLabelIndex: initialLabelIndex, + totalSwitches: 2, + labels: labels, + icons: icons, + radiusStyle: false, + onToggle: onToggle), + ); + } +} diff --git a/lib/widgets/empty_data.dart b/lib/widgets/empty_data.dart new file mode 100644 index 0000000..78a4515 --- /dev/null +++ b/lib/widgets/empty_data.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:unit2/utils/global.dart'; + + +class EmptyData extends StatelessWidget { + final String message; + const EmptyData({Key? key, required this.message,}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/empty.svg', + height: 200.0, + width: 200.0, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 20, + ), + Text( + message,style: Theme.of(context).textTheme.displaySmall!.copyWith(fontSize: blockSizeVertical * 2), + textAlign: TextAlign.center, + ), + + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/error_state.dart b/lib/widgets/error_state.dart new file mode 100644 index 0000000..b23027f --- /dev/null +++ b/lib/widgets/error_state.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; + +import '../theme-data.dart/colors.dart'; + +class SomethingWentWrong extends StatelessWidget { + final String? message; + final Function()? onpressed; + const SomethingWentWrong({Key? key, required this.message, required this.onpressed}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svgs/timeout.svg', + height: 200.0, + width: 200.0, + allowDrawingOutsideViewBox: true, + ), + const SizedBox( + height: 10, + ), + Text( + message??'', + textAlign: TextAlign.center, + ), + const SizedBox( + height: 20, + ), + SizedBox( + height: 50, + child: ElevatedButton.icon( + style: mainBtnStyle( + primary, Colors.transparent, primary.withOpacity(.5)), + onPressed: onpressed, + icon: const Icon( + Icons.refresh, + color: Colors.white, + ), + label: const Text( + "try again", + style: TextStyle(color: Colors.white), + )), + ) + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/label.dart b/lib/widgets/label.dart new file mode 100644 index 0000000..c6e9af5 --- /dev/null +++ b/lib/widgets/label.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; + +import '../utils/global.dart'; + +class Label extends StatelessWidget { + final String text; + const Label({super.key, required this.text}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text(text, + style: Theme.of(context) + .textTheme + .displayMedium! + .copyWith(fontSize: blockSizeVertical * 2.5)), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/passo/custom_button.dart b/lib/widgets/passo/custom_button.dart new file mode 100644 index 0000000..1a6d364 --- /dev/null +++ b/lib/widgets/passo/custom_button.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; + +class CustomButton extends StatelessWidget { + final VoidCallback onPressed; + final Icon icon; + + CustomButton({required this.onPressed, required this.icon}); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + padding: const EdgeInsets.all(30), + backgroundColor: primary, + foregroundColor: Colors.white, + ), + child: icon, + ); + } +} diff --git a/lib/widgets/passo/custom_formBuilder_fields.dart b/lib/widgets/passo/custom_formBuilder_fields.dart new file mode 100644 index 0000000..5adec45 --- /dev/null +++ b/lib/widgets/passo/custom_formBuilder_fields.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; + +Widget customTextField(String labelText, String hintText, String keyText) { + return Container( + margin: const EdgeInsets.only(left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderTextField( + name: keyText, + decoration: normalTextFieldStyle(labelText, hintText), + validator: FormBuilderValidators.compose([]), + ), + ); +} + +Widget customDropDownField(String labelText, String hintText, String keyText, + List dropdownItems) { + // Create a Set to keep track of unique values + Set uniqueItems = {}; + + // Iterate through the dropdownItems list to filter out duplicates + for (var item in dropdownItems) { + uniqueItems.add(item); + } + + // Convert the Set back to a List to use for DropdownMenuItem + List filteredItems = uniqueItems.toList(); + + return Container( + margin: const EdgeInsets.only(left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDropdown( + name: keyText, + autofocus: false, + decoration: normalTextFieldStyle(labelText, hintText), + items: filteredItems + .map((item) => DropdownMenuItem( + value: item, + child: Text(item), + )) + .toList(), + ), + ); +} + +Widget customDatTimePicker(String labelText, String hintText, String keyText) { + return Container( + margin: const EdgeInsets.only(left: 0, top: 10, right: 0, bottom: 0), + child: FormBuilderDateTimePicker( + name: keyText, + initialEntryMode: DatePickerEntryMode.calendarOnly, + initialValue: DateTime.now(), + inputType: InputType.date, + decoration: normalTextFieldStyle(labelText, hintText), + initialTime: const TimeOfDay(hour: 8, minute: 0), + // locale: const Locale.fromSubtags(languageCode: 'fr'), + ), + ); +} diff --git a/lib/widgets/splash_screen.dart b/lib/widgets/splash_screen.dart new file mode 100644 index 0000000..364c8ac --- /dev/null +++ b/lib/widgets/splash_screen.dart @@ -0,0 +1,66 @@ +import 'package:animate_do/animate_do.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/global.dart'; + +class UniTSplashScreen extends StatelessWidget { + const UniTSplashScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height, + color: Colors.black12, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SlideInUp( + from: 50, + duration: const Duration(milliseconds: 300), + child: SvgPicture.asset( + 'assets/svgs/logo.svg', + height: blockSizeVertical * 12.0, + allowDrawingOutsideViewBox: true, + color: primary, + ), + ), + const SizedBox( + height: 12, + ), + SlideInDown( + from: 100, + duration: const Duration(milliseconds: 200), + child: Text("uniT-App", + style: TextStyle( + fontSize: blockSizeVertical * 4, + fontWeight: FontWeight.w600, + letterSpacing: .2, + height: 1, + color: Colors.black)), + ), + const SizedBox(height: 150,), + const SpinKitCircle(color: primary,size: 42,) + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // Flexible( + // flex: 2, + // child: Text("Please Wait ",style: Theme.of(context).textTheme.labelLarge!.copyWith(fontSize: 18))), + // const SizedBox(width: 5,), + // const SpinKitDoubleBounce(color: primary,size: 32,) + // ],) + + ], + ), + ), + ); + } +} diff --git a/lib/widgets/text_icon.dart b/lib/widgets/text_icon.dart new file mode 100644 index 0000000..5a8f50b --- /dev/null +++ b/lib/widgets/text_icon.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/text-styles.dart'; + +import '../theme-data.dart/colors.dart'; + +class TextIcon extends StatelessWidget { + final String title; + final IconData icon; + + const TextIcon({Key? key, required this.title, required this.icon}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Text( + title, + style: titleTextStyle().copyWith(color: primary, fontSize: 18), + ), + Icon( + icon, + color: primary, + size: 24, + ), + ], + ); + } +} diff --git a/lib/widgets/wave.dart b/lib/widgets/wave.dart new file mode 100644 index 0000000..e78516a --- /dev/null +++ b/lib/widgets/wave.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import '../theme-data.dart/colors.dart'; + + +class Wave extends StatelessWidget { + final double height; + const Wave({Key? key, required this.height}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ClipPath( + clipper: WaveClipperOne(), + child: Container( + height: height, + width: MediaQuery.of(context).size.width, + color: primary, + )); + } +} + +class WaveReverse extends StatelessWidget { + final double height; + const WaveReverse({Key? key, required this.height}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ClipPath( + clipper: WaveClipperTwo(reverse: true), + child: Container( + height: height, + width: MediaQuery.of(context).size.width, + color: primary, + )); + } +} 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..f9949bc --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,138 @@ +# 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 "unit2") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.unit2") + +# 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) + +# 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..fcad7d4 --- /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) audioplayers_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); + audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); + g_autoptr(FlPluginRegistrar) modal_progress_hud_nsn_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ModalProgressHudNsnPlugin"); + modal_progress_hud_nsn_plugin_register_with_registrar(modal_progress_hud_nsn_registrar); + g_autoptr(FlPluginRegistrar) platform_device_id_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "PlatformDeviceIdLinuxPlugin"); + platform_device_id_linux_plugin_register_with_registrar(platform_device_id_linux_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..54e72c5 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,27 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + audioplayers_linux + modal_progress_hud_nsn + platform_device_id_linux + 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..1cb3700 --- /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, "unit2"); + 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, "unit2"); + } + + 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..4b81f9b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#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..5caa9d1 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..b1f7d47 --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,42 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import assets_audio_player +import assets_audio_player_web +import audioplayers_darwin +import device_info_plus +import location +import modal_progress_hud_nsn +import package_info_plus +import path_provider_foundation +import platform_device_id +import platform_device_id_macos +import rive_common +import share_plus +import shared_preferences_foundation +import sqflite +import syncfusion_pdfviewer_macos +import url_launcher_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AssetsAudioPlayerPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerPlugin")) + AssetsAudioPlayerWebPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerWebPlugin")) + AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) + ModalProgressHudNsnPlugin.register(with: registry.registrar(forPlugin: "ModalProgressHudNsnPlugin")) + FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) + PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) + RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..049abe2 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..e8df21a --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,123 @@ +PODS: + - assets_audio_player (0.0.1): + - FlutterMacOS + - assets_audio_player_web (0.0.1): + - FlutterMacOS + - audioplayers_darwin (0.0.1): + - FlutterMacOS + - device_info_plus (0.0.1): + - FlutterMacOS + - FlutterMacOS (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - location (0.0.1): + - FlutterMacOS + - modal_progress_hud_nsn (0.0.1): + - FlutterMacOS + - package_info_plus (0.0.1): + - FlutterMacOS + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - platform_device_id (0.0.1): + - FlutterMacOS + - platform_device_id_macos (0.0.1): + - FlutterMacOS + - rive_common (0.0.1): + - FlutterMacOS + - share_plus (0.0.1): + - FlutterMacOS + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite (0.0.2): + - FlutterMacOS + - FMDB (>= 2.7.5) + - syncfusion_pdfviewer_macos (0.0.1): + - FlutterMacOS + - url_launcher_macos (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - assets_audio_player (from `Flutter/ephemeral/.symlinks/plugins/assets_audio_player/macos`) + - assets_audio_player_web (from `Flutter/ephemeral/.symlinks/plugins/assets_audio_player_web/macos`) + - audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos`) + - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + - location (from `Flutter/ephemeral/.symlinks/plugins/location/macos`) + - modal_progress_hud_nsn (from `Flutter/ephemeral/.symlinks/plugins/modal_progress_hud_nsn/macos`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) + - platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`) + - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) + - rive_common (from `Flutter/ephemeral/.symlinks/plugins/rive_common/macos`) + - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + - syncfusion_pdfviewer_macos (from `Flutter/ephemeral/.symlinks/plugins/syncfusion_pdfviewer_macos/macos`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) + +SPEC REPOS: + trunk: + - FMDB + +EXTERNAL SOURCES: + assets_audio_player: + :path: Flutter/ephemeral/.symlinks/plugins/assets_audio_player/macos + assets_audio_player_web: + :path: Flutter/ephemeral/.symlinks/plugins/assets_audio_player_web/macos + audioplayers_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos + device_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos + FlutterMacOS: + :path: Flutter/ephemeral + location: + :path: Flutter/ephemeral/.symlinks/plugins/location/macos + modal_progress_hud_nsn: + :path: Flutter/ephemeral/.symlinks/plugins/modal_progress_hud_nsn/macos + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos + platform_device_id: + :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos + platform_device_id_macos: + :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos + rive_common: + :path: Flutter/ephemeral/.symlinks/plugins/rive_common/macos + share_plus: + :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos + sqflite: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + syncfusion_pdfviewer_macos: + :path: Flutter/ephemeral/.symlinks/plugins/syncfusion_pdfviewer_macos/macos + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos + +SPEC CHECKSUMS: + assets_audio_player: be2578e6f11dd4d183412e97143673c3c4cb2e8a + assets_audio_player_web: 917101123b6db8f73156835c0fa266c11340ff15 + audioplayers_darwin: dcad41de4fbd0099cb3749f7ab3b0cb8f70b810c + device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + location: 7cdb0665bd6577d382b0a343acdadbcb7f964775 + modal_progress_hud_nsn: 8099d46c2cf9de7af8fe0a3f8f5d2aa32cf956c3 + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 + platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763 + platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94 + rive_common: fab8476ce8352bf54152a913f393a8696d3dc98c + share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7 + shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c + sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea + syncfusion_pdfviewer_macos: e9194851581cad04b28b53913d0636d39a4ed4b2 + url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 + +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 + +COCOAPODS: 1.11.3 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..7b7cf22 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,633 @@ +// !$*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 */ + 0B42AD366C3C28D47C2AEC89 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6C623098EB8995A39C4964E /* Pods_Runner.framework */; }; + 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 */ + 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 */ + 2023D02FF0211CAEE16878C9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 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 /* unit2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = unit2.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 = ""; }; + 5BC0F6D90E7D68DE5330DF33 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7FF1BC1DFB4A45BAC2293138 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D6C623098EB8995A39C4964E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0B42AD366C3C28D47C2AEC89 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 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 */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 64DE41DBDE00B8F8F94614A7 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* unit2.app */, + ); + 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 = ""; + }; + 64DE41DBDE00B8F8F94614A7 /* Pods */ = { + isa = PBXGroup; + children = ( + 5BC0F6D90E7D68DE5330DF33 /* Pods-Runner.debug.xcconfig */, + 7FF1BC1DFB4A45BAC2293138 /* Pods-Runner.release.xcconfig */, + 2023D02FF0211CAEE16878C9 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D6C623098EB8995A39C4964E /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + C3E6A8BAF2259AABAF243D8C /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + F31D2B687E220EE9896D3A25 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* unit2.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 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 */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 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"; + }; + C3E6A8BAF2259AABAF243D8C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F31D2B687E220EE9896D3A25 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 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 */ + 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 */ + 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 */ + 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..a007c96 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + 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..53a76c1 --- /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 = unit2 + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.unit2 + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2022 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..2722837 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + 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/notes.txt b/notes.txt new file mode 100644 index 0000000..07ecc0a --- /dev/null +++ b/notes.txt @@ -0,0 +1,4 @@ + onPressed: () { + print(_formKey.currentState!.value['firstname']); + if (_formKey.currentState!.saveAndValidate()) {} + }, \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..71599d5 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1735 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + url: "https://pub.dev" + source: hosted + version: "47.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + url: "https://pub.dev" + source: hosted + version: "4.7.0" + animate_do: + dependency: "direct main" + description: + name: animate_do + sha256: "9aeacc1a7238f971c039bdf45d13c628be554a242e0251c4ddda09d19a1a923f" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + app_popup_menu: + dependency: "direct main" + description: + name: app_popup_menu + sha256: e05b262b65289431603a84e04e53cb2f3aca6013d3ea61e3f24ddd48d49ef848 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + archive: + dependency: transitive + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + assets_audio_player: + dependency: "direct main" + description: + name: assets_audio_player + sha256: "9a87062cf39be0730ba8bb31ed4d148ca4e892e0ae607113f346d3c9a8da5df0" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + assets_audio_player_web: + dependency: transitive + description: + name: assets_audio_player_web + sha256: "24cf82e72c7e7f9292d67e1b52d7945a182d9695ce8f903f60e5c6b379cbcaac" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + async: + dependency: transitive + description: + name: async + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" + source: hosted + version: "2.10.0" + audioplayers: + dependency: "direct main" + description: + name: audioplayers + sha256: "61583554386721772f9309f509e17712865b38565a903c761f96b1115a979282" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + audioplayers_android: + dependency: transitive + description: + name: audioplayers_android + sha256: dbdc9b7f2aa2440314c638aa55aadd45c7705e8340d5eddf2e3fb8da32d4ae2c + url: "https://pub.dev" + source: hosted + version: "3.0.2" + audioplayers_darwin: + dependency: transitive + description: + name: audioplayers_darwin + sha256: "6aea96df1d12f7ad5a71d88c6d1b22a216211a9564219920124c16768e456e9d" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + audioplayers_linux: + dependency: transitive + description: + name: audioplayers_linux + sha256: "396b62ac62c92dd26c3bc5106583747f57a8b325ebd2b41e5576f840cfc61338" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + audioplayers_platform_interface: + dependency: transitive + description: + name: audioplayers_platform_interface + sha256: f7daaed4659143094151ecf6bacd927d29ab8acffba98c110c59f0b81ae51143 + url: "https://pub.dev" + source: hosted + version: "5.0.1" + audioplayers_web: + dependency: transitive + description: + name: audioplayers_web + sha256: ec84fd46eed1577148ed4113f5998a36a18da4fce7170c37ce3e21b631393339 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + audioplayers_windows: + dependency: transitive + description: + name: audioplayers_windows + sha256: "1d3aaac98a192b8488167711ba1e67d8b96333e8d0572ede4e2912e5bbce69a3" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + awesome_dialog: + dependency: "direct main" + description: + name: awesome_dialog + sha256: "7da175ea284fa5da0a4d0cbdfe835c5b71d30c7b38c1770c0f27f48272ff5a08" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + azlistview: + dependency: "direct main" + description: + name: azlistview + sha256: "93e865f11777a271b439f0d6b00799c0797e9daeec2e082a2e01373809c4b90d" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + badges: + dependency: "direct main" + description: + name: badges + sha256: "6e7f3ec561ec08f47f912cfe349d4a1707afdc8dda271e17b046aa6d42c89e77" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + barcode_scan2: + dependency: "direct main" + description: + name: barcode_scan2 + sha256: "0b0625d27841a21e36e896195d86b2aada335e3c486f63647cce701495718e16" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + bloc: + dependency: transitive + description: + name: bloc + sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49" + url: "https://pub.dev" + source: hosted + version: "8.1.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + url: "https://pub.dev" + source: hosted + version: "2.0.10" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" + source: hosted + version: "2.3.3" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "0671ad4162ed510b70d0eb4ad6354c249f8429cab4ae7a4cec86bbc2886eb76e" + url: "https://pub.dev" + source: hosted + version: "7.2.7+1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf + url: "https://pub.dev" + source: hosted + version: "8.6.2" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" + source: hosted + version: "3.2.3" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" + source: hosted + version: "1.0.2" + characters: + dependency: transitive + description: + name: characters + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" + source: hosted + version: "1.2.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1" + url: "https://pub.dev" + source: hosted + version: "4.6.0" + collection: + dependency: transitive + description: + name: collection + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" + source: hosted + version: "1.17.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + convex_bottom_bar: + dependency: "direct main" + description: + name: convex_bottom_bar + sha256: ebf0f3deb1e8e99374d844fee7485d2980ec502dedfaad395c12118477933aef + url: "https://pub.dev" + source: hosted + version: "3.2.0" + cool_alert: + dependency: "direct main" + description: + name: cool_alert + sha256: "48a0b6c04914b6dc7e8d7eaccf2adf21bace6533a3eda0aeb412e0d7a03dc00a" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb + url: "https://pub.dev" + source: hosted + version: "0.3.3+5" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + date_time_picker: + dependency: "direct main" + description: + name: date_time_picker + sha256: "6923c568bcb67a66ab7e083708d0adbcae8214b41bb84d49febc17e89e06fc4a" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + device_frame: + dependency: transitive + description: + name: device_frame + sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d + url: "https://pub.dev" + source: hosted + version: "1.1.0" + device_info: + dependency: transitive + description: + name: device_info + sha256: f4a8156cb7b7480d969cb734907d18b333c8f0bc0b1ad0b342cdcecf30d62c48 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + device_info_platform_interface: + dependency: transitive + description: + name: device_info_platform_interface + sha256: b148e0bf9640145d09a4f8dea96614076f889e7f7f8b5ecab1c7e5c2dbc73c1b + url: "https://pub.dev" + source: hosted + version: "2.0.1" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 + url: "https://pub.dev" + source: hosted + version: "8.2.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" + device_preview: + dependency: "direct main" + description: + name: device_preview + sha256: "2f097bf31b929e15e6756dbe0ec1bcb63952ab9ed51c25dc5a2c722d2b21fdaf" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + dio: + dependency: "direct main" + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" + easy_app_installer: + dependency: "direct main" + description: + name: easy_app_installer + sha256: d7287bf247fe6bc85ad07dfb85804757a6dd2f47e61b0e7ce9195ec7f13e09eb + url: "https://pub.dev" + source: hosted + version: "1.0.0" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + expandable: + dependency: "direct main" + description: + name: expandable + sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2" + url: "https://pub.dev" + source: hosted + version: "5.0.1" + expandable_group: + dependency: "direct main" + description: + name: expandable_group + sha256: "874f9c2daef8a21366fb1df85405f80ee8e8be6e3c2ced727c303641b33b9a95" + url: "https://pub.dev" + source: hosted + version: "0.0.8" + 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: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + 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: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" + url: "https://pub.dev" + source: hosted + version: "5.3.1" + file_utils: + dependency: transitive + description: + name: file_utils + sha256: d1e64389a22649095c8405c9e177272caf05139255931c9ff30d53b5c9bcaa34 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + filter_list: + dependency: "direct main" + description: + name: filter_list + sha256: "2d80d6d19beb7847c1176e8bf6fe06d302b23eb7d1bf48c231dd730409ff9b4d" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flare_flutter: + dependency: transitive + description: + name: flare_flutter + sha256: "99d63c60f00fac81249ce6410ee015d7b125c63d8278a30da81edf3317a1f6a0" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae + url: "https://pub.dev" + source: hosted + version: "8.1.3" + flutter_blurhash: + dependency: transitive + description: + name: flutter_blurhash + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_custom_clippers: + dependency: "direct main" + description: + name: flutter_custom_clippers + sha256: "473e3daf61c2a6cee0ad137393259a25223239d519a131c7ec1cac04d06e5407" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_custom_selector: + dependency: "direct main" + description: + name: flutter_custom_selector + sha256: "4c42dcd6cc2de1574454f0fc86b324303d1bd30e4bc236d01071525342d51427" + url: "https://pub.dev" + source: hosted + version: "0.0.3" + flutter_form_builder: + dependency: "direct main" + description: + name: flutter_form_builder + sha256: "9551c7379adc01a3a3a1100057396407c9534ea8adc937d14a0edd96fcd9e1dc" + url: "https://pub.dev" + source: hosted + version: "7.8.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c + url: "https://pub.dev" + source: hosted + version: "2.0.16" + flutter_progress_hud: + dependency: "direct main" + description: + name: flutter_progress_hud + sha256: "19a4889460b7482c5026a936b768996dade4daad8570e8c0493e292d57121dbb" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + flutter_simple_treeview: + dependency: "direct main" + description: + name: flutter_simple_treeview + sha256: ad4978d2668dd078d3a09966832da111bef9102dd636e572c50c80133b7ff4d9 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_speed_dial: + dependency: "direct main" + description: + name: flutter_speed_dial + sha256: "41d7ad0bc224248637b3a5e0b9083e912a75445bdb450cf82b8ed06d7af7c61d" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + flutter_spinkit: + dependency: "direct main" + description: + name: flutter_spinkit + sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e + url: "https://pub.dev" + source: hosted + version: "5.2.0" + flutter_staggered_animations: + dependency: "direct main" + description: + name: flutter_staggered_animations + sha256: "81d3c816c9bb0dca9e8a5d5454610e21ffb068aedb2bde49d2f8d04f75538351" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + url: "https://pub.dev" + source: hosted + version: "1.1.6" + 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" + flutter_zoom_drawer: + dependency: "direct main" + description: + name: flutter_zoom_drawer + sha256: be25be3536e030096c356b7b0fbeaee418b5e0994d87ff74875032b349cb4079 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + fluttericon: + dependency: "direct main" + description: + name: fluttericon + sha256: "252fa8043826e93d972a602497a260cb3d62b5aea6d045793e4381590f2c1e99" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" + url: "https://pub.dev" + source: hosted + version: "8.2.2" + form_builder_validators: + dependency: "direct main" + description: + name: form_builder_validators + sha256: f2d90439c56345c23ad8d0c2912e4002cd02563d816f4387c9495051c10d3321 + url: "https://pub.dev" + source: hosted + version: "8.6.1" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + group_list_view: + dependency: "direct main" + description: + name: group_list_view + sha256: "58bfc7f4b818abff531c2b202fb18b08abfb503f1621b0e86137a4fa4b6d91dd" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + hive: + dependency: "direct main" + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + hive_generator: + dependency: "direct dev" + description: + name: hive_generator + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + http: + dependency: transitive + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + im_stepper: + dependency: "direct main" + description: + name: im_stepper + sha256: "84ca411f7c4666cb8762a6dd6eec0353c96c67f674124614263875d0570ca634" + url: "https://pub.dev" + source: hosted + version: "1.0.1+1" + image: + dependency: transitive + description: + name: image + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" + source: hosted + version: "3.3.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + location: + dependency: "direct main" + description: + name: location + sha256: "9051959f6f2ccadd887b28b66e9cbbcc25b6838e37cf9e894c421ccc0ebf80b5" + url: "https://pub.dev" + source: hosted + version: "4.4.0" + location_platform_interface: + dependency: transitive + description: + name: location_platform_interface + sha256: "62eeaf1658e92e4459b727f55a3c328eccbac8ba043fa6d262ac5286ad48384c" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + location_web: + dependency: transitive + description: + name: location_web + sha256: "6c08c408a040534c0269c4ff9fe17eebb5a36dea16512fbaf116b9c8bc21545b" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + lottie: + dependency: transitive + description: + name: lottie + sha256: "893da7a0022ec2fcaa616f34529a081f617e86cc501105b856e5a3184c58c7c2" + url: "https://pub.dev" + source: hosted + version: "1.4.3" + mask_text_input_formatter: + dependency: "direct main" + description: + name: mask_text_input_formatter + sha256: "2056a9b8303f71003b9c06c6f71443504f3ca9f4b79b1aa40c9f0f62f9d312cf" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" + source: hosted + version: "0.12.13" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" + source: hosted + version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + modal_progress_hud_nsn: + dependency: "direct main" + description: + name: modal_progress_hud_nsn + sha256: "408b9bcce97567de94637de932260e50be48db1842edc761aeea61670e5ec30c" + url: "https://pub.dev" + source: hosted + version: "0.3.0" + multi_dropdown: + dependency: "direct main" + description: + name: multi_dropdown + sha256: "65b8f505b251c5173e8eff64c09cd37460d8f8be906c2069a03815ad2641dcd1" + url: "https://pub.dev" + source: hosted + version: "1.0.9" + multi_select_flutter: + dependency: "direct main" + description: + name: multi_select_flutter + sha256: "503857b415d390d29159df8a9d92d83c6aac17aaf1c307fb7bcfc77d097d20ed" + url: "https://pub.dev" + source: hosted + version: "4.1.3" + multiselect: + dependency: "direct main" + description: + name: multiselect + sha256: "8d0c4a7b89bee6c5e5e4a25ecba68c796dafc1917492d5606f0caa3947d5905a" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + navigation_builder: + dependency: transitive + description: + name: navigation_builder + sha256: "95e25150191d9cd4e4b86504f33cd9e786d1e6732edb2e3e635bbedc5ef0dea7" + url: "https://pub.dev" + source: hosted + version: "0.0.3" + 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: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "10259b111176fba5c505b102e3a5b022b51dd97e30522e906d6922c745584745" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + path: + dependency: transitive + description: + name: path + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" + source: hosted + version: "1.8.2" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + 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: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + 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" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" + url: "https://pub.dev" + source: hosted + version: "10.4.3" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: d74e77a5ecd38649905db0a7d05ef16bed42ff263b9efb73ed794317c5764ec3 + url: "https://pub.dev" + source: hosted + version: "10.3.4" + 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: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" + url: "https://pub.dev" + source: hosted + version: "3.11.3" + 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: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + platform: + dependency: transitive + description: + name: platform + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + platform_device_id: + dependency: "direct main" + description: + name: platform_device_id + sha256: "7a12ec84de4a823bb10eba2f0e1ad29e2365abba17790489a0d78029904f562e" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + platform_device_id_linux: + dependency: transitive + description: + name: platform_device_id_linux + sha256: "994b1608593e527a629af2d5aeb241c60d308d3434bc78b0f6fcb3c1a02dff43" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + platform_device_id_macos: + dependency: transitive + description: + name: platform_device_id_macos + sha256: "968db2a504c611294b12a031b3734432d6df10553a0d3ae3b33ed21abfdbaba0" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + platform_device_id_platform_interface: + dependency: transitive + description: + name: platform_device_id_platform_interface + sha256: c61607594252aaddacf3e4c4371ab08f2ef85ff427817fa6e48a169429610c46 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + platform_device_id_web: + dependency: transitive + description: + name: platform_device_id_web + sha256: "58e124594e1165db7f108395a780b1d1e1cd403021978e5228cf4289fbe736d5" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + platform_device_id_windows: + dependency: transitive + description: + name: platform_device_id_windows + sha256: dbf8dcf03ad8555320ebae2403a3081b79f137f37661874e161fe2de0a84eeeb + url: "https://pub.dev" + source: hosted + version: "1.0.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + url: "https://pub.dev" + source: hosted + version: "2.1.6" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + provider: + dependency: transitive + description: + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" + source: hosted + version: "6.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + qr: + dependency: transitive + description: + name: qr + sha256: "5c4208b4dc0d55c3184d10d83ee0ded6212dc2b5e2ba17c5a0c0aab279128d21" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: c5c121c54cb6dd837b9b9d57eb7bc7ec6df4aee741032060c8833a678c80b87e + url: "https://pub.dev" + source: hosted + version: "4.0.0" + rive: + dependency: transitive + description: + name: rive + sha256: f3b8af0898c987d68019e91d92257edd902c28c816e49de033a7272e86bd5425 + url: "https://pub.dev" + source: hosted + version: "0.11.4" + rive_common: + dependency: transitive + description: + name: rive_common + sha256: f6687f9d70e6fd3888a9b0e9c0b307966d2ce74cf00cfb01dce906c3bbada52f + url: "https://pub.dev" + source: hosted + version: "0.1.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + scrollable_positioned_list: + dependency: transitive + description: + name: scrollable_positioned_list + sha256: "9566352ab9ba05794ee6c8864f154afba5d36c5637d0e3e32c615ba4ceb92772" + url: "https://pub.dev" + source: hosted + version: "0.2.3" + search_page: + dependency: "direct main" + description: + name: search_page + sha256: "675239c1ac17f999c37aea7f4c969dc2fc21b58eb61d78180ff0c16112aab49b" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + searchable_paginated_dropdown: + dependency: "direct main" + description: + name: searchable_paginated_dropdown + sha256: "289a40f7b0964f91b3d8123b4654a8397ec9df9fd1a6bc8ab545ec33c81a9eb2" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + searchfield: + dependency: "direct main" + description: + name: searchfield + sha256: "62b6653d7194de5a7ea724124846b996d0d211cd3eeeec2e5ca84423650f66f8" + url: "https://pub.dev" + source: hosted + version: "0.7.8" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11" + url: "https://pub.dev" + source: hosted + version: "7.1.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7" + url: "https://pub.dev" + source: hosted + version: "3.3.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac + url: "https://pub.dev" + source: hosted + version: "2.2.1" + 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: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a + url: "https://pub.dev" + source: hosted + version: "2.3.1" + 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: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + signature: + dependency: "direct main" + description: + name: signature + sha256: ad23383717dfa926204695ef6928ff513a77387be1b4a8c685099ce3ec35e5f8 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + simple_chips_input: + dependency: "direct main" + description: + name: simple_chips_input + sha256: "758c2439c74f9105ebb18407095c028e247631108195c38480ea3fb4967c8f6f" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + url: "https://pub.dev" + source: hosted + version: "1.2.6" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + url: "https://pub.dev" + source: hosted + version: "2.2.8+4" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + url: "https://pub.dev" + source: hosted + version: "2.4.5+1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + states_rebuilder: + dependency: transitive + description: + name: states_rebuilder + sha256: bf1a5ab5c543acdefce35e60f482eb7ab592339484fe3266d147ee597f18dc92 + url: "https://pub.dev" + source: hosted + version: "6.3.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + 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" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "8db8f55c77f56968681447d3837c10f27a9e861e238a898fda116c7531def979" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_flutter_pdf: + dependency: transitive + description: + name: syncfusion_flutter_pdf + sha256: a42186922a416c2c9634a8f221aee261101babc2d30b1a1e908a7f034e743046 + url: "https://pub.dev" + source: hosted + version: "21.2.4" + syncfusion_flutter_pdfviewer: + dependency: "direct main" + description: + name: syncfusion_flutter_pdfviewer + sha256: "2dc016f251c675f8e4923135c485356473b4d89c677670164292159cd1dd4f45" + url: "https://pub.dev" + source: hosted + version: "21.2.3" + syncfusion_pdfviewer_macos: + dependency: transitive + description: + name: syncfusion_pdfviewer_macos + sha256: "8cc925cae532c0fa17e849165796d962107f45b86e66ee334dcaabf6b7305c82" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_platform_interface: + dependency: transitive + description: + name: syncfusion_pdfviewer_platform_interface + sha256: "08039ecdb8f79454fb367c6bf5a833846a666039415d2b5d76a7e59a5b3ff710" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_web: + dependency: transitive + description: + name: syncfusion_pdfviewer_web + sha256: "8e5ed0d313a1aa3869e4f2e8d079bc9bfa37ce79d91be7bb328e456f37b7995f" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_windows: + dependency: transitive + description: + name: syncfusion_pdfviewer_windows + sha256: "3e93f281135fb0562f7e6c343d2db741cf3cbd78c5b04884eef9af414408bc77" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + system_info2: + dependency: "direct main" + description: + name: system_info2 + sha256: "90621f3ba586e1f268e38cc7951b172cd4d997e43dc1fbed12eb334c8a22a886" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + 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: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" + source: hosted + version: "0.4.16" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + toggle_switch: + dependency: "direct main" + description: + name: toggle_switch + sha256: "9e6af1f0c5a97d9de41109dc7b9e1b3bbe73417f89b10e0e44dc834fb493d4cb" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + url: "https://pub.dev" + source: hosted + version: "6.1.11" + url_launcher_android: + dependency: "direct main" + description: + name: url_launcher_android + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + url: "https://pub.dev" + source: hosted + version: "6.1.0" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + url: "https://pub.dev" + source: hosted + version: "3.0.6" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + url: "https://pub.dev" + source: hosted + version: "3.0.7" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 + url: "https://pub.dev" + source: hosted + version: "2.0.19" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + url: "https://pub.dev" + source: hosted + version: "3.0.8" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + url: "https://pub.dev" + source: hosted + version: "4.1.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + xml: + dependency: transitive + description: + name: xml + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">2.19.0 <3.0.0" + flutter: ">=3.7.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..2f532b8 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,160 @@ +name: unit2 +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: '>=2.18.5 <3.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. + flutter_custom_clippers: ^2.0.0 + flutter_svg: ^1.1.6 + flutter_form_builder: ^7.7.0 + form_builder_validators: ^8.4.0 + fluttericon: ^2.0.0 + fluttertoast: ^8.1.1 + device_preview: ^1.1.0 + flutter_zoom_drawer: ^3.0.3 + cached_network_image: ^3.2.3 + auto_size_text: ^3.0.0 + animate_do: ^3.0.2 + flutter_spinkit: ^5.1.0 + toggle_switch: ^2.0.1 + convex_bottom_bar: ^3.1.0+1 + azlistview: ^2.0.0 + intl: ^0.17.0 + date_time_picker: ^2.1.0 + flutter_progress_hud: ^2.0.2 + barcode_scan2: ^4.2.1 + qr_flutter: ^4.0.0 + signature: ^5.3.0 + awesome_dialog: ^3.0.2 + system_info2: ^2.0.4 + flutter_bloc: ^8.0.0 + equatable: ^2.0.5 + package_info_plus: ^3.0.2 + easy_app_installer: ^1.0.0 + path_provider: ^2.0.14 + dio: ^4.0.6 + cool_alert: ^1.1.0 + permission_handler: ^10.2.0 + expandable_group: ^0.0.8 + badges: ^3.0.2 + app_popup_menu: ^1.0.0 + modal_progress_hud_nsn: ^0.3.0 + searchfield: ^0.7.5 + filter_list: ^1.0.2 + simple_chips_input: ^1.0.0 + hive: ^2.0.5 + hive_flutter: ^1.1.0 + mask_text_input_formatter: ^2.4.0 + location: ^4.3.0 + platform_device_id: ^1.0.1 + multi_dropdown: ^1.0.9 + searchable_paginated_dropdown: ^1.2.0 + audioplayers: ^4.1.0 + assets_audio_player: ^3.0.6 + flutter_speed_dial: ^6.2.0 + im_stepper: ^1.0.1+1 + shared_preferences: ^2.0.20 + multiselect: ^0.1.0 + multi_select_flutter: ^4.1.3 + flutter_custom_selector: ^0.0.3 + flutter_staggered_animations: ^1.1.1 + group_list_view: ^1.1.1 + search_page: ^2.3.0 + file_picker: ^5.3.1 + expandable: ^5.0.1 + flutter_simple_treeview: ^3.0.2 + syncfusion_flutter_pdfviewer: ^21.2.3 + url_launcher: ^6.1.11 + url_launcher_android: ^6.0.38 + share_plus: ^7.1.0 + + + +dev_dependencies: + flutter_test: + sdk: flutter + + # 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 + build_runner: ^2.1.7 + hive_generator: ^1.1.2 +# 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 + + # To add assets to your application, add an assets section, like this: + assets: + - assets/svgs/ + - assets/pngs/ + - assets/fonts/ + - assets/ + # - 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: LexendDeca + fonts: + - asset: assets/fonts/LexendDeca-Regular.ttf + - asset: assets/fonts/LexendDeca-Light.ttf + weight: 300 + - asset: assets/fonts/LexendDeca-Medium.ttf + weight: 500 + - asset: assets/fonts/LexendDeca-SemiBold.ttf + weight: 600 + - asset: assets/fonts/LexendDeca-Bold.ttf + weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..831a007 --- /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:unit2/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const 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..10f6b60 --- /dev/null +++ b/web/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + unit2 + + + + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..9298dae --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "unit2", + "short_name": "unit2", + "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..7eae244 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,101 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(unit2 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 "unit2") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# 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() + +# 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..930d207 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,104 @@ +# 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") + +# === 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" + windows-x64 $ + 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..7af50e4 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,35 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + AudioplayersWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); + ModalProgressHudNsnPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ModalProgressHudNsnPlugin")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + PlatformDeviceIdWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PlatformDeviceIdWindowsPlugin")); + RivePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RivePlugin")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin")); + 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..6d2ce89 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,31 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + audioplayers_windows + modal_progress_hud_nsn + permission_handler_windows + platform_device_id_windows + rive_common + share_plus + syncfusion_pdfviewer_windows + 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..17411a8 --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,39 @@ +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_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..a51295b --- /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", "unit2" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "unit2" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "unit2.exe" "\0" + VALUE "ProductName", "unit2" "\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..b43b909 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#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()); + 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..f8b1c55 --- /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.CreateAndShow(L"unit2", 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..f5bf9fa --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#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); + 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, + -1, 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..c10f08d --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// 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 registar 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::CreateAndShow(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 | WS_VISIBLE, + 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; + } + + return OnCreate(); +} + +// 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; + } + + 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. +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..17ba431 --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#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 and shows a win32 window with |title| and position and size 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 to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // 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 + // responsponds 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; + + 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_