diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae1f183 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# 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/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..5d1241e --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# 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 and should not be manually edited. + +version: + revision: 9f5ff2306bb3e30b2b98eee79cd231b1336f41f4 + channel: stable + +project_type: app diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3287bb6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Flutter", + "request": "launch", + "type": "dart" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 2477288..8a0ef2c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,22 @@ +<<<<<<< HEAD # CSSD -Flutter CSSD Project \ No newline at end of file +Flutter CSSD Project +======= +# cssd + +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://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. +>>>>>>> commit diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..bc2100d --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,7 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..1333a9f --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,67 @@ +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 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.cssd" + minSdkVersion 18 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + 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" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..e9b79e1 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..702af6d --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/cssd/MainActivity.kt b/android/app/src/main/kotlin/com/example/cssd/MainActivity.kt new file mode 100644 index 0000000..9fb1905 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/cssd/MainActivity.kt @@ -0,0 +1,12 @@ +package com.example.cssd + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..e9b79e1 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..3100ad2 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +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..38c8d45 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +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..296b146 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/Fonts/Montserrat-Black.ttf b/assets/Fonts/Montserrat-Black.ttf new file mode 100644 index 0000000..f0d24ad Binary files /dev/null and b/assets/Fonts/Montserrat-Black.ttf differ diff --git a/assets/Fonts/Montserrat-BlackItalic.ttf b/assets/Fonts/Montserrat-BlackItalic.ttf new file mode 100644 index 0000000..5ce4afc Binary files /dev/null and b/assets/Fonts/Montserrat-BlackItalic.ttf differ diff --git a/assets/Fonts/Montserrat-Bold.ttf b/assets/Fonts/Montserrat-Bold.ttf new file mode 100644 index 0000000..9a425b9 Binary files /dev/null and b/assets/Fonts/Montserrat-Bold.ttf differ diff --git a/assets/Fonts/Montserrat-BoldItalic.ttf b/assets/Fonts/Montserrat-BoldItalic.ttf new file mode 100644 index 0000000..ed61ca7 Binary files /dev/null and b/assets/Fonts/Montserrat-BoldItalic.ttf differ diff --git a/assets/Fonts/Montserrat-ExtraBold.ttf b/assets/Fonts/Montserrat-ExtraBold.ttf new file mode 100644 index 0000000..6725d53 Binary files /dev/null and b/assets/Fonts/Montserrat-ExtraBold.ttf differ diff --git a/assets/Fonts/Montserrat-ExtraBoldItalic.ttf b/assets/Fonts/Montserrat-ExtraBoldItalic.ttf new file mode 100644 index 0000000..107f98d Binary files /dev/null and b/assets/Fonts/Montserrat-ExtraBoldItalic.ttf differ diff --git a/assets/Fonts/Montserrat-ExtraLight.ttf b/assets/Fonts/Montserrat-ExtraLight.ttf new file mode 100644 index 0000000..2967eb6 Binary files /dev/null and b/assets/Fonts/Montserrat-ExtraLight.ttf differ diff --git a/assets/Fonts/Montserrat-ExtraLightItalic.ttf b/assets/Fonts/Montserrat-ExtraLightItalic.ttf new file mode 100644 index 0000000..5d62085 Binary files /dev/null and b/assets/Fonts/Montserrat-ExtraLightItalic.ttf differ diff --git a/assets/Fonts/Montserrat-Italic.ttf b/assets/Fonts/Montserrat-Italic.ttf new file mode 100644 index 0000000..00fadbe Binary files /dev/null and b/assets/Fonts/Montserrat-Italic.ttf differ diff --git a/assets/Fonts/Montserrat-Light.ttf b/assets/Fonts/Montserrat-Light.ttf new file mode 100644 index 0000000..a3cf5f5 Binary files /dev/null and b/assets/Fonts/Montserrat-Light.ttf differ diff --git a/assets/Fonts/Montserrat-LightItalic.ttf b/assets/Fonts/Montserrat-LightItalic.ttf new file mode 100644 index 0000000..6dba219 Binary files /dev/null and b/assets/Fonts/Montserrat-LightItalic.ttf differ diff --git a/assets/Fonts/Montserrat-Medium.ttf b/assets/Fonts/Montserrat-Medium.ttf new file mode 100644 index 0000000..db5b1af Binary files /dev/null and b/assets/Fonts/Montserrat-Medium.ttf differ diff --git a/assets/Fonts/Montserrat-MediumItalic.ttf b/assets/Fonts/Montserrat-MediumItalic.ttf new file mode 100644 index 0000000..16dbf4c Binary files /dev/null and b/assets/Fonts/Montserrat-MediumItalic.ttf differ diff --git a/assets/Fonts/Montserrat-Regular.ttf b/assets/Fonts/Montserrat-Regular.ttf new file mode 100644 index 0000000..2a2b2aa Binary files /dev/null and b/assets/Fonts/Montserrat-Regular.ttf differ diff --git a/assets/Fonts/Montserrat-SemiBold.ttf b/assets/Fonts/Montserrat-SemiBold.ttf new file mode 100644 index 0000000..0ecc667 Binary files /dev/null and b/assets/Fonts/Montserrat-SemiBold.ttf differ diff --git a/assets/Fonts/Montserrat-SemiBoldItalic.ttf b/assets/Fonts/Montserrat-SemiBoldItalic.ttf new file mode 100644 index 0000000..39f2393 Binary files /dev/null and b/assets/Fonts/Montserrat-SemiBoldItalic.ttf differ diff --git a/assets/Fonts/Montserrat-Thin.ttf b/assets/Fonts/Montserrat-Thin.ttf new file mode 100644 index 0000000..6a394e7 Binary files /dev/null and b/assets/Fonts/Montserrat-Thin.ttf differ diff --git a/assets/Fonts/Montserrat-ThinItalic.ttf b/assets/Fonts/Montserrat-ThinItalic.ttf new file mode 100644 index 0000000..8eeeaa4 Binary files /dev/null and b/assets/Fonts/Montserrat-ThinItalic.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileBlack.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileBlack.ttf new file mode 100644 index 0000000..b0dd1d7 Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileBlack.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileBold.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileBold.ttf new file mode 100644 index 0000000..2f9c5ea Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileBold.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBlack.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBlack.ttf new file mode 100644 index 0000000..62a710d Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBlack.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBold.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBold.ttf new file mode 100644 index 0000000..aab2037 Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileExtraBold.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileLight.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileLight.ttf new file mode 100644 index 0000000..375728a Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileLight.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileMedium.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileMedium.ttf new file mode 100644 index 0000000..222cc24 Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileMedium.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileRegular.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileRegular.ttf new file mode 100644 index 0000000..5e6aae4 Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileRegular.ttf differ diff --git a/assets/Fonts/old-iranyekan/IRANYekanMobileThin.ttf b/assets/Fonts/old-iranyekan/IRANYekanMobileThin.ttf new file mode 100644 index 0000000..25da7fc Binary files /dev/null and b/assets/Fonts/old-iranyekan/IRANYekanMobileThin.ttf differ diff --git a/assets/Icons/cable.svg b/assets/Icons/cable.svg new file mode 100644 index 0000000..4b325d8 --- /dev/null +++ b/assets/Icons/cable.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/calendar.svg b/assets/Icons/calendar.svg new file mode 100644 index 0000000..db9f571 --- /dev/null +++ b/assets/Icons/calendar.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/comment.svg b/assets/Icons/comment.svg new file mode 100644 index 0000000..b40dd68 --- /dev/null +++ b/assets/Icons/comment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/Icons/electrician1.svg b/assets/Icons/electrician1.svg new file mode 100644 index 0000000..6bef71b --- /dev/null +++ b/assets/Icons/electrician1.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/electrician2.svg b/assets/Icons/electrician2.svg new file mode 100644 index 0000000..9e5e643 --- /dev/null +++ b/assets/Icons/electrician2.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/electrician3.svg b/assets/Icons/electrician3.svg new file mode 100644 index 0000000..fc65ecb --- /dev/null +++ b/assets/Icons/electrician3.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/electrician4.svg b/assets/Icons/electrician4.svg new file mode 100644 index 0000000..9d5c8d4 --- /dev/null +++ b/assets/Icons/electrician4.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/electrician5.svg b/assets/Icons/electrician5.svg new file mode 100644 index 0000000..dd32c38 --- /dev/null +++ b/assets/Icons/electrician5.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/electrician6.svg b/assets/Icons/electrician6.svg new file mode 100644 index 0000000..5c5cc5a --- /dev/null +++ b/assets/Icons/electrician6.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/ethernet.svg b/assets/Icons/ethernet.svg new file mode 100644 index 0000000..2fda658 --- /dev/null +++ b/assets/Icons/ethernet.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/hdmi.svg b/assets/Icons/hdmi.svg new file mode 100644 index 0000000..7c69a2c --- /dev/null +++ b/assets/Icons/hdmi.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/homeheart.svg b/assets/Icons/homeheart.svg new file mode 100644 index 0000000..15af370 --- /dev/null +++ b/assets/Icons/homeheart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/Icons/plug.svg b/assets/Icons/plug.svg new file mode 100644 index 0000000..7719cd9 --- /dev/null +++ b/assets/Icons/plug.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/Icons/shop.svg b/assets/Icons/shop.svg new file mode 100644 index 0000000..19ade47 --- /dev/null +++ b/assets/Icons/shop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/Icons/user.svg b/assets/Icons/user.svg new file mode 100644 index 0000000..5d2e824 --- /dev/null +++ b/assets/Icons/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/Images/1.jpg b/assets/Images/1.jpg new file mode 100644 index 0000000..582a4c2 Binary files /dev/null and b/assets/Images/1.jpg differ diff --git a/assets/Images/2.jpeg b/assets/Images/2.jpeg new file mode 100644 index 0000000..7d0235c Binary files /dev/null and b/assets/Images/2.jpeg differ diff --git a/assets/Images/3.jpg b/assets/Images/3.jpg new file mode 100644 index 0000000..4a83aab Binary files /dev/null and b/assets/Images/3.jpg differ diff --git a/assets/Images/4.jpg b/assets/Images/4.jpg new file mode 100644 index 0000000..36e8bad Binary files /dev/null and b/assets/Images/4.jpg differ diff --git a/assets/Images/5.jpg b/assets/Images/5.jpg new file mode 100644 index 0000000..5a0de57 Binary files /dev/null and b/assets/Images/5.jpg differ diff --git a/assets/Images/6.png b/assets/Images/6.png new file mode 100644 index 0000000..55c5810 Binary files /dev/null and b/assets/Images/6.png differ diff --git a/assets/Images/7.png b/assets/Images/7.png new file mode 100644 index 0000000..4c52fd6 Binary files /dev/null and b/assets/Images/7.png differ diff --git a/assets/Images/8.jpg b/assets/Images/8.jpg new file mode 100644 index 0000000..bd4a616 Binary files /dev/null and b/assets/Images/8.jpg differ diff --git a/assets/Images/default.jpg b/assets/Images/default.jpg new file mode 100644 index 0000000..0612d8e Binary files /dev/null and b/assets/Images/default.jpg differ diff --git a/assets/Images/electricity-grid-transformer-tower.jpg b/assets/Images/electricity-grid-transformer-tower.jpg new file mode 100644 index 0000000..9a1e4fa Binary files /dev/null and b/assets/Images/electricity-grid-transformer-tower.jpg differ diff --git a/assets/Images/image-asset.png b/assets/Images/image-asset.png new file mode 100644 index 0000000..9e53541 Binary files /dev/null and b/assets/Images/image-asset.png differ diff --git a/assets/Images/images.png b/assets/Images/images.png new file mode 100644 index 0000000..0eb3bb5 Binary files /dev/null and b/assets/Images/images.png differ diff --git a/assets/Images/multiline-lightning-mfi-usb-charge-sync-cable-white-mw-100pl-3-o9dc3yxyuqtoj10b2ztv6i3ik7klxmgy0y89fnkzhc.jpg b/assets/Images/multiline-lightning-mfi-usb-charge-sync-cable-white-mw-100pl-3-o9dc3yxyuqtoj10b2ztv6i3ik7klxmgy0y89fnkzhc.jpg new file mode 100644 index 0000000..4cfcbf0 Binary files /dev/null and b/assets/Images/multiline-lightning-mfi-usb-charge-sync-cable-white-mw-100pl-3-o9dc3yxyuqtoj10b2ztv6i3ik7klxmgy0y89fnkzhc.jpg differ diff --git a/assets/Images/usb-c-hubs-500.png b/assets/Images/usb-c-hubs-500.png new file mode 100644 index 0000000..f7544d1 Binary files /dev/null and b/assets/Images/usb-c-hubs-500.png differ diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..e96ef60 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,32 @@ +*.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/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..6b4c0f7 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..988ea38 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,518 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + 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 */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + 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 */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + 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; + 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\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 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; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.cssd; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.cssd; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.cssd; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 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..1d526a1 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..a28140c --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner/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..b522c75 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + cssd + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..7335fdf --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/lib/config/routes.dart b/lib/config/routes.dart new file mode 100644 index 0000000..ce57bf4 --- /dev/null +++ b/lib/config/routes.dart @@ -0,0 +1,20 @@ +class Routes{ + static const cycleAddScreen = '/CycleAddScreen'; + static const cycleDetailScreen = '/CycleDetailScreen'; + static const cycleFilterScreen = '/CycleFilterScreen'; + static const cycleResultScreen = '/CycleResultScreen'; + static const cycleScanScreen = '/CycleScanScreen'; + static const homePage = '/HomePage'; + static const labelAddScreen = '/LabelAddScreen'; + static const labelDetailScreen = '/LabelDetailScreen'; + static const labelFilterScreen = '/LabelFilterScreen'; + static const labelResultScreen = '/LabelResultScreen'; + static const labelScanScreen = '/LabelScanScreen'; + static const loginScreen = '/LoginScreen'; + static const myInfoScreen = '/MyInfoScreen'; + static const testResultAddScreen = '/TestResultAddScreen'; + static const testDetailsScreen = '/TestDetailsScreen'; + static const testFilterScreen = '/TestFilterScreen'; + static const testResultScreen = '/TestResultScreen'; + static const testVerifyScreen = '/TestVerifyScreen'; +} \ No newline at end of file diff --git a/lib/config/urls.dart b/lib/config/urls.dart new file mode 100644 index 0000000..e1d6627 --- /dev/null +++ b/lib/config/urls.dart @@ -0,0 +1,65 @@ +class Url { + static const String baseUrl = 'https://www.cssd-doc.com/api'; + + static const String login = '$baseUrl/login'; + + static const String getInputs = '$baseUrl/GetInputs'; + + static const String getUserInfo = '$baseUrl/GetInfo'; + + // static const String testResults = '$baseUrl/TestResults'; + + static const String filterItems = '$baseUrl/TestResults/ListFilterItems'; + + static const String labelItems = '$baseUrl/GetLabels'; + + static const String packageItems = '$baseUrl/GetPackages'; + +static String testResults(int id) { + return '$baseUrl/TestResults?page=$id'; + } + + static String labelResults(int id) { + return '$baseUrl/Labels?page=$id'; + } + + static String cycleResults(int id) { + return '$baseUrl/Cycles?page=$id'; + } + // static const String cycleResults = '$baseUrl/Cycles'; + + static String verifyTest(int id) { + return '$baseUrl/TestResults/Verify/$id'; + } + + static String testResultFormValues(String id) { + return '$baseUrl/TestResults/$id/edit'; + } + + static String updateTestResult(String id) { + return '$baseUrl/TestResults/$id'; + } + + static const String createTestResult = '$baseUrl/TestResults'; + + static const String createCycleResult = '$baseUrl/Cycles'; + + static const String createLabelResult = '$baseUrl/Labels'; + + + static String getTestResult(String id) { + return '$baseUrl/TestResults/$id'; + } + + static String getLabelResult(String id) { + return '$baseUrl/Labels/$id'; + } + + static String getCycleResult(String id) { + return '$baseUrl/Cycles/$id'; + } + + static String removeTestResult(String id) { + return '$baseUrl/TestResults/$id'; + } +} diff --git a/lib/config/user.dart b/lib/config/user.dart new file mode 100644 index 0000000..24975d3 --- /dev/null +++ b/lib/config/user.dart @@ -0,0 +1,11 @@ +class User { + static String _token; + + static String get token { + return 'Bearer ' + User._token; + } + + static set token (String token) { + User._token = token; + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..738df62 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,135 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/pages/test_add_screen.dart'; +import 'package:cssd/pages/cycle_add_screen.dart'; +import 'package:cssd/pages/cycle_detail_screen.dart'; +import 'package:cssd/pages/cycle_filter_screen.dart'; +import 'package:cssd/pages/cycle_result_screen.dart'; +import 'package:cssd/pages/cycle_scan_screen.dart'; +import 'package:cssd/pages/label_add_screen.dart'; +import 'package:cssd/pages/label_detail_screen.dart'; +import 'package:cssd/pages/label_filter_screen.dart'; +import 'package:cssd/pages/label_result_screen.dart'; +import 'package:cssd/pages/label_scan_screen.dart'; +import 'package:cssd/pages/login_screen.dart'; +import 'package:cssd/pages/my_info_screen.dart'; +import 'package:cssd/pages/test_detail_screen.dart'; +import 'package:cssd/pages/test_result_screen.dart'; +import 'package:cssd/pages/test_filter_screen.dart'; +import 'package:cssd/pages/test_verify_screen.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/cycles.dart'; +import 'package:cssd/providers/input.dart'; +import 'package:cssd/providers/auth.dart'; +import 'package:cssd/providers/labels.dart'; +import 'package:cssd/providers/my_info.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/Global/splash_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_phoenix/flutter_phoenix.dart'; +import 'package:provider/provider.dart'; + +import './pages/home_screen.dart'; + +void main() { + runApp(Phoenix(child: MyApp())); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + // SystemChrome.setEnabledSystemUIOverlays([]); + // SystemChrome.setSystemUIOverlayStyle( + // const SystemUiOverlayStyle( + // statusBarColor: Colors.red, + // systemNavigationBarColor: Colors.red, + // systemNavigationBarDividerColor: Colors.blue, + // ), + // ); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider.value( + value: Auth(), + ), + ChangeNotifierProvider.value( + value: TestResultsProvider(), + ), + ChangeNotifierProvider.value( + value: Inputs(), + ), + ChangeNotifierProvider.value( + value: MyInfoProvider(), + ), + ChangeNotifierProvider.value( + value: LabelsProvider(), + ), + ChangeNotifierProvider.value( + value: CyclesProvider(), + ), + ChangeNotifierProvider.value( + value: ConnectivityProvider(), + ) + ], + child: Consumer( + builder: (ctx, auth, _) => Consumer( + builder: (ct, connection, _) { + connection.checkConnection(); + print(connection.conStatus); + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'CSSD-DOC', + theme: ThemeData( + primaryColor: Colors.black, + cursorColor: Colors.black, + fontFamily: 'montserrat', + primaryTextTheme: TextTheme( + body1: TextStyle( + color: Colors.black, + ), + ) + // textTheme: TextTheme( + // body2: TextStyle(color: Colors.white, fontSize: 16), + // ), + ), + home: auth.isAuth + ? HomePage() + : FutureBuilder( + future: auth.tryAutoLogin(), + builder: (ctx, authResultSnapshot) => + authResultSnapshot.connectionState == + ConnectionState.waiting + ? SplashScreen() + : LoginScreen(), + ), + routes: { + Routes.homePage: (ctx) => HomePage(), + Routes.loginScreen: (ctx) => LoginScreen(), + Routes.myInfoScreen: (ctx) => MyInfoScreen(), + Routes.testResultScreen: (ctx) => TestResultScreen(), + Routes.testDetailsScreen: (ctx) => TestDetailsScreen(), + Routes.testFilterScreen: (ctx) => TestFilterScreen(), + // Routes.register: (ctx) => Register(), + Routes.testResultAddScreen: (ctx) => TestResultAddScreen(), + Routes.labelDetailScreen: (ctx) => LabelDetailScreen(), + Routes.cycleDetailScreen: (ctx) => CycleDetailScreen(), + Routes.labelFilterScreen: (ctx) => LabelFilterScreen(), + Routes.cycleFilterScreen: (ctx) => CycleFilterScreen(), + Routes.cycleScanScreen: (ctx) => CycleScanScreen(), + Routes.labelScanScreen: (ctx) => LabelScanScreen(), + Routes.cycleAddScreen: (ctx) => CycleAddScreen(), + Routes.labelAddScreen: (ctx) => LabelAddScreen(), + Routes.labelResultScreen: (ctx) => LabelResultScreen(), + Routes.cycleResultScreen: (ctx) => CycleResultScreen(), + Routes.testVerifyScreen: (ctx) => TestVerifyScreen(), + }, + ); + }, + ), + ), + ); + } +} diff --git a/lib/models/connection_model.dart b/lib/models/connection_model.dart new file mode 100644 index 0000000..fbc53f4 --- /dev/null +++ b/lib/models/connection_model.dart @@ -0,0 +1,5 @@ +enum ConnectionStatus{ + Wifi, + Calcular, + Offline +} \ No newline at end of file diff --git a/lib/models/cycles_models.dart b/lib/models/cycles_models.dart new file mode 100644 index 0000000..f75b9be --- /dev/null +++ b/lib/models/cycles_models.dart @@ -0,0 +1,49 @@ +import 'package:flutter/cupertino.dart'; + +class CycleResultObject { + final String id; + final List label; + final String createdAt; + + CycleResultObject({ + @required this.id, + @required this.label, + @required this.createdAt, + }); +} + +class CycleDetailObject { + final String id; // + final String description; // + final String createDate; // + final String date; // + final String sterileId; // + final String cycleNumber; // + final List labels; + + CycleDetailObject({ + @required this.id, + @required this.description, + @required this.createDate, + @required this.date, + @required this.sterileId, + @required this.cycleNumber, + @required this.labels, + }); +} + +class CycleFilterObject { + final String id; + final String cycleNumber; + final String sterilizerId; + final String hospital; + final String date; + + CycleFilterObject({ + @required this.id, + @required this.cycleNumber, + @required this.sterilizerId, + @required this.hospital, + @required this.date, + }); +} diff --git a/lib/models/label_models.dart b/lib/models/label_models.dart new file mode 100644 index 0000000..f3a2a1f --- /dev/null +++ b/lib/models/label_models.dart @@ -0,0 +1,49 @@ +import 'package:flutter/cupertino.dart'; + +class LabelResultObject { + final String id; + final String package; + final String expireDate; + + LabelResultObject({ + @required this.id, + @required this.package, + @required this.expireDate, + }); +} + +class LabelDetailsObject { + final String id; + final String package; + final String createDate; + final String expireDate; + final String sterileDate; + final String sterileId; + final String cycleNumber; + final String lotNumber; + + LabelDetailsObject({ + @required this.id, + @required this.package, + @required this.createDate, + @required this.expireDate, + @required this.sterileDate, + @required this.sterileId, + @required this.cycleNumber, + @required this.lotNumber, + }); +} + +class LabelFilterObject { + final String id; + final String cycleNumber; + final String sterilizerId; + final String hospital; + + LabelFilterObject({ + @required this.id, + @required this.cycleNumber, + @required this.sterilizerId, + @required this.hospital, + }); +} diff --git a/lib/models/test_result_models.dart b/lib/models/test_result_models.dart new file mode 100644 index 0000000..f9332a5 --- /dev/null +++ b/lib/models/test_result_models.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +class TestResultObject { + final String id; + final String name; + final String deviceId; + final String result; + final String date; + final String hospital; + + TestResultObject({ + @required this.id, + @required this.name, + @required this.deviceId, + @required this.result, + @required this.date, + @required this.hospital, + + }); +} + +class TestResultFilterObject { + final String id; + final String labelID; + final String userName; + final String hospital; + final String testType; + final String fDate; + final String uDate; + + + TestResultFilterObject({ + @required this.id, + @required this.labelID, + @required this.userName, + @required this.hospital, + @required this.testType, + @required this.fDate, + @required this.uDate, + + }); +} diff --git a/lib/pages/cycle_add_screen.dart b/lib/pages/cycle_add_screen.dart new file mode 100644 index 0000000..1c84829 --- /dev/null +++ b/lib/pages/cycle_add_screen.dart @@ -0,0 +1,277 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/cycles_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/cycles.dart'; +import 'package:cssd/widgets/CycleScreens/Add/add_label_box.dart'; +import 'package:cssd/widgets/CycleScreens/Add/date_picker.dart'; +import 'package:cssd/widgets/CycleScreens/Add/save_button.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter/cupertino.dart'; + +class CycleAddScreen extends StatefulWidget { + // static const route = '/CycleAddScreen'; + + @override + _CycleAddScreenState createState() => _CycleAddScreenState(); +} + +class _CycleAddScreenState extends State { + final _cycleNumberFocusNode = FocusNode(); + final _descriptionFocosNode = FocusNode(); + TextEditingController descriptionCTRL = new TextEditingController(); + TextEditingController cycleNumberCTRL = new TextEditingController(); + TextEditingController striizerIdCTRL = new TextEditingController(); + TextEditingController dateCTRL = new TextEditingController(); + // String initialLabelValue = ''; + DateTime dateTimeFrom; + // String dateValue; + final _form = GlobalKey(); + + // List labelVals = []; + // List labelValues = []; + bool isInit = true; + CycleFilterObject filters; + + List labelsCTRL = [TextEditingController()]; + int curLabelVal = 1; + @override + void initState() { + descriptionCTRL.text = ''; + cycleNumberCTRL.text = ''; + dateCTRL.text = DateFormat('y-M-d').format(DateTime.now()); + striizerIdCTRL.text = ''; + // dateValue = DateFormat('y-M-d').format(DateTime.now()); + super.initState(); + } + + @override + void didChangeDependencies() async { + if (isInit) { + // var _id = ModalRoute.of(context).settings.arguments; + var cycleProviderObject = Provider.of(context); + cycleProviderObject.resetLabelVals(); + cycleProviderObject.getLabelFilters().then( + (result) { + setState( + () { + // labelValues = + // filters.hospital == '' ? labelVals[0] : filters.hospital; + isInit = false; + }, + ); + }, + ); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Cycles'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context) + .pushReplacementNamed(Routes.cycleResultScreen), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : Form( + key: _form, + child: Padding( + padding: EdgeInsets.all(20), + child: ListView( + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'ADD A CYCLE', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 6 * _deviceBlockSize, + letterSpacing: 3, + ), + ), + SizedBox( + height: 20, + ), + + TextFormField( + validator: (val) { + if (val.isEmpty) { + return 'Strilizer ID required!'; + } + return null; + }, + controller: striizerIdCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 7 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Strilizer ID', + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_cycleNumberFocusNode); + }, + ), + SizedBox( + height: 30, + ), + TextFormField( + validator: (val) { + if (val.isEmpty) { + return 'Cycle number required!'; + } + return null; + }, + controller: cycleNumberCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 7 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Cycle Number', + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + focusNode: _cycleNumberFocusNode, + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_descriptionFocosNode); + }, + ), + + SizedBox( + height: 20, + ), + Container( + margin: EdgeInsets.symmetric(vertical: 10), + child: Text( + 'LABELS INCLUDED', + style: TextStyle( + color: Colors.deepOrange, + letterSpacing: 2, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + Consumer( + builder: (ctx, cycleProvider, _) => + ListView.builder( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (ctx, index) => CycleAddLabelBox( + deviceBlockSize: _deviceBlockSize, + labelValues: cycleProvider.labelValues[index], + labelVals: cycleProvider.labelVals, + initialLabelValue: + cycleProvider.initialLabelValue, + index: index, + ), + itemCount: cycleProvider.labelValues.length, + ), + ), + + CycleAddDatePicker( + dateCTRL: dateCTRL, + deviceBlockSize: _deviceBlockSize), + SizedBox( + height: 30, + ), + TextFormField( + controller: descriptionCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.alignLeft, + size: 7 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Description', + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.multiline, + focusNode: _descriptionFocosNode, + minLines: 1, + maxLines: 5, + ), + SizedBox( + height: 70, + ), + CycleAddSaveButton( + form: _form, + labelValues: Provider.of(context, + listen: false) + .labelValues, + cycleNumberCTRL: cycleNumberCTRL, + dateValue: dateCTRL.text, + descriptionCTRL: descriptionCTRL, + striizerIdCTRL: striizerIdCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 100, + ), + + // DropDownBox(values: ['Washer ID']), + ], + ), + ), + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/cycle_detail_screen.dart b/lib/pages/cycle_detail_screen.dart new file mode 100644 index 0000000..0c050bf --- /dev/null +++ b/lib/pages/cycle_detail_screen.dart @@ -0,0 +1,83 @@ +import 'package:cssd/models/cycles_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/cycles.dart'; +import 'package:cssd/widgets/CycleScreens/Details/datas_box.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class CycleDetailScreen extends StatefulWidget { + // static const route = '/CycleDetailScreen'; + final String testResultId; + + CycleDetailScreen({this.testResultId}); + + @override + _CycleDetailScreenState createState() => _CycleDetailScreenState(); +} + +class _CycleDetailScreenState extends State { + bool isInit = true; + bool isEmpty = false; + CycleDetailObject datas; + @override + void didChangeDependencies() async { + if (isInit) { + var _id = ModalRoute.of(context).settings.arguments; + await Provider.of(context, listen: false) + .showCycleResult(_id.toString()) + .then( + (result) { + setState( + () { + if (result.id == 'null') { + isEmpty = true; + } + datas = result; + isInit = false; + }, + ); + }, + ); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + print(datas); + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Cycles'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : isEmpty + ? Center( + child: Text('This Cycle doesnt exists!'), + ) + : CycleDetailsDataBox( + datas: datas, + deviceBlockSize: _deviceBlockSize, + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/cycle_filter_screen.dart b/lib/pages/cycle_filter_screen.dart new file mode 100644 index 0000000..308d912 --- /dev/null +++ b/lib/pages/cycle_filter_screen.dart @@ -0,0 +1,241 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/cycles_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/cycles.dart'; +import 'package:cssd/widgets/CycleScreens/Filter/date_picker.dart'; +import 'package:cssd/widgets/CycleScreens/Filter/save_button.dart'; +import 'package:cssd/widgets/CycleScreens/Filter/selector_box.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter/cupertino.dart'; + +class CycleFilterScreen extends StatefulWidget { + // static const route = '/CycleFilterScreen'; + + @override + _CycleFilterScreenState createState() => _CycleFilterScreenState(); +} + +class _CycleFilterScreenState extends State { + final _cycleNumberFocusNode = FocusNode(); + final _strilizerIdFocusNode = FocusNode(); + TextEditingController cycleIdCTRL = new TextEditingController(); + TextEditingController cycleNumberCTRL = new TextEditingController(); + TextEditingController striizerIdCTRL = new TextEditingController(); + TextEditingController hospitalCTRL = new TextEditingController(); + + TextEditingController dateCTRL = new TextEditingController(); + DateTime dateTimeFrom; + // String dateValue; + + List> hospitalVals = []; + // String curhospitalVal; + bool isInit = true; + CycleFilterObject filters; + @override + void initState() { + filters = Provider.of(context, listen: false).filters; + cycleIdCTRL.text = filters.id; + cycleNumberCTRL.text = filters.cycleNumber; + dateCTRL.text = DateFormat('y-M-d').format(DateTime.now()); + striizerIdCTRL.text = filters.sterilizerId; + // dateValue = DateFormat('y-M-d').format(DateTime.now()); + super.initState(); + } + + @override + void didChangeDependencies() async { + if (isInit) { + // var _id = ModalRoute.of(context).settings.arguments; + await Provider.of(context, listen: false) + .getHospitalsFilters() + .then( + (result) { + setState( + () { + hospitalVals = result; + filters.hospital == '' + ? hospitalCTRL.text = hospitalVals[0]['name'] + : hospitalVals.forEach( + //id convert to name + (hospital) { + if (hospital['id'] == filters.hospital) { + hospitalCTRL.text = hospital['name']; + } + }, + ); + isInit = false; + }, + ); + }, + ); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Cycles'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context) + .pushReplacementNamed(Routes.cycleResultScreen), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : Padding( + padding: EdgeInsets.all(20), + child: ListView( + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'FILTER RESULTS', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + ), + SizedBox( + height: 20, + ), + TextFormField( + controller: cycleIdCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Cycle ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_cycleNumberFocusNode); + }, + ), + SizedBox( + height: 30, + ), + TextFormField( + controller: cycleNumberCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Cycle Number', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + focusNode: _cycleNumberFocusNode, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_strilizerIdFocusNode); + }, + ), + SizedBox( + height: 30, + ), + TextField( + controller: striizerIdCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Strilizer ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + focusNode: _strilizerIdFocusNode, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.done, + ), + SizedBox( + height: 20, + ), + CycleFilterSelectorBox( + deviceBlockSize: _deviceBlockSize, + hospitalCTRL: hospitalCTRL, + hospitalVals: hospitalVals, + ), + SizedBox( + height: 20, + ), + CycleFilterDatePicker( + dateCTRL: dateCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 70, + ), + CycleFilterSaveButton( + hospitalVals: hospitalVals, + hospitalCTRL: hospitalCTRL, + cycleIdCTRL: cycleIdCTRL, + cycleNumberCTRL: cycleNumberCTRL, + striizerIdCTRL: striizerIdCTRL, + dateCTRL: dateCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 100, + ), + ], + ), + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/cycle_result_screen.dart b/lib/pages/cycle_result_screen.dart new file mode 100644 index 0000000..9279b9d --- /dev/null +++ b/lib/pages/cycle_result_screen.dart @@ -0,0 +1,261 @@ +import 'package:cssd/config/routes.dart'; + +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/CycleScreens/Result/banner.dart'; +import 'package:cssd/widgets/CycleScreens/Result/data_box.dart'; +import 'package:cssd/widgets/CycleScreens/Result/filter_objects.dart'; +import 'package:cssd/widgets/CycleScreens/Result/search_box.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; + +import '../providers/cycles.dart'; + +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class CycleResultScreen extends StatefulWidget { + // static const route = '/CycleResultScreen'; + final bool isAdmin; + + CycleResultScreen({this.isAdmin}); + + @override + _CycleResultScreenState createState() => _CycleResultScreenState(); +} + +class _CycleResultScreenState extends State { + bool _isInit = true; + ScrollController sc; + TextEditingController searchCTRL = new TextEditingController(); + + @override + void initState() { + sc = new ScrollController(); + super.initState(); + } + + @override + void didChangeDependencies() { + if (_isInit) { + var testResults = Provider.of(context); + testResults.setLoading(); + testResults.resetPageNumber(); + testResults.getCycleResults().then((_) { + testResults.resetLoading(); + sc.addListener( + () { + if (sc.position.pixels == sc.position.maxScrollExtent && + searchCTRL.text == '') { + var testResults = Provider.of(context); + testResults.getCycleResults(); + } + }, + ); + }); + } + _isInit = false; + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + floatingActionButton: CycleResultFloatingButton( + deviceBlockSize: _deviceBlockSize, + ), + appBar: AppBar( + titleSpacing: -10, + title: Text('Home'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? Padding( + padding: + EdgeInsets.only(top: 20, right: 20, bottom: 60, left: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CycleResultBanner(deviceBlockSize: _deviceBlockSize), + SizedBox( + height: 10, + ), + Consumer(builder: (ctx, cycle, _) { + return Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + CycleFilterBaner(deviceBlockSize: _deviceBlockSize), + cycle.filters.id != '' + ? CycleFilterChip( + deviceBlockSize: _deviceBlockSize, + label: 'ID', + id: '', + cycleNumber: cycle.filters.cycleNumber, + sterilizerId: cycle.filters.sterilizerId, + hospital: cycle.filters.hospital, + date: cycle.filters.date, + ) + : Container(), + cycle.filters.cycleNumber != '' + ? CycleFilterChip( + deviceBlockSize: _deviceBlockSize, + label: 'Cycle Number', + id: cycle.filters.id, + cycleNumber: '', + sterilizerId: cycle.filters.sterilizerId, + hospital: cycle.filters.hospital, + date: cycle.filters.date, + ) + : Container(), + cycle.filters.sterilizerId != '' + ? CycleFilterChip( + deviceBlockSize: _deviceBlockSize, + label: 'Sterilizer ID', + id: cycle.filters.id, + cycleNumber: cycle.filters.cycleNumber, + sterilizerId: '', + hospital: cycle.filters.hospital, + date: cycle.filters.date, + ) + : Container(), + cycle.filters.hospital != '' + ? CycleFilterChip( + deviceBlockSize: _deviceBlockSize, + label: 'Hospital', + id: cycle.filters.id, + cycleNumber: cycle.filters.cycleNumber, + sterilizerId: cycle.filters.sterilizerId, + hospital: '', + date: cycle.filters.date, + ) + : Container(), + cycle.filters.date != '' + ? CycleFilterChip( + deviceBlockSize: _deviceBlockSize, + label: 'Date', + id: cycle.filters.id, + cycleNumber: cycle.filters.cycleNumber, + sterilizerId: cycle.filters.sterilizerId, + hospital: cycle.filters.hospital, + date: '', + ) + : Container(), + ], + ), + ); + }), + CycleResultSearchBox( + searchCTRL: searchCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 20, + ), + Expanded( + child: Consumer( + builder: (context, cycleResults, _) { + return cycleResults.isloading + ? Center( + child: CircularProgressIndicator(), + ) + : ListView.builder( + controller: sc, + itemBuilder: (context, index) { + String labels = ''; + for (var label + in cycleResults.items[index].label) { + labels += label; + labels += ' , '; + } + labels = labels.substring( + 0, labels.length - 3); // remove extra , + return CycleItemBox( + deviceBlockSize: _deviceBlockSize, + item: cycleResults.items[index], + labels: labels, + ); + }, + itemCount: cycleResults.items.length, + shrinkWrap: true, + ); + }, + ), + ), + ], + ), + ) + : ConnectionErrorBox(); + }), + ); + } +} + +class CycleResultFloatingButton extends StatelessWidget { + const CycleResultFloatingButton({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushNamed(Routes.cycleScanScreen); + }, + child: Container( + padding: EdgeInsets.all(2.5 * _deviceBlockSize), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.barcode, + size: 7.1 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + SizedBox( + width: 2 * _deviceBlockSize, + ), + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushReplacementNamed(Routes.cycleAddScreen); + }, + child: Container( + padding: EdgeInsets.all(_deviceBlockSize), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Color.fromRGBO(0, 190, 190, 1), + ), + child: Icon( + Icons.add, + size: 10 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ); + } +} diff --git a/lib/pages/cycle_scan_screen.dart b/lib/pages/cycle_scan_screen.dart new file mode 100644 index 0000000..98fa41a --- /dev/null +++ b/lib/pages/cycle_scan_screen.dart @@ -0,0 +1,211 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:barcode_scan/barcode_scan.dart'; + +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class CycleScanScreen extends StatefulWidget { + // static const route = '/cycleScanScreen'; + @override + State createState() { + return _CycleScanScreenState(); + } +} + +class _CycleScanScreenState extends State { + String testCode = ""; + TextEditingController idCTRL = new TextEditingController(); + final _form = GlobalKey(); + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + centerTitle: true, + titleSpacing: -10, + title: Text('CSSD'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? ListView( + padding: EdgeInsets.symmetric(horizontal: 20), + children: [ + Container( + padding: EdgeInsets.only(top: 30), + child: Text( + 'LOOKING FOR A CYCLE?', + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 5.5 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 3, + ), + ), + ), + GestureDetector( + child: Container( + margin: EdgeInsets.symmetric(vertical: 10), + height: 200, + decoration: BoxDecoration(border: Border.all()), + child: Center( + child: Text( + 'Please Scan The Cycle Barcode', + style: TextStyle( + color: Colors.black, + fontSize: 5 * _deviceBlockSize, + fontWeight: FontWeight.w100, + letterSpacing: 3, + ), + textAlign: TextAlign.center, + ), + ), + ), + onTap: () { + scan().then( + (String result) { + if (result == 'cancel') { + print('cancel'); + } else if (result == 'error') { + print('error'); + } else if (result == 'access') { + print('access'); + } else { + Navigator.of(context).pushNamed( + Routes.cycleDetailScreen, + arguments: result, + ); + } + }, + ); + }, + ), + Form( + key: _form, + child: TextFormField( + validator: (val) { + if (val.isEmpty) { + return 'Id required!!'; + } + return null; + }, + controller: idCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Or enter a cycle ID', + contentPadding: EdgeInsets.symmetric( + vertical: 2, + horizontal: 3, + ), + focusedBorder: UnderlineInputBorder( + // borderRadius: BorderRadius.only(Radius.circular(4)), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + ), + ), + SizedBox( + height: 40, + ), + Divider( + color: Colors.black, + thickness: 3, + ), + SizedBox( + height: 30, + ), + InkWell( + onTap: () { + if (!_form.currentState.validate()) { + return; + } + Navigator.of(context).pushNamed( + Routes.cycleDetailScreen, + arguments: idCTRL.text, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + margin: EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.red, Colors.orange], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'GO!', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ), + ], + ) + : ConnectionErrorBox(); + }), + ); + } + + Future scan() async { + try { + var barcode = await BarcodeScanner.scan(); + if (barcode.type.name == 'Cancelled') { + return 'cancel'; + } else if (barcode.type.name == 'Failed') { + return 'error'; + } + try { + var id = barcode.rawContent.contains('www.cssd-doc.com') + ? barcode.rawContent.split('/')[5] + : barcode.rawContent; + + return id; + } catch (_) { + return 'null'; + } + } on PlatformException catch (_) { + return 'access'; + } catch (_) { + return 'error'; + } + } +} diff --git a/lib/pages/home_screen.dart b/lib/pages/home_screen.dart new file mode 100644 index 0000000..a5b969c --- /dev/null +++ b/lib/pages/home_screen.dart @@ -0,0 +1,252 @@ +import 'package:cssd/pages/cycle_result_screen.dart'; +import 'package:cssd/pages/label_result_screen.dart'; +// import 'package:cssd/pages/my_test_result.dart'; +import 'package:cssd/pages/test_result_screen.dart'; +import 'package:cssd/providers/auth.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/drawer.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_phoenix/flutter_phoenix.dart'; +import 'package:provider/provider.dart'; +import './my_info_screen.dart'; + +class HomePage extends StatelessWidget { + // 09338736511 + + // static const route = '/HomeScreen'; + @override + Widget build(BuildContext context) { + final userData = Provider.of(context).user; + return Scaffold( + resizeToAvoidBottomPadding: false, + drawer: Selector( + builder: (ctx, value, _) => + value != 'offline' ? AppDrawer() : Container(), + selector: (_, connctivity) => connctivity.conStatus, + ) + // Consumer(builder: (ct, connection, _) { + // return connection.conStatus != 'offline' ? AppDrawer() : Container(); + // }) + , + appBar: AppBar( + centerTitle: true, + title: Text('CSSD'), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 10.0), + child: IconButton( + icon: Icon( + Icons.power_settings_new, + ), + onPressed: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text('LogOut'), + content: Text('Are you sure for logout?'), + actions: [ + FlatButton( + child: Text('Yes'), + onPressed: () { + Navigator.of(ctx).pop(); + Provider.of(context).logout(); + Phoenix.rebirth(context); + }, + ), + FlatButton( + child: Text('No'), + onPressed: () { + Navigator.of(ctx).pop(); + }, + ), + ], + ), + ); + }, + ), + ) + ], + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? DoubleBackToCloseApp( + snackBar: SnackBar( + duration: Duration(seconds: 2), + backgroundColor: Colors.black, + content: Text( + 'Double tap for exit . . .', + style: TextStyle(color: Colors.white), + ), + ), + child: Container( + margin: EdgeInsets.only( + top: 0, bottom: 10, left: 20, right: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: 20, bottom: 10), + child: Text( + 'WELCOME HOME', + style: TextStyle( + color: Colors.black, + fontSize: 20, + letterSpacing: 3.5, + fontWeight: FontWeight.w700, + ), + ), + ), + SelectionItem( + startColor: Color(0xFFFCB8A2), + endColor: Color(0xFFFFECD2), + firstLine: 'My INFO', + secondLine: 'List, Details & Add a one', + onTap: Consumer( + builder: (ctx, auth, _) { + return MyInfoScreen(); + }, + ), + ), + SelectionItem( + startColor: Color(0xFFD5F5FD), + endColor: Color(0xFFE9FFF7), + firstLine: 'TEST RESULTS', + secondLine: 'List, Details & Add a one', + onTap: TestResultScreen() + // MyTestResult( + // isAdmin: false, + // ), + ), + SelectionItem( + startColor: Color(0xFFE2D2C4), + endColor: Color(0xFFFAF7F5), + firstLine: 'LABELS', + secondLine: 'List, Details & Add a one', + onTap: LabelResultScreen(), + ), + SelectionItem( + startColor: Color(0xFFA7CCE1), + endColor: Color(0xFFECF7ED), + firstLine: 'CYCLES', + secondLine: 'List, Details & Add a one', + onTap: CycleResultScreen(), + ), + userData['roles'].contains('Admin') + ? Container() + // SelectionItem( + // startColor: Color(0xFFA7CCE1), + // endColor: Color(0xFFECF7ED), + // firstLine: 'TEST TO VERIFY', + // secondLine: 'List, Details & Add a one', + // onTap: TestVerifyScreen(), + // ) + : Container(), + ], + ), + ), + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} + +class SelectionItem extends StatelessWidget { + final Color startColor; + final Color endColor; + final String firstLine; + final String secondLine; + final Widget onTap; + + SelectionItem( + {this.startColor, + this.endColor, + this.firstLine, + this.secondLine, + this.onTap}); + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + padding: EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [startColor, endColor], + ), + borderRadius: BorderRadius.all( + Radius.circular(3), + ), + ), + child: InkWell( + splashColor: Colors.red, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return onTap; + }, + ), + ); + }, + child: ListTile( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + firstLine, + style: TextStyle( + color: Colors.black, + fontSize: 5 * _deviceBlockSize, + letterSpacing: 3.5, + ), + ), + Text( + secondLine, + style: TextStyle( + color: Colors.grey, + fontSize: 3.5 * _deviceBlockSize, + ), + ), + ], + ), + trailing: Icon( + Icons.arrow_forward_ios, + color: Colors.black, + ), + ), + // Column( + // children: [ + // ListTile( + // title: Text( + // firstLine, + // textAlign: TextAlign.start, + // style: TextStyle(color: Colors.black), + // ), + // ), + // ListTile( + // title: Text( + // secondLine, + // style: TextStyle(color: Colors.black, fontSize: 20), + // ), + // trailing: Icon( + // Icons.arrow_forward_ios, + // color: Colors.black, + // ), + // ), + // ], + // ), + ), + ); + } +} diff --git a/lib/pages/label_add_screen.dart b/lib/pages/label_add_screen.dart new file mode 100644 index 0000000..c3ca9d1 --- /dev/null +++ b/lib/pages/label_add_screen.dart @@ -0,0 +1,268 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/labels.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Add/date_picker.dart'; +import 'package:cssd/widgets/LabelScreens/Add/save_button.dart'; +import 'package:cssd/widgets/LabelScreens/Add/selector_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart' as DateEditor; +import 'package:provider/provider.dart'; + +class LabelAddScreen extends StatefulWidget { + // static const route = '/LabelAddScreen'; + + @override + _LabelAddScreenState createState() => _LabelAddScreenState(); +} + +class _LabelAddScreenState extends State { + final _cycleNumberFocusNode = FocusNode(); + TextEditingController lotNumberCTRL = new TextEditingController(); + TextEditingController cycleNumberCTRL = new TextEditingController(); + TextEditingController striizerIdCTRL = new TextEditingController(); + TextEditingController sDateCTRL = new TextEditingController(); + TextEditingController eDateCTRL = new TextEditingController(); + TextEditingController packageCTRL = new TextEditingController(); + + DateTime dateTimeS; + // String sDateValue; + // String eDateValue; + + final _form = GlobalKey(); + + List> packageVals = []; + List packageValue = []; + bool isInit = true; + // CycleFilterObject filters; + + List labelsCTRL = [TextEditingController()]; + int curLabelVal = 1; + @override + void initState() { + sDateCTRL.text = DateEditor.DateFormat('y-M-d').format(DateTime.now()); + // sDateValue = DateEditor.DateFormat('y-M-d').format(DateTime.now()); + eDateCTRL.text = DateEditor.DateFormat('y-M-d').format(DateTime.now()); + // eDateValue = DateEditor.DateFormat('y-M-d').format(DateTime.now()); + super.initState(); + } + + @override + void didChangeDependencies() async { + if (isInit) { + Provider.of(context, listen: false) + .getPackageFilters() + .then( + (result) { + setState( + () { + packageVals = result; + packageValue.add(result[0]['id']); + packageValue.add(result[0]['name']); + packageCTRL.text = result[0]['name']; + isInit = false; + }, + ); + }, + ); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Labels'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pushReplacementNamed(Routes.labelResultScreen), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : Form( + key: _form, + child: Padding( + padding: EdgeInsets.all(20), + child: ListView( + children: [ + Text( + 'ADD A LABEL', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 6 * _deviceBlockSize, + letterSpacing: 3, + ), + ), + SizedBox( + height: 20, + ), + TextFormField( + onChanged: (val) { + setState(() { + lotNumberCTRL.text = + val + ' - ' + cycleNumberCTRL.text; + }); + }, + validator: (val) { + if (val.isEmpty) { + return 'Strilizer ID required!'; + } + return null; + }, + controller: striizerIdCTRL, + decoration: InputDecoration( + icon: Icon(FontAwesomeIcons.sortNumericDown, + size: 7 * _deviceBlockSize), + isDense: true, + labelText: 'Strilizer ID', + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_cycleNumberFocusNode); + }, + ), + SizedBox( + height: 20, + ), + TextFormField( + onChanged: (val) { + setState( + () { + lotNumberCTRL.text = + striizerIdCTRL.text + ' - ' + val; + }, + ); + }, + validator: (val) { + if (val.isEmpty) { + return 'Cycle number required!'; + } + return null; + }, + controller: cycleNumberCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 7 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Cycle Number', + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + focusNode: _cycleNumberFocusNode, + keyboardType: TextInputType.number, + textInputAction: TextInputAction.done, + ), + SizedBox( + height: 20, + ), + TextFormField( + readOnly: true, + controller: lotNumberCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 7 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + isDense: true, + labelText: 'Lot Number', + contentPadding: EdgeInsets.symmetric( + vertical: 2, + horizontal: 3, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.visiblePassword, + ), + SizedBox( + height: 20, + ), + LabelAddSelectorBox( + deviceBlockSize: _deviceBlockSize, + packageCTRL: packageCTRL, + packageVals: packageVals, + packageValue: packageValue, + ), + SizedBox( + height: 10, + ), + LabelAddDatePicker( + dateCTRL: sDateCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Sterile Date', + ), + SizedBox( + height: 20, + ), + LabelAddDatePicker( + dateCTRL: eDateCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Sterile Date', + ), + SizedBox( + height: 70, + ), + LabelAddSaveButton( + form: _form, + lotNumberCTRL: lotNumberCTRL, + cycleNumberCTRL: cycleNumberCTRL, + sDateCTRL: sDateCTRL, + packageValue: packageValue, + eDateCTRL: eDateCTRL, + striizerIdCTRL: striizerIdCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 100, + ), + ], + ), + ), + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/label_detail_screen.dart b/lib/pages/label_detail_screen.dart new file mode 100644 index 0000000..e72dc48 --- /dev/null +++ b/lib/pages/label_detail_screen.dart @@ -0,0 +1,84 @@ +import 'package:cssd/models/label_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/labels.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Detail/datas_box.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class LabelDetailScreen extends StatefulWidget { + // static const route = '/LabelDetailScreen'; + // final String testResultId; + + // LabelDetailScreen({this.testResultId}); + + @override + _LabelDetailScreenState createState() => _LabelDetailScreenState(); +} + +class _LabelDetailScreenState extends State { + bool isEmpty = false; + bool isInit = true; + LabelDetailsObject datas; + @override + void didChangeDependencies() async { + if (isInit) { + var _id = ModalRoute.of(context).settings.arguments; + await Provider.of(context, listen: false) + .showLabelResult(_id.toString()) + .then( + (result) { + setState( + () { + if (result.id == 'null') { + isEmpty = true; + } + datas = result; + isInit = false; + }, + ); + }, + ); + // print(datas); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + print(datas); + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Labels'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : isEmpty + ? Center( + child: Text('This Lable doesnt exists!'), + ) + : LabelDetailsDataBox( + datas: datas, + deviceBlockSize: _deviceBlockSize, + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/label_filter_screen.dart b/lib/pages/label_filter_screen.dart new file mode 100644 index 0000000..bc7121c --- /dev/null +++ b/lib/pages/label_filter_screen.dart @@ -0,0 +1,228 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/label_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/labels.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Filter/save_button.dart'; +import 'package:cssd/widgets/LabelScreens/Filter/selector_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter/cupertino.dart'; + +class LabelFilterScreen extends StatefulWidget { + // static const route = '/LabelFilterScreen'; + + @override + _LabelFilterScreenState createState() => _LabelFilterScreenState(); +} + +class _LabelFilterScreenState extends State { + final _cycleNumberFocusNode = FocusNode(); + final _strilizerIdFocusNode = FocusNode(); + + TextEditingController labelIdCTRl = new TextEditingController(); + TextEditingController cycleNumberCTRL = new TextEditingController(); + TextEditingController striizerIdCTRL = new TextEditingController(); + TextEditingController hospitalCTRL = new TextEditingController(); + + TextEditingController dateCTRL = new TextEditingController(); + DateTime dateTimeFrom; + + List> hospitalVals = []; + bool isInit = true; + LabelFilterObject filters; + @override + void initState() { + filters = Provider.of(context, listen: false).filters; + labelIdCTRl.text = filters.id; + cycleNumberCTRL.text = filters.cycleNumber; + striizerIdCTRL.text = filters.sterilizerId; + super.initState(); + } + + @override + void didChangeDependencies() async { + if (isInit) { + await Provider.of(context, listen: false) + .getHospitalsFilters() + .then( + (result) { + setState( + () { + hospitalVals = result; + filters.hospital == '' + ? hospitalCTRL.text = hospitalVals[0]['name'] + : hospitalVals.forEach( + //id convert to name + (hospital) { + if (hospital['id'] == filters.hospital) + hospitalCTRL.text = hospital['name']; + }, + ); + isInit = false; + }, + ); + }, + ); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Labels'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context) + .pushReplacementNamed(Routes.labelResultScreen), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : Padding( + padding: EdgeInsets.all(20), + child: ListView( + children: [ + Text( + 'FILTER RESULTS', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + ), + SizedBox( + height: 20, + ), + TextFormField( + controller: labelIdCTRl, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Label ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_cycleNumberFocusNode); + }, + ), + SizedBox( + height: 30, + ), + TextFormField( + controller: cycleNumberCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Cycle Number', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + focusNode: _cycleNumberFocusNode, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_strilizerIdFocusNode); + }, + ), + SizedBox( + height: 30, + ), + TextFormField( + controller: striizerIdCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Strilizer ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + textInputAction: TextInputAction.done, + keyboardType: TextInputType.visiblePassword, + focusNode: _strilizerIdFocusNode, + ), + SizedBox( + height: 30, + ), + + LabelFilterSelectorBox( + deviceBlockSize: _deviceBlockSize, + hospitalCTRL: hospitalCTRL, + hospitalVals: hospitalVals, + ), + SizedBox( + height: 70, + ), + LabelFilterSaveButton( + hospitalVals: hospitalVals, + hospitalCTRL: hospitalCTRL, + labelIdCTRl: labelIdCTRl, + cycleNumberCTRL: cycleNumberCTRL, + striizerIdCTRL: striizerIdCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 50, + ), + // DropDownBox(values: ['Washer ID']), + ], + ), + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} diff --git a/lib/pages/label_result_screen.dart b/lib/pages/label_result_screen.dart new file mode 100644 index 0000000..9d5d371 --- /dev/null +++ b/lib/pages/label_result_screen.dart @@ -0,0 +1,211 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/page_header.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Result/data_box.dart'; +import 'package:cssd/widgets/LabelScreens/Result/filter_chip_box.dart'; +import 'package:cssd/widgets/LabelScreens/Result/floating_buttons.dart'; +import 'package:cssd/widgets/LabelScreens/Result/search_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import '../providers/labels.dart'; + +class LabelResultScreen extends StatefulWidget { + // static const route = '/LabelResultScreen'; + final bool isAdmin; + + LabelResultScreen({this.isAdmin}); + + @override + _LabelResultScreenState createState() => _LabelResultScreenState(); +} + +class _LabelResultScreenState extends State { + bool _isInit = true; + ScrollController sc; + TextEditingController searchCTRL = new TextEditingController(); + + @override + void initState() { + sc = new ScrollController(); + + super.initState(); + } + + @override + void didChangeDependencies() { + if (_isInit) { + var labelProviderObject = + Provider.of(context, listen: false); + labelProviderObject.setLoading(); + labelProviderObject.resetPageNumber(); + labelProviderObject.getLabelResults().then((_) { + labelProviderObject.resetLoading(); + sc.addListener(() { + if (sc.position.pixels == sc.position.maxScrollExtent && + searchCTRL.text == '') { + var labelProviderObject = + Provider.of(context, listen: false); + labelProviderObject.getLabelResults(); + } + }); + }); + } + _isInit = false; + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + floatingActionButton: + LabelFloatingButtons(deviceBlockSize: _deviceBlockSize), + appBar: AppBar( + titleSpacing: -10, + title: Text('Home'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? Padding( + padding: + EdgeInsets.only(top: 20, right: 20, bottom: 60, left: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PageHeader( + deviceBlockSize: _deviceBlockSize, + label: 'LABELS', + route: Routes.labelFilterScreen, + ), + SizedBox( + height: 10, + ), + Consumer( + builder: (context, label, _) { + return Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + InkWell( + onTap: () { + Navigator.of(context).popAndPushNamed( + Routes.labelFilterScreen, + ); + }, + child: Chip( + backgroundColor: Colors.black, + label: Text( + 'Filters', + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + FontAwesomeIcons.filter, + color: Colors.white, + size: 4 * _deviceBlockSize, + ), + onDeleted: () { + Navigator.of(context).popAndPushNamed( + Routes.labelFilterScreen, + ); + }, + ), + ), + label.filters.id != '' + ? LabelFilterChip( + deviceBlockSize: _deviceBlockSize, + id: '', + cycleNumber: label.filters.cycleNumber, + sterilizerId: + label.filters.sterilizerId, + hospital: label.filters.hospital, + label: 'ID', + ) + : Container(), + label.filters.cycleNumber != '' + ? LabelFilterChip( + deviceBlockSize: _deviceBlockSize, + id: label.filters.id, + cycleNumber: '', + sterilizerId: + label.filters.sterilizerId, + hospital: label.filters.hospital, + label: 'Cycle Number', + ) + : Container(), + label.filters.sterilizerId != '' + ? LabelFilterChip( + deviceBlockSize: _deviceBlockSize, + id: label.filters.id, + cycleNumber: label.filters.cycleNumber, + sterilizerId: '', + hospital: label.filters.hospital, + label: 'Sterilizer ID', + ) + : Container(), + label.filters.hospital != '' + ? LabelFilterChip( + deviceBlockSize: _deviceBlockSize, + id: label.filters.id, + cycleNumber: label.filters.cycleNumber, + sterilizerId: + label.filters.sterilizerId, + hospital: '', + label: 'Hospital', + ) + : Container(), + ], + ), + ); + }, + ), + LabelSearchBox( + searchCTRL: searchCTRL, + deviceBlockSize: _deviceBlockSize), + SizedBox( + height: 20, + ), + Expanded( + child: Consumer( + builder: (context, labelResults, _) { + return labelResults.isloading + ? Center( + child: CircularProgressIndicator(), + ) + : ListView.builder( + controller: sc, + itemBuilder: (context, index) => + LabelItemBox( + deviceBlockSize: _deviceBlockSize, + item: labelResults.items[index], + ), + itemCount: labelResults.items.length, + shrinkWrap: true, + ); + }, + ), + ), + ], + ), + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} diff --git a/lib/pages/label_scan_screen.dart b/lib/pages/label_scan_screen.dart new file mode 100644 index 0000000..3b9f5cc --- /dev/null +++ b/lib/pages/label_scan_screen.dart @@ -0,0 +1,90 @@ +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Scan/input_box.dart'; +import 'package:cssd/widgets/LabelScreens/Scan/save_button.dart'; +import 'package:cssd/widgets/LabelScreens/Scan/scan_box.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +// import 'package:flutter/services.dart'; +// import 'package:barcode_scan/barcode_scan.dart'; + +class LabelScanScreen extends StatefulWidget { + // static const route = '/LabelScanScreen'; + @override + State createState() { + return _LabelScanScreenState(); + } +} + +class _LabelScanScreenState extends State { + String testCode = ""; + TextEditingController idCTRL = new TextEditingController(); + final _form = GlobalKey(); + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + centerTitle: true, + titleSpacing: -10, + title: Text('CSSD'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? ListView( + padding: EdgeInsets.symmetric(horizontal: 20), + children: [ + Container( + padding: EdgeInsets.only(top: 30), + child: Text( + 'LOOKING FOR A Label?', + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 5.5 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 3, + ), + ), + ), + LabelScanBox(), + Form( + key: _form, + child: LabelScanInputBox( + idCTRL: idCTRL, deviceBlockSize: _deviceBlockSize), + ), + SizedBox( + height: 40, + ), + Divider( + color: Colors.black, + thickness: 3, + ), + SizedBox( + height: 30, + ), + FilterScanSaveButton( + form: _form, + idCTRL: idCTRL, + deviceBlockSize: _deviceBlockSize, + ), + ], + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} diff --git a/lib/pages/login_screen.dart b/lib/pages/login_screen.dart new file mode 100644 index 0000000..408d5a3 --- /dev/null +++ b/lib/pages/login_screen.dart @@ -0,0 +1,293 @@ +import 'package:cssd/providers/auth.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class LoginScreen extends StatefulWidget { + // static const route = '/HomeScreen'; + + @override + State createState() { + return _LoginScreenState(); + } +} + +class _LoginScreenState extends State { + final _passwordFocusNode = FocusNode(); + final _form = GlobalKey(); + bool _isLoading = false; + final cellNumberController = TextEditingController(); + final passwordController = TextEditingController(); + + bool _hidePass = true; + Map map = Map(); + + @override + void initState() { + cellNumberController.text = map['cellNumber']; + super.initState(); + } + + @override + void dispose() { + _passwordFocusNode.dispose(); + super.dispose(); + } + + void _showDialog(String message) { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text('Error'), + content: Text(message), + actions: [ + FlatButton( + child: Text('Ok'), + onPressed: () { + Navigator.of(ctx).pop(); + }, + ), + ], + ), + ); + } + + void _login() async { + if (!_form.currentState.validate()) { + return; + } + _form.currentState.save(); + setState(() { + _isLoading = true; + }); + // try { + await Provider.of(context) + .login( + map['cellNumber'], + map['password'], + ) + .then( + (result) { + if (result == 'error') { + _showDialog('Something went wrong!'); + setState( + () { + _isLoading = false; + }, + ); + } else if (result == 'badinput') { + _showDialog('User or password incorrect!'); + setState( + () { + _isLoading = false; + }, + ); + } + }, + ); + // } + // } catch (error) { + // _showDialog('something went wrong!'); + // setState(() { + // _isLoading = false; + // }); + // } + + // Navigator.pushReplacement( + // context, + // MaterialPageRoute(builder: (context) { + // return HomePage(); + // }), + // ); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text('CSSD'), + ), + body: Selector( + builder: (ctx, value, _) => value != 'offline' + ? _isLoading + ? Center( + child: CircularProgressIndicator(), + ) + : Form( + key: _form, + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 20), + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 20), + child: Text( + 'LOGIN', + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 6 * _deviceBlockSize, + letterSpacing: 3, + fontWeight: FontWeight.w700, + ), + ), + ), + TextFormField( + validator: (value) { + if (value.isEmpty) { + return 'Cell number is required.'; + } + RegExp regExp = + RegExp(r'^09[0,1,2,3,9]{1}[0-9]{8}$'); + if (!regExp.hasMatch(value)) { + return 'Enter a valid cell number'; + } + return null; + }, + controller: cellNumberController, + decoration: InputDecoration( + icon: Icon( + Icons.call, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Cell Number', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.phone, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(_passwordFocusNode); + }, + onSaved: (value) { + map['cellNumber'] = value; + }, + ), + SizedBox( + height: 30, + ), + TextFormField( + validator: (value) { + if (value.isEmpty) { + return 'Password is required.'; + } + if (value.length < 8) { + return 'Password at least is 8 characters.'; + } + return null; + }, + obscureText: _hidePass, + controller: passwordController, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.starOfLife, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Password', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + suffixIcon: InkWell( + child: Icon(FontAwesomeIcons.eye), + onTap: () { + setState(() { + _hidePass = !_hidePass; + }); + }, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + textInputAction: TextInputAction.done, + onFieldSubmitted: (_) { + _login(); + }, + keyboardType: TextInputType.visiblePassword, + focusNode: _passwordFocusNode, + onSaved: (value) { + map['password'] = value; + }, + ), + SizedBox(height: 40), + Row( + children: [ + InkWell( + onTap: () => _login(), + child: Container( + width: 40 * _deviceBlockSize, + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Spacer(), + Icon( + Icons.exit_to_app, + color: Colors.white, + ), + Text( + 'Login', + style: TextStyle(color: Colors.white), + ), + Spacer() + ], + )), + ), + Spacer(), + ], + ), + SizedBox(height: 10), + FlatButton( + padding: EdgeInsets.all(0), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + 'Forgot Password ?', + style: TextStyle( + color: Colors.black54, + decoration: TextDecoration.underline, + ), + ), + ), + onPressed: () {}, + ), + ], + ), + ) + : ConnectionErrorBox(), + selector: (_, connectivity) => connectivity.conStatus, + )); + } +} diff --git a/lib/pages/my_info_screen.dart b/lib/pages/my_info_screen.dart new file mode 100644 index 0000000..f9eedf1 --- /dev/null +++ b/lib/pages/my_info_screen.dart @@ -0,0 +1,157 @@ +// import 'package:cssd/widgets/LabelScreens/LabelDetails/header.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/LabelScreens/Detail/header.dart'; +import 'package:cssd/widgets/MyInfo/input_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import '../providers/auth.dart'; + +class MyInfoScreen extends StatefulWidget { + // static const route = '/MyInfoScreenRoute'; + + @override + State createState() { + return _MyInfoScreenState(); + } +} + +class _MyInfoScreenState extends State { + Map user; + TextEditingController usernameCTRL = new TextEditingController(); + TextEditingController emailCTRL = new TextEditingController(); + + bool isInit = true; + @override + void didChangeDependencies() async { + if (isInit) { + var authObj = Provider.of(context, listen: false); + user = await authObj.getUserData(); + usernameCTRL.text = user['name'] != null ? user['name'] : ''; + emailCTRL.text = user['email'] != null ? user['email'] : ''; + isInit = false; + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Dashboard'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : ListView( + children: [ + InfoHeader( + deviceBlockSize: _deviceBlockSize, + label: 'MY INFO', + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Column( + children: [ + InfoInputBox( + controller: usernameCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Full Name', + icon: FontAwesomeIcons.sortNumericDown, + ), + SizedBox( + height: 20, + ), + TextFormField( + readOnly: true, + initialValue: user['cell_number'], + decoration: InputDecoration( + icon: Icon( + Icons.call, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Cell Number', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.grey, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + ), + SizedBox( + height: 20, + ), + InfoInputBox( + controller: emailCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Email Address', + icon: FontAwesomeIcons.envelope, + ), + SizedBox( + height: 40, + ), + InkWell( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 60, vertical: 10), + margin: EdgeInsets.only(top: 50, bottom: 20), + width: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(5), + ), + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + textAlign: TextAlign.center, + ), + ), + onTap: () async { + await Provider.of(context, listen: false) + .setUserData( + user['id'], + usernameCTRL.text, + emailCTRL.text, + ); + Navigator.of(context).pop(); + }, + ), + ], + ), + ), + ], + ) + : ConnectionErrorBox(); + }), + ); + } +} diff --git a/lib/pages/register.dart b/lib/pages/register.dart new file mode 100644 index 0000000..71b082c --- /dev/null +++ b/lib/pages/register.dart @@ -0,0 +1,377 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class Register extends StatefulWidget { + // static const route = '/RegisterScreen'; + + @override + State createState() { + return _RegisterState(); + } +} + +class _RegisterState extends State { + final _passwordFocusNode = FocusNode(); + final _form = GlobalKey(); + bool _isLoading = false; + final cellNumberController = TextEditingController(); + bool _hidePass = true; + Map map = Map(); + final List hospitalVals = ['Shahid Beheshti', 'None']; + String curhospitalVal; + @override + void initState() { + cellNumberController.text = map['cellNumber']; + curhospitalVal = hospitalVals[0]; + super.initState(); + } + + @override + void dispose() { + _passwordFocusNode.dispose(); + super.dispose(); + } + + // void _showDialog(String message) { + // showDialog( + // context: context, + // builder: (ctx) => AlertDialog( + // title: Text('error occured'), + // content: Text(message), + // actions: [ + // FlatButton( + // child: Text('Ok'), + // onPressed: () { + // Navigator.of(ctx).pop(); + // }, + // ), + // ], + // ), + // ); + // } + + void _register() async { + if (!_form.currentState.validate()) { + return; + } + _form.currentState.save(); + // setState(() { + // _isLoading = true; + // }); + // try { + // // await Provider.of(context).register( + // // map['cellNumber'], + // // map['password'], + // // ); + // } catch (error) { + // _showDialog('something went wrong!'); + // setState(() { + // _isLoading = false; + // }); + // } + + // Navigator.pushReplacement( + // context, + // MaterialPageRoute(builder: (context) { + // return HomePage(); + // }), + // ); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar:AppBar( + titleSpacing: -10, + title: Text('Login'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: _isLoading + ? Center( + child: CircularProgressIndicator(), + ) + : Form( + key: _form, + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 20), + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 20), + child: Text( + 'register', + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 7 * _deviceBlockSize, + letterSpacing: 3, + ), + ), + ), + TextFormField( + validator: (value) { + if (value.isEmpty) { + return 'Cell number is required.'; + } + RegExp regExp = RegExp(r'^09[0,1,2,3,9]{1}[0-9]{8}$'); + if (!regExp.hasMatch(value)) { + return 'Enter a valid cell number'; + } + return null; + }, + style: TextStyle(fontWeight: FontWeight.w700), + keyboardType: TextInputType.phone, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) { + FocusScope.of(context).requestFocus(_passwordFocusNode); + }, + controller: cellNumberController, + decoration: InputDecoration( + isDense: true, + icon: Icon( + Icons.call, + color: Colors.grey, + ), + border: UnderlineInputBorder(), + fillColor: Colors.red, + labelText: 'Cell Number', + contentPadding: EdgeInsets.symmetric(vertical: 5), + ), + onSaved: (value) { + map['cellNumber'] = value; + }, + ), + SizedBox( + height: 10, + ), + TextFormField( + validator: (value) { + if (value.isEmpty) { + return 'Password is required.'; + } + if (value.length < 8) { + return 'Password at least is 8 characters.'; + } + return null; + }, + obscureText: _hidePass, + textInputAction: TextInputAction.done, + onFieldSubmitted: (_) { + _register(); + }, + style: TextStyle(fontWeight: FontWeight.w700), + decoration: InputDecoration( + isDense: true, + icon: Icon( + FontAwesomeIcons.starOfLife, + color: Colors.grey, + ), + border: UnderlineInputBorder(), + fillColor: Colors.red, + labelText: 'Password', + contentPadding: EdgeInsets.symmetric(vertical: 5), + suffixIcon: InkWell( + child: Icon(FontAwesomeIcons.eye), + onTap: () { + setState(() { + _hidePass = !_hidePass; + }); + }, + ), + ), + focusNode: _passwordFocusNode, + onSaved: (value) { + map['password'] = value; + }, + ), + SizedBox( + height: 10, + ), + TextFormField( + validator: (value) { + if (value.isEmpty) { + return 'Full Name is required.'; + } + // RegExp regExp = RegExp(r'^09[0,1,2,3,9]{1}[0-9]{8}$'); + // if (!regExp.hasMatch(value)) { + // return 'Enter a valid cell number'; + // } + return null; + }, + // keyboardType: TextInputType.phone, + // textInputAction: TextInputAction.next, + // onFieldSubmitted: (_) { + // FocusScope.of(context).requestFocus(_passwordFocusNode); + // }, + // controller: cellNumberController, + decoration: InputDecoration( + isDense: true, + icon: Icon( + FontAwesomeIcons.sortNumericDown, + color: Colors.grey, + ), + border: UnderlineInputBorder(), + fillColor: Colors.red, + labelText: 'Full Name', + contentPadding: EdgeInsets.symmetric(vertical: 5), + ), + style: TextStyle(fontWeight: FontWeight.w700), + // onSaved: (value) { + // map['cellNumber'] = value; + // }, + ), + SizedBox( + height: 20, + ), + Row( + // width: double.infinity, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 5 * _deviceBlockSize, + ), + SizedBox( + width: 3 * _deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: DropdownButton( + focusColor: Colors.red, + icon: Icon(FontAwesomeIcons.angleDown), + isExpanded: true, + hint: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + curhospitalVal, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + // color: _mainFontColor, + // fontSize: 5 * _deviceBlockSize, + ), + ), + ), + isDense: true, + items: hospitalVals.map((String value) { + return new DropdownMenuItem( + value: value, + child: Container( + child: Text( + value, + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * _deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + curhospitalVal = val; + }); + }, + ), + ), + ], + ), + SizedBox(height: 40), + Row( + children: [ + InkWell( + onTap: () => _register(), + child: Container( + width: 40 * _deviceBlockSize, + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 5, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Spacer(), + Icon( + Icons.add, + color: Colors.white, + ), + Text( + 'register', + style: TextStyle(color: Colors.white), + ), + Spacer() + ], + ) + // FlatButton.icon( + // padding: EdgeInsets.all(0), + // onPressed: () { + // _register(); + // }, + // icon: Icon(Icons.exit_to_app, + // color: Colors.white, size: 17), + // label: Text('register', + // style: TextStyle(color: Colors.white)), + // ), + ), + ), + Spacer(), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + width: 40 * _deviceBlockSize, + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 5, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: Colors.black, + ), + ), + child: Row( + children: [ + Spacer(), + Icon( + Icons.exit_to_app, + // size: 6 * _pixelRatio, + ), + Text( + 'Login', + style: TextStyle( + // fontSize: 5.5, + ), + ), + Spacer(), + ], + ), + ), + ), + ], + ), + + ], + ), + ), + ); + } +} diff --git a/lib/pages/test_add_screen.dart b/lib/pages/test_add_screen.dart new file mode 100644 index 0000000..7fcab39 --- /dev/null +++ b/lib/pages/test_add_screen.dart @@ -0,0 +1,269 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/TestResultScreens/Add/selector_box.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:barcode_scan/barcode_scan.dart'; +import 'package:cssd/providers/test_results.dart'; +// import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; + +import 'package:cssd/pages/test_form_page.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class TestResultAddScreen extends StatefulWidget { + // static const route = '/TestResultAddScreen'; + @override + State createState() { + return _TestResultAddScreenState(); + } +} + +class _TestResultAddScreenState extends State { + String testCode = ""; + TextEditingController testTypeCTRL = new TextEditingController(); + final List testTypeVals = []; + + TextEditingController testIdCTRL = new TextEditingController(); + bool isInit = true; + @override + void didChangeDependencies() { + if (isInit) { + var testResultProviderObject = + Provider.of(context, listen: false); + testResultProviderObject.getFilterItems().then((result) { + for (var testType in result[1].keys) { + testTypeVals.add(testType); + } + testTypeCTRL.text = testTypeVals[0]; + setState(() { + isInit = false; + }); + }); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Test Results'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + // padding: EdgeInsets.all(0), + onPressed: () => + Navigator.of(context).popAndPushNamed(Routes.testResultScreen), + ), + ), + body: Consumer(builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : ListView( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20), + children: [ + Container( + padding: EdgeInsets.only( + top: 10, + ), + child: Text( + 'ADD A TEST RESULT', + style: TextStyle( + color: Colors.black, + fontSize: 5 * _deviceBlockSize, + letterSpacing: 3, + fontWeight: FontWeight.w700, + ), + ), + ), + GestureDetector( + child: Container( + margin: EdgeInsets.only(top: 5, bottom: 30), + padding: EdgeInsets.all(10), + height: 200, + decoration: BoxDecoration(border: Border.all()), + child: Center( + child: Text( + 'PLEASE SCAN THE TEST BARCODE', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.grey, + fontSize: 5 * _deviceBlockSize, + fontWeight: FontWeight.w100, + letterSpacing: 3, + ), + ), + ), + ), + onTap: () { + scan().then( + (String result) { + if (result == 'cancel') { + print('cancel'); + } else if (result == 'error') { + print('error'); + } else if (result == 'access') { + print('access'); + } else { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) { + return FormPage( + uniqueCode: result, + ); + }, + ), + ); + } + }, + ); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 70 * _deviceBlockSize, + child: TestResultAddSelectorBox( + deviceBlockSize: _deviceBlockSize, + dataCTRL: testTypeCTRL, + dataVals: testTypeVals, + label: 'Choose a Test Type'), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'OR', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 7 * _deviceBlockSize, + ), + ), + SizedBox( + width: 8 * _deviceBlockSize, + ), + Container( + width: 50 * _deviceBlockSize, + child: TextFormField( + onChanged: (val) { + if (val != '') { + setState(() { + testTypeCTRL.text = ''; + }); + } else { + setState(() { + testTypeCTRL.text = testTypeVals[0]; + }); + } + }, + controller: testIdCTRL, + decoration: InputDecoration( + isDense: true, + icon: Icon( + FontAwesomeIcons.sortNumericDown, + ), + labelText: 'Enter a Test Code', + labelStyle: TextStyle( + fontSize: 3 * _deviceBlockSize), + contentPadding: + EdgeInsets.only(bottom: 5, top: 5), + ), + keyboardType: TextInputType.number, + ), + ), + ], + ) + ], + ), + SizedBox( + width: 5 * _deviceBlockSize, + ), + Expanded( + child: Container( + height: 100, + child: FlatButton( + padding: EdgeInsets.all(0), + color: Color(0xFFEB4A64), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Text( + 'GO', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 6 * _deviceBlockSize, + fontWeight: FontWeight.w700), + ), + onPressed: () { + if (testIdCTRL.text != '') { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return FormPage( + uniqueCode: testIdCTRL.text); + }, + ), + ); + } else if (testTypeCTRL.text != '') { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) { + return FormPage( + name: testTypeCTRL.text, + ); + }, + ), + ); + } + // print(testCode); + }, + ), + ), + ) + ], + ), + ], + ) + : ConnectionErrorBox(); + }), + ); + } + + Future scan() async { + try { + var barcode = await BarcodeScanner.scan(); + if (barcode.type.name == 'Cancelled') { + return 'cancel'; + } else if (barcode.type.name == 'Failed') { + return 'error'; + } + return barcode.rawContent; + } on PlatformException catch (_) { + return 'access'; + } catch (_) { + return 'error'; + } + } +} diff --git a/lib/pages/test_detail_screen.dart b/lib/pages/test_detail_screen.dart new file mode 100644 index 0000000..07046a9 --- /dev/null +++ b/lib/pages/test_detail_screen.dart @@ -0,0 +1,73 @@ +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/TestResultScreens/Details/datas_box.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class TestDetailsScreen extends StatefulWidget { + // static const route = '/TestDetailsScreen'; + final String testResultId; + + TestDetailsScreen({this.testResultId}); + + @override + _TestDetailsScreenState createState() => _TestDetailsScreenState(); +} + +class _TestDetailsScreenState extends State { + bool isInit = true; + Map datas; + @override + void didChangeDependencies() async { + if (isInit) { + var _id = ModalRoute.of(context).settings.arguments; + await Provider.of(context, listen: false) + .showTestResult(_id.toString()) + .then((result) { + setState(() { + datas = result; + isInit = false; + }); + }); + // print(datas); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + // print(datas); + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Test Result Detail'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : DatasBox( + datas: datas, + deviceBlockSize: _deviceBlockSize, + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} diff --git a/lib/pages/test_filter_screen.dart b/lib/pages/test_filter_screen.dart new file mode 100644 index 0000000..7018893 --- /dev/null +++ b/lib/pages/test_filter_screen.dart @@ -0,0 +1,337 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/test_result_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/TestResultScreens/Filter/date_picker.dart'; +import 'package:cssd/widgets/TestResultScreens/Filter/selector_box.dart'; + +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter/cupertino.dart'; + +class TestFilterScreen extends StatefulWidget { + // static const route = '/TestFilterScreen'; + + @override + _TestFilterScreenState createState() => _TestFilterScreenState(); +} + +class _TestFilterScreenState extends State { + TextEditingController idCTRL = new TextEditingController(); + TextEditingController labelIdCTRL = new TextEditingController(); + TextEditingController testTypeCTRL = new TextEditingController(); + TextEditingController hospitalCTRL = new TextEditingController(); + TextEditingController fDateCTRL = new TextEditingController(); + TextEditingController uDateCTRL = new TextEditingController(); + + TextEditingController usernameCTRL = new TextEditingController(); + // TextEditingController dateFrom = new TextEditingController(); + // TextEditingController dateUntil = new TextEditingController(); + DateTime dateTimeFrom; + DateTime dateTimeUntil; + + final List labelIDVals = [ + 'Washer ID', + 'Autocleave ID', + 'Sterilizer ID', + 'Seal Machine ID', + 'Patiant ID', + 'Set/Pack ID', + 'Medical Device ID', + 'OR ID', + 'Insrtument ID', + 'Basket ID', + 'Impalent ID', + 'None', + ]; + // String curLabelIDVal; + + final List testTypeVals = []; + Map testTypes; + + final List hospitalVals = []; + Map hospitals; + // String curhospitalVal; + + bool isInit = true; + // final List labelIDVals = ['Washer ID']; + // String curLabelIDVal; + + // final List labelIDVals = ['Washer ID']; + // String curLabelIDVal; + + // @override + // void initState() { + // super.initState(); + // } + + @override + void didChangeDependencies() { + if (isInit) { + fDateCTRL.text = DateFormat('y-M-d').format(DateTime.now()); + uDateCTRL.text = DateFormat('y-M-d').format(DateTime.now()); + var testResultProviderObject = + Provider.of(context, listen: false); + TestResultFilterObject filters = testResultProviderObject.filters; + idCTRL.text = filters.id; + usernameCTRL.text = filters.userName; + labelIdCTRL.text = + filters.labelID == '' ? labelIDVals[0] : filters.labelID; + idCTRL.text = filters.id; + usernameCTRL.text = filters.userName; + testResultProviderObject.getFilterItems().then((result) { + hospitals = result[0]; + testTypes = result[1]; + + for (var hospital in result[0].keys) { + hospitalVals.add(hospital); + } + for (var testType in result[1].keys) { + testTypeVals.add(testType); + } + var testTypeKey = testTypes.keys.firstWhere( + (k) => testTypes[k] == filters.testType, + orElse: () => ''); // recent testtype name + var hospitalKey = hospitals.keys.firstWhere( + (k) => hospitals[k] == filters.hospital, + orElse: () => ''); // recent testtype name + testTypeCTRL.text = + filters.testType == '' ? testTypeVals[0] : testTypeKey; + hospitalCTRL.text = + filters.hospital == '' ? hospitalVals[0] : hospitalKey; + // print(result[0]); + // print(result[1]); + setState(() { + isInit = false; + }); + }); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Tests'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).popAndPushNamed( + Routes.testResultScreen, + ), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? isInit + ? Center( + child: CircularProgressIndicator(), + ) + : Padding( + padding: EdgeInsets.all(20), + child: ListView( + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'FILTER RESULTS', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + ), + SizedBox( + height: 20, + ), + TextFormField( + controller: idCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + // onFieldSubmitted: (_) { + // FocusScope.of(context) + // .requestFocus(_cycleNumberFocusNode); + // }, + ), + SizedBox( + height: 25, + ), + TestResultFilterSelectorBox( + deviceBlockSize: _deviceBlockSize, + dataCTRL: labelIdCTRL, + dataVals: labelIDVals, + label: 'Label ID', + ), + SizedBox( + height: 25, + ), + + TextFormField( + controller: usernameCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Username', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.next, + // onFieldSubmitted: (_) { + // FocusScope.of(context) + // .requestFocus(_cycleNumberFocusNode); + // }, + ), + SizedBox( + height: 25, + ), + TestResultFilterSelectorBox( + deviceBlockSize: _deviceBlockSize, + dataCTRL: testTypeCTRL, + dataVals: testTypeVals, + label: 'Test Type', + ), + SizedBox( + height: 25, + ), + TestResultFilterSelectorBox( + deviceBlockSize: _deviceBlockSize, + dataCTRL: hospitalCTRL, + dataVals: hospitalVals, + label: 'Hospital', + ), + SizedBox( + height: 25, + ), + + TestResultFilterDatePicker( + dateCTRL: fDateCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Date From', + ), + SizedBox( + height: 25, + ), + TestResultFilterDatePicker( + dateCTRL: uDateCTRL, + deviceBlockSize: _deviceBlockSize, + label: 'Date Until', + ), + SizedBox( + height: 70, + ), + InkWell( + onTap: () { + Provider.of(context) + .setFilters( + idCTRL.text, + labelIdCTRL.text != 'None' + ? labelIdCTRL.text + : '', + usernameCTRL.text, + testTypeCTRL.text != 'None' + ? testTypes[testTypeCTRL.text] + : '', + hospitalCTRL.text != 'None' + ? hospitals[hospitalCTRL.text] + : '', + fDateCTRL.text, + uDateCTRL.text, + ); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Filters changed.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + // Navigator.of(context).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then( + (_) => Navigator.of(context).popAndPushNamed( + Routes.testResultScreen, + ), + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'FILTER', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ), + SizedBox( + height: 70, + ), + // DropDownBox(values: ['Washer ID']), + ], + ), + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} diff --git a/lib/pages/test_form_page.dart b/lib/pages/test_form_page.dart new file mode 100644 index 0000000..9ea7ff8 --- /dev/null +++ b/lib/pages/test_form_page.dart @@ -0,0 +1,178 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/providers/input.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/TestResultScreens/Add/form_creator.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class FormPage extends StatefulWidget { + final String name; + final String uniqueCode; + final String testResultId; + final String testTypeId; + + FormPage({this.name, this.uniqueCode, this.testResultId, this.testTypeId}); + + @override + _FormPageState createState() => _FormPageState(); +} + +class _FormPageState extends State { + bool _isInit = true; + bool _isLoading = false; + bool isAdding = false; + final _form = GlobalKey(); + Map values = {}; + List> formInputs; + + void _saveForm() { + formatData(formInputs); + if (this.widget.testResultId != null && this.widget.testResultId !=''){ + values['_method'] = 'put'; + TestResultsProvider.updateTestResult(this.widget.testResultId, values).then((_){ + Navigator.of(context).pop(); + }); + } else { + setState(() { + _isLoading = true; + }); + TestResultsProvider.createTestResult(values).then((_) { + setState(() { + _isLoading = false; + }); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Test added.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then((_) { + Navigator.of(context).popAndPushNamed(Routes.testResultScreen); + }); + }); + + + } + } + + @override + void didChangeDependencies() { + if (_isInit) { + setState(() { + _isLoading = true; + }); + Provider.of(context) + .getInputs( + testResultId: this.widget.testResultId ?? "", + name: this.widget.name ?? "", + uniqueCode: this.widget.uniqueCode ?? "", + testTypeId: this.widget.testTypeId ?? "" + ) + .then((_) { + setState(() { + _isLoading = false; + }); + }); + } + _isInit = false; + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text('Add Test Result'), + actions: [ + IconButton( + icon: Icon(Icons.save), + onPressed: () { + _saveForm(); + }, + ) + ], + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () { + Navigator.of(context).popAndPushNamed(Routes.testResultScreen); + }, + ), + ), + body: Column( + children: [ + Expanded( + child: _isLoading + ? Center(child: CircularProgressIndicator()) + : Form( + key: _form, + child: Consumer( + builder: (context, inputs, _) { + formInputs = inputs.inputItems; + // print(formInputs); + return formInputs.length != 0 ? FormCreator( + form: inputs.inputItems, + onChanged: (value) { + formInputs = value; + }, + ) : Center(child: Text('An error happen!!!'),); + }, + ), + ), + ), + // https://www.cssd-doc.com/api/GetInfo + // InkWell( + // onTap: () { + // _saveForm(); + // }, + // child: Container( + // padding: EdgeInsets.symmetric(horizontal: 60, vertical: 15), + // margin: EdgeInsets.symmetric(vertical: 20, horizontal: 50), + // decoration: BoxDecoration( + // gradient: LinearGradient(colors: [Colors.blue, Colors.green]), + // borderRadius: BorderRadius.circular(10), + // ), + // child: Text( + // 'Save', + // style: TextStyle(color: Colors.white, fontSize: 17), + // textAlign: TextAlign.center, + // ), + // ), + // ), + ], + )); + } + + void formatData(inputs) { + for (var input in inputs) { + if(input['type'] != 'Form') { + if(input['key'] == 'result') { + values[input["key"]] = input["value"] ? "Accept" : "Reject"; + // print('${input["key"]} : ${input["value"] ? "Accept" : "Reject"}'); + } else if(input['key'] == 'date') { + var date = input["value"]; + + values[input["key"]] = "${date.year}-${date.month}-${date.day}"; + } else { + values[input["key"]] = input["value"]; + // print('${input["key"]} : ${input["value"]}'); + } + } + if (input['children'] != null && input['children'].isNotEmpty) { + formatData(input['children']); + } + } + print(values); + + } +} diff --git a/lib/pages/test_result_screen.dart b/lib/pages/test_result_screen.dart new file mode 100644 index 0000000..da8f0aa --- /dev/null +++ b/lib/pages/test_result_screen.dart @@ -0,0 +1,451 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/test_result_models.dart'; +import 'package:cssd/providers/connectivity.dart'; +// import 'package:cssd/providers/test_result.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/Global/splash_screen%20copy.dart'; +import 'package:cssd/widgets/TestResultScreens/Main/filter_chip_box.dart'; +import 'package:cssd/widgets/TestResultScreens/Main/floating_button.dart'; +import 'package:cssd/widgets/TestResultScreens/Main/search_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class TestResultScreen extends StatefulWidget { + // static const route = '/TestResultScreen'; + final bool isAdmin; + + TestResultScreen({this.isAdmin}); + + @override + _TestResultScreenState createState() => _TestResultScreenState(); +} + +class _TestResultScreenState extends State { + TextEditingController searchCTRL = new TextEditingController(); + ScrollController sc; + + bool _isInit = true; + // List _data = []; + + @override + void initState() { + sc = new ScrollController(); + + super.initState(); + } + + @override + void didChangeDependencies() { + if (_isInit) { + var testResults = + Provider.of(context, listen: false); + // testResults.resetFilters(); + testResults.setLoading(); + testResults.resetPageNumber(); + testResults.getTestResults().then((_) { + testResults.resetLoading(); + sc.addListener(() { + if (sc.position.pixels == sc.position.maxScrollExtent && + searchCTRL.text == '') { + var labelProviderObject = + Provider.of(context, listen: false); + labelProviderObject.getTestResults(); + } + }); + + // setState(() { + // _isLoading = false; + // }); + }); + _isInit = false; + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + floatingActionButton: + TestResultFloatingButton(deviceBlockSize: _deviceBlockSize), + appBar: AppBar( + titleSpacing: -10, + title: Text('Home'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Consumer( + builder: (ct, connection, _) { + return connection.conStatus != 'offline' + ? Padding( + padding: + EdgeInsets.only(top: 20, left: 20, right: 20, bottom: 60), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + // padding: EdgeInsets.only(top: 20, bottom: 40), + child: Text( + 'MY TEST RESULTS', + // textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 6 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 2, + ), + ), + ), + Spacer(), + InkWell( + onTap: () { + Navigator.of(context) + .popAndPushNamed(Routes.testFilterScreen); + }, + child: Container( + padding: EdgeInsets.all(7), + child: Icon( + FontAwesomeIcons.filter, + size: 7 * _deviceBlockSize, + ), + ), + ), + ], + ), + SizedBox( + height: 20, + ), + Consumer( + builder: (context, testResult, _) { + return Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + InkWell( + onTap: () { + Navigator.of(context).popAndPushNamed( + Routes.testFilterScreen); + }, + child: Chip( + backgroundColor: Colors.black, + label: Text( + 'Filters', + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + FontAwesomeIcons.filter, + color: Colors.white, + size: 4 * _deviceBlockSize, + ), + onDeleted: () { + Navigator.of(context).popAndPushNamed( + Routes.testFilterScreen, + ); + }, + ), + ), + testResult.filters.id != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'ID', + id: '', + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.labelID != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Label ID', + id: testResult.filters.id, + labelID: '', + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.testType != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Test Type', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: '', + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.hospital != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Hospital', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: '', + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.userName != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Username', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: '', + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.fDate != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'From Date', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: '', + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.uDate != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Until Date', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: '', + ) + : Container(), + ], + ), + ); + }, + ), + TestResultSearchBox( + searchCTRL: searchCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 20, + ), + Expanded( + child: Consumer( + builder: (context, testResults, _) { + return testResults.isloading + ? Center( + child: CircularProgressIndicator(), + ) + : ListView.builder( + controller: sc, + itemBuilder: (context, index) => + TestItemBox( + deviceBlockSize: _deviceBlockSize, + item: testResults.items[index], + ), + itemCount: testResults.items.length, + shrinkWrap: true, + ); + }, + ), + ), + ], + ), + ) + : ConnectionErrorBox(); + }, + ), + ); + } +} + +class TestItemBox extends StatelessWidget { + final TestResultObject item; + const TestItemBox({ + Key key, + @required double deviceBlockSize, + this.item, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + // print(item.result); + return GestureDetector( + onTap: () => Navigator.of(context).pushNamed( + Routes.testDetailsScreen, + arguments: item.id, + ), + child: Card( + child: Container( + padding: EdgeInsets.all(10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 57 * _deviceBlockSize, + child: Text( + item.name, + overflow: TextOverflow.ellipsis, + // style: TextStyle(fontSize: 20), + ), + ), + Container( + width: 57 * _deviceBlockSize, + child: Text( + item.hospital, + style: TextStyle( + color: Colors.grey, + fontSize: 3 * _deviceBlockSize, + ), + ), + ), + SizedBox( + height: 15, + ), + item.result == 'Verified' + ? Text( + 'Verified', + style: TextStyle(color: Colors.blueAccent), + ) + : Text( + 'Rejected', + style: TextStyle( + color: Colors.red, + ), + ), + ], + ), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(item.date), + SizedBox( + height: 15, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + item.result != 'Verified' + ? InkWell( + onTap: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text('Delete'), + content: Text( + 'Are you sure for delete this test?'), + actions: [ + FlatButton( + onPressed: () { + Provider.of( + context) + .removeTestResult( + item.id.toString()) + .then((_) { + Navigator.of(ctx).pop(); + }); + }, + child: Text('Yes'), + ), + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('No'), + ), + ], + ), + ); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + child: Icon( + Icons.delete, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ) + : Container(), + SizedBox( + width: _deviceBlockSize, + ), + InkWell( + onTap: () { + Navigator.of(context).pushNamed( + Routes.testDetailsScreen, + arguments: item.id, + ); + // TestDetail(testResultId: item.id.toString()); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.fileAlt, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ) + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/test_verify_screen.dart b/lib/pages/test_verify_screen.dart new file mode 100644 index 0000000..6c4d004 --- /dev/null +++ b/lib/pages/test_verify_screen.dart @@ -0,0 +1,464 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/test_result_models.dart'; +// import 'package:cssd/providers/test_result.dart'; +import 'package:cssd/providers/test_results.dart'; +import 'package:cssd/widgets/TestResultScreens/Main/filter_chip_box.dart'; +import 'package:cssd/widgets/TestResultScreens/Main/search_box.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class TestVerifyScreen extends StatefulWidget { + // static const route = '/TestVerifyScreen'; + final bool isAdmin; + + TestVerifyScreen({this.isAdmin}); + + @override + _TestVerifyScreenState createState() => _TestVerifyScreenState(); +} + +class _TestVerifyScreenState extends State { + TextEditingController searchCTRL = new TextEditingController(); + ScrollController sc; + + bool _isInit = true; + // List _data = []; + + @override + void initState() { + sc = new ScrollController(); + + super.initState(); + } + + @override + void didChangeDependencies() { + if (_isInit) { + // setState(() { + // _isLoading = true; + // }); + var testResults = + Provider.of(context, listen: false); + testResults.setLoading(); + testResults.resetPageNumber(); + testResults.getTestResults().then((_) { + testResults.resetLoading(); + sc.addListener(() { + if (sc.position.pixels == sc.position.maxScrollExtent && + searchCTRL.text == '') { + var labelProviderObject = + Provider.of(context, listen: false); + labelProviderObject.getTestResults(); + } + }); + + // setState(() { + // _isLoading = false; + // }); + }); + _isInit = false; + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Scaffold( + appBar: AppBar( + titleSpacing: -10, + title: Text('Home'), + leading: IconButton( + icon: Icon( + Icons.keyboard_arrow_left, + size: 35, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Padding( + padding: EdgeInsets.only(top: 20, left: 20, right: 20, bottom: 60), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + // padding: EdgeInsets.only(top: 20, bottom: 40), + child: Text( + 'TESTS TO VERIFY', + // textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 6 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 2, + ), + ), + ), + Spacer(), + InkWell( + onTap: () { + Navigator.of(context) + .popAndPushNamed(Routes.testFilterScreen); + }, + child: Container( + padding: EdgeInsets.all(7), + child: Icon( + FontAwesomeIcons.filter, + size: 7 * _deviceBlockSize, + ), + ), + ), + ], + ), + SizedBox( + height: 20, + ), + Consumer( + builder: (context, testResult, _) { + return Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + InkWell( + onTap: () { + Navigator.of(context) + .popAndPushNamed(Routes.testFilterScreen); + }, + child: Chip( + backgroundColor: Colors.black, + label: Text( + 'Filters', + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + FontAwesomeIcons.filter, + color: Colors.white, + size: 4 * _deviceBlockSize, + ), + onDeleted: () { + Navigator.of(context) + .popAndPushNamed(Routes.testFilterScreen); + }, + ), + ), + testResult.filters.id != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'ID', + id: '', + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.labelID != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Label ID', + id: testResult.filters.id, + labelID: '', + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.testType != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Test Type', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: '', + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.hospital != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Hospital', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: '', + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.userName != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Username', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: '', + fDate: testResult.filters.fDate, + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.fDate != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'From Date', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: '', + uDate: testResult.filters.uDate, + ) + : Container(), + testResult.filters.uDate != '' + ? TestResultChip( + deviceBlockSize: _deviceBlockSize, + label: 'Until Date', + id: testResult.filters.id, + labelID: testResult.filters.labelID, + testType: testResult.filters.testType, + hospital: testResult.filters.hospital, + username: testResult.filters.userName, + fDate: testResult.filters.fDate, + uDate: '', + ) + : Container(), + ], + ), + ); + }, + ), + TestResultSearchBox( + searchCTRL: searchCTRL, + deviceBlockSize: _deviceBlockSize, + ), + SizedBox( + height: 20, + ), + Expanded( + child: Consumer( + builder: (context, testResults, _) { + return testResults.isloading + ? Center( + child: CircularProgressIndicator(), + ) + : ListView.builder( + controller: sc, + itemBuilder: (context, index) => TestItemBox( + deviceBlockSize: _deviceBlockSize, + item: testResults.items[index], + id: testResults.items[index].id, + ), + // Column( + // children: [ + // Text(testResults.items[index].name), + // Text(testResults.items[index].isVerified.toString()), + // Text(testResults.items[index].hospital), + // Text(testResults.items[index].date), + + // ], + // ), + // ChangeNotifierProvider.value( + // value: testResults.items[index], + // child: ResultCard( + // isAdmin: widget.isAdmin, + // ), + // ), + itemCount: testResults.items.length, + shrinkWrap: true, + ); + }, + ), + ), + ], + ), + ), + ); + } +} + +class TestItemBox extends StatelessWidget { + final TestResultObject item; + const TestItemBox({ + Key key, + @required String id, + @required double deviceBlockSize, + this.item, + }) : _deviceBlockSize = deviceBlockSize, + // _id = id, + super(key: key); + + final double _deviceBlockSize; + // final String _id; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Navigator.of(context).pushNamed( + Routes.testDetailsScreen, + arguments: item.id, + ), + child: Card( + child: Container( + padding: EdgeInsets.all(10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 57 * _deviceBlockSize, + child: Text( + item.name, + overflow: TextOverflow.ellipsis, + // style: TextStyle(fontSize: 20), + ), + ), + Container( + width: 57 * _deviceBlockSize, + child: Text( + item.hospital, + style: TextStyle( + color: Colors.grey, + fontSize: 3 * _deviceBlockSize, + ), + ), + ), + SizedBox( + height: 15, + ), + item.result == 'Verified' + ? Text( + 'Verified', + style: TextStyle(color: Colors.blueAccent), + ) + : Text( + 'Awaiting Verification', + style: TextStyle( + color: Colors.orange, + ), + ), + ], + ), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(item.date), + SizedBox( + height: 15, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + item.result != 'Verified' + ? InkWell( + onTap: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text('Verify'), + content: Text( + 'Are you sure for verify this test?'), + actions: [ + FlatButton( + onPressed: () { + // TestResultsProvider.updateTestResult( + // _id, + // {}) + // .then((_) { + // Navigator.of(context).pop(); + // }); + // Provider.of( + // context) + // .removeTestResult( + // item.id.toString()) + // .then((_) { + // Navigator.of(ctx).pop(); + // }); + Navigator.of(ctx).pop(); + }, + child: Text('Yes'), + ), + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('No'), + ), + ], + ), + ); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Color.fromRGBO(0, 190, 190, 1), + ), + child: Icon( + Icons.check, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ) + : Container(), + SizedBox( + width: _deviceBlockSize, + ), + InkWell( + onTap: () { + Navigator.of(context).pushNamed( + Routes.testDetailsScreen, + arguments: item.id, + ); + // TestDetail(testResultId: item.id.toString()); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.fileAlt, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ) + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/providers/auth.dart b/lib/providers/auth.dart new file mode 100644 index 0000000..92d6e2c --- /dev/null +++ b/lib/providers/auth.dart @@ -0,0 +1,183 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:cssd/config/user.dart'; +import 'package:flutter/material.dart'; +import 'package:cssd/config/urls.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; + +class Auth with ChangeNotifier { + String _token; + DateTime _expiaryDate; + + Map _user = {}; + + bool get isAuth { + return token != null; + } + + String get token { + if (_expiaryDate != null && + _expiaryDate.isAfter(DateTime.now()) && + _token != null) { + return _token; + } + return null; + } + + Map get user { + return {..._user}; + } + + Future login(String cellNumber, String password) async { + final response = await http.post( + Url.login, + body: { + 'cell_number': cellNumber, + 'password': password, + }, + // headers: {'X-Requested-With': 'XMLHttpRequest'}, + ); + final responseData = json.decode(response.body); + // print(responseData); + if (response.statusCode == 401) { + if (responseData['message'] == 'The user credentials were incorrect.') { + return 'badinput'; // incorrect user or pass + } + else{ + return 'error'; + } + } + _token = responseData['access_token']; + _expiaryDate = DateTime.now().add( + Duration( + seconds: responseData['expires_in'], + ), + ); + User.token = _token; + // print(isAuth); + + // print(User.token); + var localUser = await getUserData(); + // print("------ in auth ==========="); + print(localUser); + + final prefs = await SharedPreferences.getInstance(); + final userData = json.encode({ + 'token': _token, + 'expiaryDate': _expiaryDate.toIso8601String(), + 'user': user + }); + prefs.setString('userData', userData); + notifyListeners(); + return 'true'; + } + + Future tryAutoLogin() async { + final prefs = await SharedPreferences.getInstance(); + if (!prefs.containsKey('userData')) { + return false; + } + final userData = + json.decode(prefs.getString('userData')) as Map; + final expiaryDate = DateTime.parse(userData['expiaryDate']); + if (expiaryDate.isBefore(DateTime.now())) { + return false; + } + _token = userData['token']; + _expiaryDate = expiaryDate; + _user = userData['user']; + User.token = _token; + notifyListeners(); + return true; + } + + Future> getUserData() async { + final response = await http.get( + Url.getUserInfo, + headers: {'Authorization': 'Bearer ' + token}, + ); + // print(response.body); + if (response.statusCode == 200) { + var data = json.decode(response.body)['data']; + _user.addAll( + { + 'id': data['user']['id'], + 'name': data['user']['name'], + 'email': data['user']['email'], + 'cell_number': data['user']['cell_number'], + 'address': data['user']['address'], + 'gender': data['user']['gender'], + 'medical_center': data['user']['medical_center']['name'], + 'roles': data['roles'], + }, + ); + // print(_user); + notifyListeners(); + return _user; + } else { + return {}; + } + } + + Future setUserData(id, name, email) async { + var response = await http.post( + 'https://cssd-doc.com/api/UpdateInfo', + headers: { + 'Authorization': 'Bearer ' + token, + HttpHeaders.contentTypeHeader: 'application/json', + }, + body: json.encode( + { + "id": id, + "name": name, + "email": email, + // "country_code": "0098", + // "cell_number": "09338736511", + // "gender": "Male", + // "verified": "Verified", + // "status": "Active", + // "medical_center_id": 1, + // "address": null, + // "created_at": null, + // "updated_at": "2020-04-23 21:54:52", + // "medical_center": { + // "id": 1, + // "name": "B", + // "address": "1", + // "phone_number": "12345678951", + // "city_id": 1, + // "created_at": null, + // "updated_at": "2020-01-12 05:38:35" + // }, + // "roles": [ + // { + // "id": 1, + // "name": "Admin", + // "guard_name": "web", + // "created_at": null, + // "updated_at": null, + // "pivot": { + // "model_id": 1, + // "role_id": 1, + // "model_type": "App\\User", + // }, + // }, + // ], + }, + ), + ); + print(response.body); + } + + void logout() async { + _token = null; + _expiaryDate = null; + _user = {}; + User.token = null; + final prefs = await SharedPreferences.getInstance(); + prefs.remove('userData'); + notifyListeners(); + } +} diff --git a/lib/providers/connectivity.dart b/lib/providers/connectivity.dart new file mode 100644 index 0000000..e0976eb --- /dev/null +++ b/lib/providers/connectivity.dart @@ -0,0 +1,31 @@ + +import 'package:flutter/material.dart'; +import 'package:connectivity/connectivity.dart'; + +class ConnectivityProvider extends ChangeNotifier { + String conStatus = ''; + + checkConnection() { + Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + conStatus = _getStatus(result); + notifyListeners(); + }); + } + + String _getStatus(ConnectivityResult result) { + switch (result) { + case ConnectivityResult.wifi: + return 'wifi'; + break; + case ConnectivityResult.mobile: + return 'calcular'; + break; + case ConnectivityResult.none: + return 'offline'; + break; + default: + return 'offline'; + break; + } + } +} diff --git a/lib/providers/cycles.dart b/lib/providers/cycles.dart new file mode 100644 index 0000000..ca267b0 --- /dev/null +++ b/lib/providers/cycles.dart @@ -0,0 +1,262 @@ +import 'dart:convert'; + +import 'package:cssd/config/urls.dart'; +import 'package:cssd/config/user.dart'; +import 'package:cssd/models/cycles_models.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +class CyclesProvider extends ChangeNotifier { + List labelVals = []; + List labelValues = []; + String initialLabelValue = ''; + int curLabelVal = 1; + + resetLabelVals() { + labelVals = []; + labelValues = []; + initialLabelValue = ''; + curLabelVal = 1; + // notifyListeners(); + } + + addLabelVal() { + curLabelVal += 1; + TextEditingController lbl = new TextEditingController(); + lbl.text = initialLabelValue; + labelValues.add(lbl); + notifyListeners(); + } + + changeLabelVal(String value, int index) { + labelValues[index].text = value; + notifyListeners(); + } + + String searchBoxValue = ''; + bool filterOn = false; + List items; + List originalItems; //before do search on results + + CycleDetailObject result; + CycleFilterObject filters = CycleFilterObject( + id: '', + cycleNumber: '', + sterilizerId: '', + hospital: '', + date: '', + ); + int pageNumber = 1; + void resetPageNumber() => pageNumber = 1; + bool isloading = false; + void resetLoading() { + isloading = false; + notifyListeners(); + } + + void setLoading() { + isloading = true; + // notifyListeners(); + } + + Future>> getHospitalsFilters() async { + var response = await http.get( + Url.filterItems, + headers: { + 'Authorization': User.token, + }, + ); + List> result = []; + var filterDatas = json.decode(response.body); + for (var hospital in filterDatas['data']['MedicalCenters']) { + result.add({ + 'name': hospital['name'].toString(), + 'id': hospital['id'].toString() + }); + // print(hospital['name']); + } + return result; + } + + Future> getLabelFilters() async { + var response = await http.get( + Url.labelItems, + headers: { + 'Authorization': User.token, + }, + ); + List result = []; + var filterDatas = json.decode(response.body); + for (var label in filterDatas['data']) { + result.add(label['id'].toString()); + // print(hospital['name']); + } + labelVals = result; + initialLabelValue = labelVals[0]; + TextEditingController newLbl = new TextEditingController(); + newLbl.text = initialLabelValue; + labelValues.add(newLbl); + notifyListeners(); + return result; + } + + Future createCycleResult( + cycleNumber, date, labels, note, sterilizerId) async { + List> labs = []; + for (var label in labels) { + labs.add({'name': '', 'id': label}); + } + // print(labs); + var response = await http.post(Url.createCycleResult, + body: json.encode( + { + 'note': note, + 'labels': labs, + 'cycle_number': cycleNumber, + 'date': date, + 'sterilizer_id': sterilizerId, + }, + ), + headers: { + 'Authorization': User.token, + 'X-Requested-With': 'XMLHttpRequest', + "Content-Type": "application/json", + "Accept": "application/json" + }); + + print(response.body); + } + + void setFilters(id, cycleNumber, sterilizerId, hospital, date) { + pageNumber = 1; + filters = CycleFilterObject( + id: id, + cycleNumber: cycleNumber, + sterilizerId: sterilizerId, + hospital: hospital, + date: date, + ); + if (filters.id == '' && + filters.cycleNumber == '' && + filters.sterilizerId == '' && + filters.hospital == '' && + filters.date == '') { + filterOn = false; + } else { + filterOn = true; + } + notifyListeners(); + } + + void search(String value) { + items = []; + searchBoxValue = value; + originalItems.forEach((result) { + if (result.id.toString().contains(searchBoxValue)) { + items.add(result); + } + }); + notifyListeners(); + } + + Future getCycleResults() async { + String url = Url.cycleResults(pageNumber); + if (filterOn) { + items = []; + if (filters.id != '') { + url += '&cycle_id=${filters.id}'; + } + if (filters.cycleNumber != '') { + url += '&cycle_number=${filters.cycleNumber}'; + } + if (filters.sterilizerId != '') { + url += '&sterilizer_id=${filters.sterilizerId}'; + } + if (filters.hospital != '') { + url += '&medical_center_id=${filters.hospital}'; + } + if (filters.date != '') { + url += '&date=${filters.date}'; + } + } + // print(url); + var response = await http.get( + url, + headers: { + 'Authorization': User.token, + }, + ); + + var testResultData = json.decode(response.body); + List labels = []; + if (pageNumber == 1) { + originalItems = []; + items = []; + } + + for (var item in testResultData['data']['data']) { + // print(item); + labels = []; + for (var label in item['labels']) { + // print(label['id']); + labels.add(label['id'].toString()); + } + originalItems.add( + CycleResultObject( + createdAt: item['date'], + id: item['id'].toString(), + label: labels, + ), + ); + } + pageNumber += 1; + search(''); + } + + Future showCycleResult(String id) async { + var response = await http.get(Url.getCycleResult(id), headers: { + 'Authorization': User.token, + }); + if (response.statusCode != 200) { + return CycleDetailObject( + id: 'null', + description: 'null', + createDate: 'null', + date: '2020-01-01', + sterileId: 'null', + cycleNumber: 'null', + labels: [], + ); + } + var data = json.decode(response.body)['data']; + List lablesList = []; + for (var label in data['labels']) { + lablesList.add(label['id'].toString()); + } + result = CycleDetailObject( + id: data['id'].toString(), + description: data['note'] != null ? data['note'] : '', + createDate: data['created_at'] != null ? data['created_at'] : '', + date: data['date'] != null ? data['date'] : '', + sterileId: data['sterilizer_id'] != null ? data['sterilizer_id'] : '', + cycleNumber: data['cycle_number'] != null ? data['cycle_number'] : '', + labels: lablesList, + ); + // result = { + // 'id': data['id'], + // 'auto_cleave_id': data['inputs']['Autoclave ID'], + // 'test_code': data['test_type_id'], + // 'date': data['created_at'], + // 'verified': data['verified'], + // 'description': data['inputs']['Note'], + // 'test_type_name': data['test_type']['name'], + + // // 'device_label': data['device_label'], + // // 'device_id': data['device_id'], + // // 'result': data['result'], + // // 'user_name': data['user']['name'], + // // 'medical_center': data['user']['medical_center']['name'], + // }; + return result; + } +} diff --git a/lib/providers/input.dart b/lib/providers/input.dart new file mode 100644 index 0000000..0f49ef1 --- /dev/null +++ b/lib/providers/input.dart @@ -0,0 +1,101 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:cssd/config/urls.dart'; +import 'package:cssd/config/user.dart'; + +class Inputs with ChangeNotifier { + + List> inputItems = []; + + Future getInputs({String testResultId = "", String name = "", String uniqueCode = "", String testTypeId = ""}) async { + print({ + 'test_type_id': testTypeId, + 'test_result_id': testResultId, + 'name': name, + 'unique_code': uniqueCode, + },); + var response = await http.post( + Url.getInputs, + body: { + 'test_type_id': testTypeId, + 'test_result_id': testResultId, + 'name': name, + 'unique_code': uniqueCode, + }, + headers: { + 'Authorization': User.token, + 'X-Requested-With': 'XMLHttpRequest', + }, + ); + if (response.statusCode != 200) { + inputItems = []; + notifyListeners(); + return false; + } + final responseData = json.decode(response.body); + + // print(responseData); + + Map values; + if (testResultId.isNotEmpty) { + response = await http.get(Url.testResultFormValues(testResultId), + headers: { + 'Authorization': User.token + }); + values = json.decode(response.body)['data']; + } + + var inputs = responseData['data']['inputs'] as List; + var general = responseData['data']['testType'] as Map; + + clearInputs(); + bool result = false; + DateTime dateTime = DateTime.now(); + String deviceLabel; + if (values != null && values.isNotEmpty) { + result = values['result'] == 'Accept' ? true : false; + dateTime = values['date'] == null ? DateTime.now() : DateTime.parse(values['date']); + deviceLabel = values['device_id'] ?? ''; + } + + inputItems.add({'type': 'Label', 'key': 'test_type_id', 'name': general['name'], 'value': general['id']}); + + inputItems.add({'type': 'Text', 'key': 'device_id', 'name': general['device_label'], 'value': deviceLabel}); + inputItems.add({'type': 'Date', 'key': 'date' , 'name': 'date', 'value': dateTime}); + inputItems.add({'type': 'Switch', 'key': 'result', 'name': 'Result', 'value': result}); + + setValues(inputs, values); + for (var input in inputs) { + inputItems.add(input as Map); + } + notifyListeners(); + return true; + } + + void setValues(inputs, values) { + for (var input in inputs) { + if (input.containsKey('children')) { + setValues(input['children'], values); + } + var key = "${input['name']}_${input['id']}"; + input['key'] = key; + if(values != null && values.isNotEmpty && values.containsKey(key)) { + if (input['type'] == 'Range' || input['type'] == 'Temperature' || input['type'] == 'Pressure') { + input['value'] = double.parse(values[key]); + } else if (input['type'] == 'Switch'){ + input['value'] = values[key] == "1" ? true : false; + } else if (input['type'] == 'Time'){ + input['value'] = values[key] == null ? '' : values[key].substring(0, 2) + ":" + values[key].substring(2, 4); + } else { + input['value'] = values[key]; + } + } + } + } + + void clearInputs() { + inputItems.clear(); + } +} diff --git a/lib/providers/labels.dart b/lib/providers/labels.dart new file mode 100644 index 0000000..133ce00 --- /dev/null +++ b/lib/providers/labels.dart @@ -0,0 +1,213 @@ +import 'dart:convert'; + +import 'package:cssd/config/urls.dart'; +import 'package:cssd/config/user.dart'; +import 'package:cssd/models/label_models.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +class LabelsProvider extends ChangeNotifier { + String searchBoxValue = ''; + bool filterOn = false; + List items; + List originalItems; + + LabelDetailsObject result; + LabelFilterObject filters = LabelFilterObject( + id: '', + cycleNumber: '', + sterilizerId: '', + hospital: '', + ); + int pageNumber = 1; + void resetPageNumber() => pageNumber = 1; + bool isloading = false; + void resetLoading() { + isloading = false; + notifyListeners(); + } + + void setLoading() { + isloading = true; + // notifyListeners(); + } + + Future>> getHospitalsFilters() async { + var response = await http.get( + Url.filterItems, + headers: { + 'Authorization': User.token, + }, + ); + List> result = []; + var filterDatas = json.decode(response.body); + for (var hospital in filterDatas['data']['MedicalCenters']) { + result.add({ + 'name': hospital['name'].toString(), + 'id': hospital['id'].toString() + }); + // print(hospital); + } + return result; + } + + Future>> getPackageFilters() async { + var response = await http.get( + Url.packageItems, + headers: { + 'Authorization': User.token, + }, + ); + List> result = []; + var filterDatas = json.decode(response.body); + // print(filterDatas); + for (var package in filterDatas['data']) { + result.add( + { + 'name': package['name'].toString(), + 'id': package['id'].toString(), + }, + ); + // print(hospital['name']); + } + // print(result); + return result; + } + + Future createLabelResult(lotNumber, cycleNumber, sterileDate, package, + expireDate, sterilizerId) async { + // print(labs); + var response = await http.post(Url.createLabelResult, + body: json.encode( + { + 'sterile_date': sterileDate, + 'expire_date': expireDate, + 'sterilizer_id': sterilizerId, + 'cycle_number': cycleNumber, + 'lot_number': lotNumber, + 'package_id': package['id'] + // 'package': { + // 'id': package['id'], + // 'name': package['name'], + // }, + }, + ), + headers: { + 'Authorization': User.token, + 'X-Requested-With': 'XMLHttpRequest', + "Content-Type": "application/json", + "Accept": "application/json" + }); + + print(response.body); + } + + void setFilters(id, cycleNumber, sterilizerId, hospital) { + pageNumber = 1; + filters = LabelFilterObject( + id: id, + cycleNumber: cycleNumber, + sterilizerId: sterilizerId, + hospital: hospital, + ); + if (filters.id == '' && + filters.cycleNumber == '' && + filters.sterilizerId == '' && + filters.hospital == '') { + filterOn = false; + } else { + filterOn = true; + } + notifyListeners(); + } + + void search(String value) { + items = []; + searchBoxValue = value; + originalItems.forEach((result) { + if (result.id.toString().contains(searchBoxValue)) { + items.add(result); + } + }); + notifyListeners(); + } + + Future getLabelResults() async { + String url = Url.labelResults(pageNumber); + if (filterOn) { + items = []; + // url = Url.labelResults(pNum); + if (filters.id != '') { + url += '&label_id=${filters.id}'; + } + if (filters.hospital != '') { + url += '&medical_center_id=${filters.hospital}'; + } + if (filters.sterilizerId != '') { + url += '&sterilizer_id=${filters.sterilizerId}'; + } + if (filters.cycleNumber != '') { + url += '&cycle_number=${filters.cycleNumber}'; + } + } + + var response = await http.get( + url, + headers: { + 'Authorization': User.token, + }, + ); + + var testResultData = json.decode(response.body); + if (pageNumber == 1) { + originalItems = []; + items = []; + } + + for (var item in testResultData['data']['data']) { + originalItems.add( + LabelResultObject( + expireDate: item['expire_date'], + id: item['id'].toString(), + package: item['package']['name'], + ), + ); + } + pageNumber += 1; + search(''); + } + + Future showLabelResult(String id) async { + var response = await http.get( + Url.getLabelResult(id), + headers: { + 'Authorization': User.token, + }, + ); + if (response.statusCode != 200) { + return LabelDetailsObject( + id: 'null', + package: 'null', + createDate: 'null', + expireDate: 'null', + sterileDate: 'null', + sterileId: 'null', + cycleNumber: 'null', + lotNumber: 'null', + ); + } + + var data = json.decode(response.body)['data']; + result = LabelDetailsObject( + id: data['id'].toString(), + package: data['package']['name'] != null ? data['package']['name'] : '', + createDate: data['created_at'] != null ? data['created_at'] : '', + expireDate: data['expire_date'] != null ? data['expire_date'] : '', + sterileDate: data['sterile_date'] != null ? data['sterile_date'] : '', + sterileId: data['sterilizer_id'] != null ? data['sterilizer_id'] : '', + cycleNumber: data['cycle_number'] != null ? data['cycle_number'] : '', + lotNumber: data['lot_number'] != null ? data['lot_number'] : '', + ); + return result; + } +} diff --git a/lib/providers/my_info.dart b/lib/providers/my_info.dart new file mode 100644 index 0000000..2af2117 --- /dev/null +++ b/lib/providers/my_info.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:cssd/config/urls.dart'; + +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class MyInfoProvider extends ChangeNotifier { + Map _user = {}; + Map get user { + return {..._user}; + } + + String _token; + + Future setToken() async { + final prefs = await SharedPreferences.getInstance(); + if (!prefs.containsKey('auth')) { + return false; + } + final auth = json.decode(prefs.getString('auth')) as Map; + _token = auth['token']; + notifyListeners(); + } + + Future> getUserData() async { + final prefs = await SharedPreferences.getInstance(); + final auth = json.decode(prefs.getString('auth')) as Map; + _token = auth['token']; + final response = await http.get( + Url.getUserInfo, + headers: { + 'Authorization': 'Bearer ' + _token, + }, + ); + print(response.body); + + if (response.statusCode == 200) { + var data = json.decode(response.body)['data']; + _user.addAll( + { + 'id': data['user']['id'], + 'name': data['user']['name'], + 'email': data['user']['email'], + 'cell_number': data['user']['cell_number'], + 'address': data['user']['address'], + 'gender': data['user']['gender'], + 'medical_center': data['user']['medical_center']['name'], + 'roles': data['roles'], + }, + ); + final prefs = await SharedPreferences.getInstance(); + prefs.setString('userData', json.encode(_user)); + return _user; + } else { + return {}; + } + } +} diff --git a/lib/providers/test_result_old.dart b/lib/providers/test_result_old.dart new file mode 100644 index 0000000..363630a --- /dev/null +++ b/lib/providers/test_result_old.dart @@ -0,0 +1,38 @@ +import 'package:cssd/config/urls.dart'; +import 'package:cssd/config/user.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +class TestResult with ChangeNotifier{ + final int id; + final String name; + final String date; + final String deviceId; + String result; + + bool get isVerified { + return result == 'Verified'; + } + + TestResult({ + this.id, + this.name, + this.date, + this.deviceId, + this.result, + }); + + Future toggleVerify() async { + final response = await http.post( + Url.verifyTest(id), headers: { + 'Authorization': User.token + } + ); + + if (response.statusCode == 200) { + result = result == 'Verified' ? 'NotVerified' : 'Verified'; + notifyListeners(); + } + + } +} diff --git a/lib/providers/test_results.dart b/lib/providers/test_results.dart new file mode 100644 index 0000000..e677e33 --- /dev/null +++ b/lib/providers/test_results.dart @@ -0,0 +1,241 @@ +import 'dart:convert'; + +import 'package:cssd/config/urls.dart'; +import 'package:cssd/config/user.dart'; +import 'package:cssd/models/test_result_models.dart'; +// import 'package:cssd/providers/test_result.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +class TestResultsProvider with ChangeNotifier { + String searchBoxValue = ''; + bool filterOn = false; + List items; + List originalItems; + // List items = []; + Map result; + + TestResultFilterObject _filters = TestResultFilterObject( + id: '', + labelID: '', + userName: '', + hospital: '', + testType: '', + fDate: '', + uDate: '', + ); + + void resetFilters() { + filterOn = false; + _filters = TestResultFilterObject( + id: '', + labelID: '', + userName: '', + hospital: '', + testType: '', + fDate: '', + uDate: '', + ); + } + + int pageNumber = 1; + void resetPageNumber() => pageNumber = 1; + bool isloading = false; + void resetLoading() { + isloading = false; + notifyListeners(); + } + + void setLoading() { + isloading = true; + // notifyListeners(); + } + + TestResultFilterObject get filters { + return _filters; + } + + void search(String value) { + print(value); + items = []; + searchBoxValue = value; + originalItems.forEach((result) { + if (result.name.toString().contains(searchBoxValue)) { + items.add(result); + } + }); + notifyListeners(); + } + + void setFilters(id, labelId, username, testType, hospital, fDate, uDate) { + pageNumber = 1; + _filters = TestResultFilterObject( + id: id, + labelID: labelId, + userName: username, + hospital: hospital, + testType: testType, + fDate: fDate, + uDate: uDate); + if (_filters.id == '' && + _filters.labelID == '' && + _filters.testType == '' && + _filters.hospital == '' && + _filters.userName == '' && + _filters.fDate == '' && + _filters.uDate == '') { + filterOn = false; + } else { + filterOn = true; + } + notifyListeners(); + } + + Future>> getFilterItems() async { + var response = await http.get( + Url.filterItems, + headers: { + 'Authorization': User.token, + }, + ); + List> result = []; + Map hospitals = {}; + Map testTypes = {}; + + var filterDatas = json.decode(response.body); + for (var hospital in filterDatas['data']['MedicalCenters']) { + hospitals.addAll({hospital['name']: hospital['id'].toString()}); + } + result.add(hospitals); + for (var testType in filterDatas['data']['TestTypes']) { + testTypes.addAll({testType['name']: testType['id'].toString()}); + } + result.add(testTypes); + + return result; + } + + Future getTestResults() async { + String url = Url.testResults(pageNumber); + if (filterOn) { + items = []; + if (_filters.id != '') { + url += '&device_id=${_filters.id}'; + } + if (_filters.labelID != '') { + url += '&device_label=${_filters.labelID}'; + } + if (_filters.hospital != '') { + url += '&medicalCenter_id=${_filters.hospital}'; + } + if (_filters.testType != '') { + url += '&testType_id=${_filters.testType}'; + } + if (_filters.userName != '') { + url += '&user_name=${_filters.userName}'; + } + if (_filters.fDate != '') { + url += '&fromPicker=${_filters.fDate}'; + } + if (_filters.uDate != '') { + url += '&upToPicker=${_filters.uDate}'; + } + print(url); + } + //'device_id=3526&testType_id=107&medicalCenter_id=2&user_name=erfan&fromPicker=2020-05-12&upToPicker=2020-05-19&device_label=Instrument%20ID&page=1' + var response = await http.get( + url, + headers: { + 'Authorization': User.token, + }, + ); + + var testResultData = json.decode(response.body); + + if (pageNumber == 1) { + originalItems = []; + items = []; + } + for (var item in testResultData['data']['data']) { + originalItems.add( + TestResultObject( + id: item['id'].toString(), + name: item['test_type']['name'], + deviceId: item['device_id'].toString(), + result: item['verified'] == 'Verified' ? 'Verified' : 'Not Verified', + date: item['date'], + hospital: item['user']['medical_center']['name'], + ), + ); + } + pageNumber += 1; + search(''); + notifyListeners(); + } + + static Future updateTestResult(String id, values) async { + var response = await http.post( + Url.updateTestResult(id), + body: json.encode(values), + headers: { + 'Authorization': User.token, + 'X-Requested-With': 'XMLHttpRequest', + "Content-Type": "application/json", + "Accept": "application/json" + }, + ); + print(response.body); + } + + static Future createTestResult(values) async { + var response = await http + .post(Url.createTestResult, body: json.encode(values), headers: { + 'Authorization': User.token, + 'X-Requested-With': 'XMLHttpRequest', + "Content-Type": "application/json", + "Accept": "application/json" + }); + + print(response.body); + } + + Future> showTestResult(String id) async { + var response = await http.get(Url.getTestResult(id), headers: { + 'Authorization': User.token, + }); + + var data = json.decode(response.body)['data']; + // print(data); + result = { + 'id': data['id'], + 'auto_cleave_id': data['inputs']['Autoclave ID'] != null + ? data['inputs']['Autoclave ID'] + : '', + 'test_code': data['test_type_id'] != null ? data['test_type_id'] : '', + 'date': data['created_at'] != null ? data['created_at'] : '', + 'verified': data['verified'] != null ? data['verified'] : '', + 'description': + data['inputs']['Note'] != null ? data['inputs']['Note'] : '', + 'test_type_name': + data['test_type']['name'] != null ? data['test_type']['name'] : '', + }; + return result; + } + + Future removeTestResult(String id) async { + var response = await http.post(Url.removeTestResult(id), body: { + '_method': 'delete' + }, headers: { + 'Authorization': User.token, + }); + + if (response.statusCode == 200) { + items.removeWhere((item) { + return item.id.toString() == id; + }); + } + + notifyListeners(); + return true; + } +} diff --git a/lib/widgets/CycleScreens/Add/add_label_box.dart b/lib/widgets/CycleScreens/Add/add_label_box.dart new file mode 100644 index 0000000..fd577f0 --- /dev/null +++ b/lib/widgets/CycleScreens/Add/add_label_box.dart @@ -0,0 +1,250 @@ +import 'package:barcode_scan/barcode_scan.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/cycles.dart'; + +class CycleAddLabelBox extends StatelessWidget { + const CycleAddLabelBox({ + Key key, + @required double deviceBlockSize, + @required this.labelValues, + @required this.labelVals, + @required this.initialLabelValue, + @required this.index, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController labelValues; + final List labelVals; + final String initialLabelValue; + final int index; + + @override + Widget build(BuildContext context) { + return Container( + // color: Colors.blue, + height: 150, + child: Stack( + children: [ + Container( + padding: EdgeInsets.only( + right: 10, + bottom: 30, + left: 10, + top: 10, + ), + decoration: BoxDecoration( + border: Border( + left: BorderSide(color: Colors.black, width: 2), + right: BorderSide(color: Colors.grey), + bottom: BorderSide(color: Colors.grey), + top: BorderSide(color: Colors.grey), + ), + ), + height: 120, + child: Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 7 * _deviceBlockSize, + ), + SizedBox( + width: 4 * _deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + SizedBox( + width: _deviceBlockSize, + ), + Text( + 'Select Labels Included', + style: TextStyle( + fontSize: 3.5 * _deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w100, + ), + ), + ], + ), + Row( + children: [ + Container( + width: MediaQuery.of(context).size.width - + (40 * _deviceBlockSize), + // height: 30, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + left: _deviceBlockSize, + ), + border: InputBorder.none, + ), + iconSize: 7 * _deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric( + horizontal: 0), + child: TextFormField( + controller: labelValues, + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + bottom: 12, + ), + isDense: true, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + isDense: true, + items: labelVals.map((val) { + return new DropdownMenuItem( + value: val, + child: Container( + child: Text( + val, + style: TextStyle( + fontSize: 4 * _deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + Provider.of(context, + listen: false) + .changeLabelVal(val, index); + // setState(() { + // labelValues[index] + // .text = val; + // }); + }, + ), + ), + Spacer(), + InkWell( + onTap: () { + scan().then( + (String result) { + if (result == 'cancel') { + print('cancel'); + } else if (result == 'error') { + print('error'); + } else if (result == 'access') { + print('access'); + } else { + print(result); + Provider.of(context, + listen: false) + .changeLabelVal(result, index); + // Navigator.of(context).pushNamed( + // CycleDetailScreen.route, + // arguments: result, + // ); + } + }, + ); + }, + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.barcode, + size: 5 * _deviceBlockSize, + color: Colors.white, + ), + ), + ) + ], + ), + ]), + ), + ], + ), + ), + ), + Positioned( + bottom: 15, + right: 0, + child: InkWell( + onTap: () { + Provider.of(context).addLabelVal(); + // setState( + // () { + // curLabelVal += 1; + // TextEditingController lbl = + // new TextEditingController(); + // lbl.text = initialLabelValue; + // labelValues.add(lbl); + // }, + // ); + }, + child: Container( + padding: EdgeInsets.all(3), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.deepOrange, + ), + child: Icon( + Icons.add, + color: Colors.white, + ), + ), + ), + ), + ], + ), + ); + } + + Future scan() async { + try { + var barcode = await BarcodeScanner.scan(); + if (barcode.type.name == 'Cancelled') { + return 'cancel'; + } else if (barcode.type.name == 'Failed') { + return 'error'; + } + try { + var id = barcode.rawContent.contains('www.cssd-doc.com') + ? barcode.rawContent.split('/')[5] + : barcode.rawContent; + + return id; + } catch (_) { + return 'null'; + } + } on PlatformException catch (_) { + return 'access'; + } catch (_) { + return 'error'; + } + } +} diff --git a/lib/widgets/CycleScreens/Add/date_picker.dart b/lib/widgets/CycleScreens/Add/date_picker.dart new file mode 100644 index 0000000..45857f8 --- /dev/null +++ b/lib/widgets/CycleScreens/Add/date_picker.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +class CycleAddDatePicker extends StatefulWidget { + const CycleAddDatePicker({ + Key key, + @required this.dateCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, super(key: key); + + final TextEditingController dateCTRL; + final double _deviceBlockSize; + + @override + _CycleAddDatePickerState createState() => _CycleAddDatePickerState(); +} + +class _CycleAddDatePickerState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () async { + var res = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2010, 1), + lastDate: DateTime(2101), + ); + if (res != null) { + // dateTimeFrom = res; + setState( + () { + widget.dateCTRL.text = DateFormat('y-M-d').format(res); + // dateValue = DateFormat('y-M-d').format( + // dateTimeFrom, + // ); // baraye tavize makane gharar giri baraye api + }, + ); + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: TextField( + enabled: false, + controller: widget.dateCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.alignLeft, + size: 7 * widget._deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * widget._deviceBlockSize, + ), + labelText: 'Date', + isDense: true, + contentPadding: EdgeInsets.only( + bottom: 7, + right: 3, + left: 3, + ), + // border: InputBorder.none, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * widget._deviceBlockSize, + ), + ), + ), + Icon(FontAwesomeIcons.angleDown) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/CycleScreens/Add/save_button.dart b/lib/widgets/CycleScreens/Add/save_button.dart new file mode 100644 index 0000000..8a770da --- /dev/null +++ b/lib/widgets/CycleScreens/Add/save_button.dart @@ -0,0 +1,90 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/cycles.dart'; + +class CycleAddSaveButton extends StatelessWidget { + const CycleAddSaveButton({ + Key key, + @required GlobalKey form, + @required this.labelValues, + @required this.cycleNumberCTRL, + @required this.dateValue, + @required this.descriptionCTRL, + @required this.striizerIdCTRL, + @required double deviceBlockSize, + }) : _form = form, + _deviceBlockSize = deviceBlockSize, + super(key: key); + + final GlobalKey _form; + final List labelValues; + final TextEditingController cycleNumberCTRL; + final String dateValue; + final TextEditingController descriptionCTRL; + final TextEditingController striizerIdCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (!_form.currentState.validate()) { + return; + } + + List labels = []; + for (TextEditingController label in labelValues) { + labels.add(label.text); + } + Provider.of(context).createCycleResult( + cycleNumberCTRL.text, + dateValue, + labels, + descriptionCTRL.text, + striizerIdCTRL.text, + ); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Cycle added.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then((_) { + Navigator.of(context).pushReplacementNamed(Routes.cycleResultScreen); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.red, Colors.orange], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'SAVE', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/CycleScreens/Details/datas_box.dart b/lib/widgets/CycleScreens/Details/datas_box.dart new file mode 100644 index 0000000..8787cbf --- /dev/null +++ b/lib/widgets/CycleScreens/Details/datas_box.dart @@ -0,0 +1,231 @@ +import 'package:cssd/models/cycles_models.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class CycleDetailsDataBox extends StatelessWidget { + const CycleDetailsDataBox({ + Key key, + @required this.datas, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final CycleDetailObject datas; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(20), + child: ListView(children: [ + SizedBox( + height: 10, + ), + Text( + 'CYCLE DETAILS', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + letterSpacing: 3, + ), + ), + SizedBox( + height: 10, + ), + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Color.fromRGBO(235, 235, 235, 1), + border: Border( + left: BorderSide( + color: Colors.black54, + width: 2, + ), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + DateFormat.yMMMd().format( + DateTime.parse( + datas.createDate, + ), + ), + style: TextStyle( + color: Colors.red, + ), + ), + Divider(), + Text( + 'ID: ${datas.id}', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.w700, + ), + ), + SizedBox( + height: 30, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Sterilizer ID', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.sterileId.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Cycle Number', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.cycleNumber.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Date', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + DateFormat('d-M-y').format( + DateTime.parse( + datas.date, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Description', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.description.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 30, + ), + Text( + 'LABELS INCLUDED', + style: TextStyle( + color: Colors.orange, + letterSpacing: 3, + fontWeight: FontWeight.w700, + fontSize: 4.5 * _deviceBlockSize, + ), + ), + Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: Colors.grey, + ), + ), + child: ListView.separated( + shrinkWrap: true, + itemBuilder: (ctx, index) => RichText( + text: TextSpan( + text: 'Label ID ', + style: TextStyle(color: Colors.grey,fontFamily: 'montserrat',), + // style: DefaultTextStyle.of(context).style, + children: [ + TextSpan( + text: datas.labels[index], + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.orange, + ), + ), + ], + ), + ), + separatorBuilder: (ctx, index) => Divider(), + itemCount: datas.labels.length, + ), + + ), + SizedBox(height: 50,) + ], + ), + ), + ]), + ); + } +} diff --git a/lib/widgets/CycleScreens/Filter/date_picker.dart b/lib/widgets/CycleScreens/Filter/date_picker.dart new file mode 100644 index 0000000..641bf22 --- /dev/null +++ b/lib/widgets/CycleScreens/Filter/date_picker.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +class CycleFilterDatePicker extends StatefulWidget { + const CycleFilterDatePicker({ + Key key, + @required this.dateCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final TextEditingController dateCTRL; + final double _deviceBlockSize; + + @override + _CycleFilterDatePickerState createState() => _CycleFilterDatePickerState(); +} + +class _CycleFilterDatePickerState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () async { + var res = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2010, 1), + lastDate: DateTime(2101), + ); + if (res != null) { + // dateTimeFrom = res; + setState( + () { + widget.dateCTRL.text = DateFormat('y-M-d').format(res); + // dateValue = DateFormat('y-M-d').format( + // dateTimeFrom, + // ); // baraye tavize makane gharar giri baraye api + }, + ); + } + }, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: TextField( + enabled: false, + controller: widget.dateCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.calendarAlt, + size: 7 * widget._deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * widget._deviceBlockSize, + ), + labelText: 'Date', + isDense: true, + contentPadding: EdgeInsets.only( + bottom: 5, + left: 2, + ), + // border: InputBorder.none, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * widget._deviceBlockSize, + ), + ), + ), + Icon(FontAwesomeIcons.angleDown) + ], + ), + // Divider( + // color: Colors.grey, + // ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/CycleScreens/Filter/save_button.dart b/lib/widgets/CycleScreens/Filter/save_button.dart new file mode 100644 index 0000000..8b92064 --- /dev/null +++ b/lib/widgets/CycleScreens/Filter/save_button.dart @@ -0,0 +1,89 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/cycles.dart'; + +class CycleFilterSaveButton extends StatelessWidget { + const CycleFilterSaveButton({ + Key key, + @required this.hospitalVals, + @required this.hospitalCTRL, + @required this.cycleIdCTRL, + @required this.cycleNumberCTRL, + @required this.striizerIdCTRL, + @required this.dateCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final List> hospitalVals; + final TextEditingController hospitalCTRL; + final TextEditingController cycleIdCTRL; + final TextEditingController cycleNumberCTRL; + final TextEditingController striizerIdCTRL; + final TextEditingController dateCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + String hospitalID; + hospitalVals.forEach( + (hospital) { + if (hospital['name'] == hospitalCTRL.text) { + hospitalID = hospital['id']; + } + }, + ); + Provider.of(context).setFilters( + cycleIdCTRL.text, + cycleNumberCTRL.text, + striizerIdCTRL.text, + hospitalID, + dateCTRL.text, + ); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Filters changed.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then((_) { + Navigator.of(context).popAndPushNamed(Routes.cycleResultScreen); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 5, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.red, Colors.orange], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'FILTER', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/CycleScreens/Filter/selector_box.dart b/lib/widgets/CycleScreens/Filter/selector_box.dart new file mode 100644 index 0000000..af04f21 --- /dev/null +++ b/lib/widgets/CycleScreens/Filter/selector_box.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +class CycleFilterSelectorBox extends StatefulWidget { + const CycleFilterSelectorBox({ + Key key, + @required double deviceBlockSize, + @required this.hospitalCTRL, + @required this.hospitalVals, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController hospitalCTRL; + final List> hospitalVals; + + @override + _CycleFilterSelectorBoxState createState() => _CycleFilterSelectorBoxState(); +} + +class _CycleFilterSelectorBoxState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 7 * widget._deviceBlockSize, + ), + SizedBox( + width: 4 * widget._deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + SizedBox( + width: widget._deviceBlockSize, + ), + Text( + 'Package', + style: TextStyle( + fontSize: 3.5 * widget._deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w100, + ), + ), + ], + ), + Container( + // height: 30, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + left: widget._deviceBlockSize, + ), + border: InputBorder.none, + ), + iconSize: 7 * widget._deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric( + horizontal: 0, + ), + child: TextFormField( + controller: widget.hospitalCTRL, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(bottom: 15), + isDense: true, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + ), + ), + ), + isDense: true, + items: widget.hospitalVals.map((val) { + return new DropdownMenuItem( + value: val['name'], + child: Container( + child: Text( + val['name'], + style: TextStyle( + // color: _mainFontColor, + fontSize: 5 * widget._deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + widget.hospitalCTRL.text = val; + // packageValue[1] = val; + // packageCTRL.text = val; + // packageVals.forEach((package) { + // if (package['name'] == val) { + // packageValue[0] = package['id']; + // } + // }); + }); + }, + ), + ), + ]), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/CycleScreens/Result/banner.dart b/lib/widgets/CycleScreens/Result/banner.dart new file mode 100644 index 0000000..33a545a --- /dev/null +++ b/lib/widgets/CycleScreens/Result/banner.dart @@ -0,0 +1,45 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class CycleResultBanner extends StatelessWidget { + const CycleResultBanner({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Row( + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + 'CYCLES', + style: TextStyle( + color: Colors.black, + fontSize: 7 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 2, + ), + ), + Spacer(), + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).popAndPushNamed(Routes.cycleFilterScreen); + }, + child: Container( + padding: EdgeInsets.all(5), + child: Icon( + FontAwesomeIcons.filter, + size: 7 * _deviceBlockSize, + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/CycleScreens/Result/data_box.dart b/lib/widgets/CycleScreens/Result/data_box.dart new file mode 100644 index 0000000..6da86ee --- /dev/null +++ b/lib/widgets/CycleScreens/Result/data_box.dart @@ -0,0 +1,139 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/cycles_models.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; + +class CycleItemBox extends StatelessWidget { + final CycleResultObject item; + final String labels; + + const CycleItemBox({ + Key key, + @required double deviceBlockSize, + this.item, + this.labels, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Navigator.of(context).pushNamed( + Routes.cycleDetailScreen, + arguments: item.id, + ), + child: Card( + elevation: 1, + child: Container( + padding: EdgeInsets.all(10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.all(8.0), + child: Text( + item.id, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + SizedBox( + width: 3 * _deviceBlockSize, + ), + // Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 50 * _deviceBlockSize, + child: Text( + 'Label Included:', + style: TextStyle( + fontSize: 3 * _deviceBlockSize, + color: Colors.grey, + ), + ), + ), + Container( + width: 50 * _deviceBlockSize, + child: Text( + labels, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 3 * _deviceBlockSize, + ), + ), + ), + Container( + width: 50 * _deviceBlockSize, + child: Row( + children: [ + Text( + 'Date:', + style: TextStyle( + color: Colors.grey, + fontSize: 3 * _deviceBlockSize, + ), + ), + Text( + DateFormat('y-M-d').format( + DateTime.parse( + item.createdAt, + ), + ), + style: TextStyle( + fontSize: 3 * _deviceBlockSize, + ), + ), + ], + ), + ) + ], + ), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushNamed( + Routes.cycleDetailScreen, + arguments: item.id, + ); + // TestDetail(testResultId: item.id.toString()); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.fileAlt, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ) + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/widgets/CycleScreens/Result/filter_objects.dart b/lib/widgets/CycleScreens/Result/filter_objects.dart new file mode 100644 index 0000000..8c50518 --- /dev/null +++ b/lib/widgets/CycleScreens/Result/filter_objects.dart @@ -0,0 +1,114 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/cycles.dart'; + +class CycleFilterBaner extends StatelessWidget { + const CycleFilterBaner({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Navigator.of(context).popAndPushNamed(Routes.cycleFilterScreen); + }, + child: Chip( + backgroundColor: Colors.black, + label: Text( + 'Filters', + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + FontAwesomeIcons.filter, + color: Colors.white, + size: 4 * _deviceBlockSize, + ), + onDeleted: () { + Navigator.of(context).popAndPushNamed(Routes.cycleFilterScreen); + }, + ), + ); + } +} + +class CycleFilterChip extends StatelessWidget { + const CycleFilterChip({ + Key key, + @required double deviceBlockSize, + @required String label, + @required String id, + @required String cycleNumber, + @required String sterilizerId, + @required String hospital, + @required String date, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + _id = id, + _cycleNumber = cycleNumber, + _sterilizerId = sterilizerId, + _hospital = hospital, + _date = date, + super(key: key); + + final double _deviceBlockSize; + final String _label; + final String _id; + final String _cycleNumber; + final String _sterilizerId; + final String _hospital; + final String _date; + + @override + Widget build(BuildContext context) { + return Row(children: [ + SizedBox( + width: _deviceBlockSize, + ), + Chip( + backgroundColor: Colors.black, + label: Text( + _label, + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + Icons.close, + color: Colors.white, + ), + onDeleted: () { + var cycleProvider = Provider.of(context); + cycleProvider.setFilters( + _id, + _cycleNumber, + _sterilizerId, + _hospital, + _date, + ); + // cycle.resetPageNumber(); + // cycle.setFilters( + // '', + // cycle.filters.cycleNumber, + // cycle.filters.sterilizerId, + // cycle.filters.hospital, + // cycle.filters.date, + // ); + cycleProvider.setLoading(); + cycleProvider.getCycleResults().then((_) { + cycleProvider.resetLoading(); + }); + // _reloadItems(); + }, + ), + ]); + } +} diff --git a/lib/widgets/CycleScreens/Result/search_box.dart b/lib/widgets/CycleScreens/Result/search_box.dart new file mode 100644 index 0000000..e5f07e4 --- /dev/null +++ b/lib/widgets/CycleScreens/Result/search_box.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/cycles.dart'; +class CycleResultSearchBox extends StatelessWidget { + const CycleResultSearchBox({ + Key key, + @required this.searchCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final TextEditingController searchCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return TextField( + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + controller: searchCTRL, + onChanged: (value) { + Provider.of(context, listen: false).search(value); + }, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.search, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Search by cycle ID', + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + ); + } +} \ No newline at end of file diff --git a/lib/widgets/Global/drawer.dart b/lib/widgets/Global/drawer.dart new file mode 100644 index 0000000..1763aaf --- /dev/null +++ b/lib/widgets/Global/drawer.dart @@ -0,0 +1,182 @@ +import 'package:cssd/config/routes.dart'; +// import 'package:cssd/pages/test_result_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class AppDrawer extends StatelessWidget { + @override + Widget build(BuildContext context) { + return SafeArea( + child: SizedBox( + width: 250, + child: Drawer( + child: Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.black, + ), + child: Column( + children: [ + ListTile( + leading: CircleAvatar( + backgroundColor: Colors.white, + ), + title: Text( + 'CSSD', + style: TextStyle( + color: Colors.white, + ), + ), + ), + Divider( + color: Colors.white, + ), + InkWell( + onTap: () => + Navigator.of(context).pushNamed(Routes.myInfoScreen), + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.only(top: 10), + decoration: BoxDecoration( + gradient: + LinearGradient(colors: [Colors.blue, Colors.green]), + borderRadius: BorderRadius.circular(5), + ), + child: Row( + children: [ + Icon( + Icons.person_outline, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Text( + 'My Info', + style: TextStyle( + color: Colors.white, + ), + ) + ], + ), + ), + ), + InkWell( + onTap: () => + Navigator.of(context).pushNamed(Routes.testResultScreen), + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.only(top: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + ), + child: Row( + children: [ + Icon( + Icons.assignment, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Text( + 'Test Results', + style: TextStyle( + color: Colors.white, + ), + ) + ], + ), + ), + ), + InkWell( + onTap: () { + Navigator.of(context).pushNamed(Routes.labelResultScreen); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.only(top: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + ), + child: Row( + children: [ + Icon( + FontAwesomeIcons.tag, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Text( + 'Labels', + style: TextStyle( + color: Colors.white, + ), + ) + ], + ), + ), + ), + InkWell( + onTap: () { + Navigator.of(context).pushNamed(Routes.cycleResultScreen); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.only(top: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + ), + child: Row( + children: [ + Icon( + Icons.refresh, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Text( + 'Circles', + style: TextStyle( + color: Colors.white, + ), + ) + ], + ), + ), + ), + Container( + margin: EdgeInsets.only(left: 20), + child: ListTile( + leading: Icon(Icons.phone_bluetooth_speaker), + title: Text('All Test Result'), + dense: true, + ), + ), + Container( + margin: EdgeInsets.only(left: 20), + child: ListTile( + leading: Icon(Icons.settings), + title: Text('Manage Users'), + dense: true, + ), + ), + Container( + margin: EdgeInsets.only(left: 20), + child: ListTile( + leading: Icon(Icons.label), + title: Text('Manage Medical Center'), + dense: true, + ), + ), + ], + ), + ), + elevation: 0, + ), + ), + ); + } +} diff --git a/lib/widgets/Global/input_box.dart b/lib/widgets/Global/input_box.dart new file mode 100644 index 0000000..e655ef7 --- /dev/null +++ b/lib/widgets/Global/input_box.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class InputBox extends StatelessWidget { + const InputBox({ + Key key, + @required double deviceBlockSize, + this.lable, + this.initialValue, + this.ico, this.isPass, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + final String lable; + final String initialValue; + final IconData ico; + final bool isPass; + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + ico, + color: Colors.grey, + ), + SizedBox( + width: _deviceBlockSize, + ), + Expanded( + child: TextFormField( + decoration: InputDecoration( + isDense: false, + // border: UnderlineInputBorder(), + fillColor: Colors.red, + labelText: lable, + contentPadding: EdgeInsets.all(0), + ), + style: TextStyle( + fontSize: 6 * _deviceBlockSize, + ), + initialValue: initialValue, + ), + ), + ], + ); + } +} diff --git a/lib/widgets/Global/page_header.dart b/lib/widgets/Global/page_header.dart new file mode 100644 index 0000000..7acaac8 --- /dev/null +++ b/lib/widgets/Global/page_header.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class PageHeader extends StatelessWidget { + const PageHeader({ + Key key, + @required double deviceBlockSize, + @required String label, + @required String route, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + _route = route, + super(key: key); + + final double _deviceBlockSize; + final String _label; + final String _route; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Container( + child: Text( + _label, + style: TextStyle( + color: Colors.black, + fontSize: 7 * _deviceBlockSize, + fontWeight: FontWeight.w700, + letterSpacing: 2, + ), + ), + ), + Spacer(), + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).popAndPushNamed(_route); + }, + child: Container( + padding: EdgeInsets.all(5), + child: Icon( + FontAwesomeIcons.filter, + size: 7 * _deviceBlockSize, + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/widgets/Global/splash_screen copy.dart b/lib/widgets/Global/splash_screen copy.dart new file mode 100644 index 0000000..8bca2f5 --- /dev/null +++ b/lib/widgets/Global/splash_screen copy.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class ConnectionErrorBox extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Text('Please connect to the Internet ! !'), + ); + } +} diff --git a/lib/widgets/Global/splash_screen.dart b/lib/widgets/Global/splash_screen.dart new file mode 100644 index 0000000..e287656 --- /dev/null +++ b/lib/widgets/Global/splash_screen.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class SplashScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Text('Loading...'), + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Add/date_picker.dart b/lib/widgets/LabelScreens/Add/date_picker.dart new file mode 100644 index 0000000..6777aee --- /dev/null +++ b/lib/widgets/LabelScreens/Add/date_picker.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart' as DateEditor; + +class LabelAddDatePicker extends StatefulWidget { + LabelAddDatePicker({ + Key key, + @required this.dateCTRL, + @required double deviceBlockSize, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + super(key: key); + + final TextEditingController dateCTRL; + final double _deviceBlockSize; + final String _label; + + @override + _LabelAddDatePickerState createState() => _LabelAddDatePickerState(); +} + +class _LabelAddDatePickerState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () async { + var res = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2010, 1), + lastDate: DateTime(2101), + ); + if (res != null) { + setState( + () { + widget.dateCTRL.text = DateEditor.DateFormat('y-M-d').format(res); + // sDateValue = + // DateEditor.DateFormat('y-M-d').format( + // dateTimeS, + // ); // baraye tavize makane gharar giri baraye api + }, + ); + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: TextField( + enabled: false, + controller: widget.dateCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.calendarAlt, + size: 7 * widget._deviceBlockSize, + ), + labelText: widget._label, + isDense: true, + contentPadding: EdgeInsets.only(bottom: 7, right: 3, left: 3), + // border: InputBorder.none, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + ), + ), + Icon(FontAwesomeIcons.angleDown) + ], + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Add/save_button.dart b/lib/widgets/LabelScreens/Add/save_button.dart new file mode 100644 index 0000000..3bef135 --- /dev/null +++ b/lib/widgets/LabelScreens/Add/save_button.dart @@ -0,0 +1,90 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/labels.dart'; + +class LabelAddSaveButton extends StatelessWidget { + const LabelAddSaveButton({ + Key key, + @required GlobalKey form, + @required this.lotNumberCTRL, + @required this.cycleNumberCTRL, + @required this.sDateCTRL, + @required this.packageValue, + @required this.eDateCTRL, + @required this.striizerIdCTRL, + @required double deviceBlockSize, + }) : _form = form, + _deviceBlockSize = deviceBlockSize, + super(key: key); + + final GlobalKey _form; + final TextEditingController lotNumberCTRL; + final TextEditingController cycleNumberCTRL; + final TextEditingController sDateCTRL; + final List packageValue; + final TextEditingController eDateCTRL; + final TextEditingController striizerIdCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (!_form.currentState.validate()) { + return; + } + Provider.of(context).createLabelResult( + lotNumberCTRL.text, + cycleNumberCTRL.text, + sDateCTRL.text, + // sDateValue, + {'id': packageValue[0], 'name': packageValue[1]}, + eDateCTRL.text, + // eDateValue, + striizerIdCTRL.text, + ); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Label added.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then((_) { + Navigator.of(context).pushReplacementNamed(Routes.labelResultScreen); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'SAVE', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Add/selector_box.dart b/lib/widgets/LabelScreens/Add/selector_box.dart new file mode 100644 index 0000000..61b439e --- /dev/null +++ b/lib/widgets/LabelScreens/Add/selector_box.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class LabelAddSelectorBox extends StatefulWidget { + const LabelAddSelectorBox({ + Key key, + @required double deviceBlockSize, + @required this.packageCTRL, + @required this.packageVals, + @required this.packageValue, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController packageCTRL; + final List> packageVals; + final List packageValue; + + @override + _LabelAddSelectorBoxState createState() => _LabelAddSelectorBoxState(); +} + +class _LabelAddSelectorBoxState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 7 * widget._deviceBlockSize, + ), + SizedBox( + width: 4 * widget._deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + SizedBox( + width: widget._deviceBlockSize, + ), + Text( + 'Package', + style: TextStyle( + fontSize: 3.5 * widget._deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w700), + ), + ], + ), + Container( + // height: 30, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: + EdgeInsets.only(left: widget._deviceBlockSize), + // border: InputBorder.none, + ), + iconSize: 7 * widget._deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: + Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric(horizontal: 0), + child: Text( + widget.packageCTRL.text, + textDirection: TextDirection.rtl, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + fontSize: 5 * widget._deviceBlockSize + ), + ),), + // Container( + // // width: 100, + // height: 70, + // padding: const EdgeInsets.symmetric(horizontal: 0), + // child: TextFormField( + // controller: widget.packageCTRL, + // decoration: InputDecoration( + // contentPadding: EdgeInsets.only(bottom: 15), + // isDense: true, + // ), + // style: TextStyle( + // fontWeight: FontWeight.w700, + // color: Colors.black, + // fontSize: 5 * widget._deviceBlockSize, + // ), + // ), + // ), + isDense: true, + items: widget.packageVals.map((val) { + return new DropdownMenuItem( + value: val['name'], + child: Container( + child: Text( + val['name'], + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * widget._deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + widget.packageValue[1] = val; + widget.packageCTRL.text = val; + widget.packageVals.forEach((package) { + if (package['name'] == val) { + widget.packageValue[0] = package['id']; + } + }); + }); + }, + ), + ), + ]), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Detail/datas_box.dart b/lib/widgets/LabelScreens/Detail/datas_box.dart new file mode 100644 index 0000000..f95d731 --- /dev/null +++ b/lib/widgets/LabelScreens/Detail/datas_box.dart @@ -0,0 +1,243 @@ +import 'package:cssd/models/label_models.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class LabelDetailsDataBox extends StatelessWidget { + const LabelDetailsDataBox({ + Key key, + @required this.datas, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final LabelDetailsObject datas; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(20), + child: ListView(children: [ + SizedBox( + height: 10, + ), + Text( + 'LABEL DETAILS', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + letterSpacing: 3, + ), + ), + SizedBox( + height: 10, + ), + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Color.fromRGBO(235, 235, 235, 1), + border: Border( + left: BorderSide( + color: Colors.black54, + width: 2, + ), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + DateFormat.yMMMd().format( + DateTime.parse( + datas.createDate, + ), + ), + style: TextStyle( + color: Colors.red, + ), + ), + Divider(), + Text( + 'ID: ${datas.id}', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.w700, + ), + ), + SizedBox( + height: 30, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Sterilizer ID', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.sterileId.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Cycle Number', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.cycleNumber.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Lot Number', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.lotNumber.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Sterile Date', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + DateFormat('y-M-d').format( + DateTime.parse( + datas.sterileDate, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Expire Date', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + DateFormat('y-M-d').format( + DateTime.parse( + datas.expireDate, + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, color: Colors.red), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Package', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas.package.toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + ], + ), + ), + ]), + ); + } +} diff --git a/lib/widgets/LabelScreens/Detail/header.dart b/lib/widgets/LabelScreens/Detail/header.dart new file mode 100644 index 0000000..9cdebb3 --- /dev/null +++ b/lib/widgets/LabelScreens/Detail/header.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class InfoHeader extends StatelessWidget { + const InfoHeader({ + Key key, + @required double deviceBlockSize, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + super(key: key); + + final double _deviceBlockSize; + final String _label; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + left: 20, + top: 20, + bottom: 10, + right: 20, + ), + child: Text( + _label, + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 7 * _deviceBlockSize, + letterSpacing: _deviceBlockSize, + fontWeight: FontWeight.w700, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/LabelScreens/Filter/save_button.dart b/lib/widgets/LabelScreens/Filter/save_button.dart new file mode 100644 index 0000000..13a9e30 --- /dev/null +++ b/lib/widgets/LabelScreens/Filter/save_button.dart @@ -0,0 +1,86 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:cssd/providers/labels.dart'; + +class LabelFilterSaveButton extends StatelessWidget { + const LabelFilterSaveButton({ + Key key, + @required this.hospitalVals, + @required this.hospitalCTRL, + @required this.labelIdCTRl, + @required this.cycleNumberCTRL, + @required this.striizerIdCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final List> hospitalVals; + final TextEditingController hospitalCTRL; + final TextEditingController labelIdCTRl; + final TextEditingController cycleNumberCTRL; + final TextEditingController striizerIdCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + String hospitalID; + hospitalVals.forEach( + (hospital) { + if (hospital['name'] == hospitalCTRL.text) { + hospitalID = hospital['id']; + } + }, + ); + Provider.of(context).setFilters( + labelIdCTRl.text, + cycleNumberCTRL.text, + striizerIdCTRL.text, + hospitalID, + ); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + content: Text('Filters changed.'), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: Text('Ok'), + ) + ], + ), + ).then((_) { + Navigator.of(context).popAndPushNamed(Routes.labelResultScreen); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 5, + ), + // margin: + // EdgeInsets.symmetric(horizontal: 35, vertical: 15), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'FILTER', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Filter/selector_box.dart b/lib/widgets/LabelScreens/Filter/selector_box.dart new file mode 100644 index 0000000..c0f9792 --- /dev/null +++ b/lib/widgets/LabelScreens/Filter/selector_box.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class LabelFilterSelectorBox extends StatefulWidget { + const LabelFilterSelectorBox({ + Key key, + @required double deviceBlockSize, + @required this.hospitalCTRL, + @required this.hospitalVals, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController hospitalCTRL; + final List> hospitalVals; + + @override + _LabelFilterSelectorBoxState createState() => _LabelFilterSelectorBoxState(); +} + +class _LabelFilterSelectorBoxState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 7 * widget._deviceBlockSize, + ), + SizedBox( + width: 4 * widget._deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + 'Hospital', + style: TextStyle( + fontSize: 3.5 * widget._deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + Container( + // height: 30, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 0), + border: InputBorder.none, + ), + iconSize: 7 * widget._deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric(horizontal: 0), + child: TextFormField( + controller: widget.hospitalCTRL, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(bottom: 15), + isDense: true, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + ), + ), + ), + isDense: true, + items: widget.hospitalVals.map((val) { + return new DropdownMenuItem( + value: val['name'], + child: Container( + child: Text( + val['name'], + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * widget._deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + widget.hospitalCTRL.text = val; + }); + }, + ), + ), + ]), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Result/data_box.dart b/lib/widgets/LabelScreens/Result/data_box.dart new file mode 100644 index 0000000..943e2cf --- /dev/null +++ b/lib/widgets/LabelScreens/Result/data_box.dart @@ -0,0 +1,126 @@ +import 'package:cssd/config/routes.dart'; +import 'package:cssd/models/label_models.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class LabelItemBox extends StatelessWidget { + final LabelResultObject item; + const LabelItemBox({ + Key key, + @required double deviceBlockSize, + this.item, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Navigator.of(context).pushNamed( + Routes.labelDetailScreen, + arguments: item.id, + ), + child: Card( + elevation: 1, + child: Container( + padding: EdgeInsets.all(10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.all(8.0), + child: Text( + item.id, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + SizedBox( + width: 3 * _deviceBlockSize, + ), + // Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 50 * _deviceBlockSize, + child: Text( + 'Package:', + style: TextStyle( + fontSize: 3 * _deviceBlockSize, + color: Colors.grey, + ), + ), + ), + Container( + width: 50 * _deviceBlockSize, + child: Text( + item.package, + overflow: TextOverflow.ellipsis, + ), + ), + Container( + width: 50 * _deviceBlockSize, + child: Row( + children: [ + Text( + 'Exp:', + style: TextStyle( + color: Colors.grey, + fontSize: 3 * _deviceBlockSize, + ), + ), + Text( + item.expireDate, + style: TextStyle( + fontSize: 3 * _deviceBlockSize, + ), + ), + ], + ), + ) + ], + ), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushNamed( + Routes.labelDetailScreen, + arguments: item.id, + ); + }, + child: Container( + padding: EdgeInsets.all(7), + width: 10 * _deviceBlockSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.fileAlt, + size: 6 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ) + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Result/filter_chip_box.dart b/lib/widgets/LabelScreens/Result/filter_chip_box.dart new file mode 100644 index 0000000..6f07b14 --- /dev/null +++ b/lib/widgets/LabelScreens/Result/filter_chip_box.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../../../providers/labels.dart'; +class LabelFilterChip extends StatelessWidget { + const LabelFilterChip({ + Key key, + @required double deviceBlockSize, + @required String id, + @required String cycleNumber, + @required String sterilizerId, + @required String hospital, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _id = id, + _cycleNumber = cycleNumber, + _sterilizerId = sterilizerId, + _hispotal = hospital, + _label = label, + super(key: key); + + final double _deviceBlockSize; + final String _id; + final String _cycleNumber; + final String _sterilizerId; + final String _hispotal; + final String _label; + + @override + Widget build(BuildContext context) { + return Row(children: [ + SizedBox( + width: _deviceBlockSize, + ), + Chip( + backgroundColor: Colors.black, + label: Text( + _label, + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + Icons.close, + color: Colors.white, + ), + onDeleted: () { + var labelProviderObject = Provider.of(context); + labelProviderObject.setFilters( + _id, + _cycleNumber, + _sterilizerId, + _hispotal, + ); + labelProviderObject.setLoading(); + labelProviderObject.getLabelResults().then((_) { + labelProviderObject.resetLoading(); + }); + }, + ), + ]); + } +} \ No newline at end of file diff --git a/lib/widgets/LabelScreens/Result/floating_buttons.dart b/lib/widgets/LabelScreens/Result/floating_buttons.dart new file mode 100644 index 0000000..a83c8f7 --- /dev/null +++ b/lib/widgets/LabelScreens/Result/floating_buttons.dart @@ -0,0 +1,61 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class LabelFloatingButtons extends StatelessWidget { + const LabelFloatingButtons({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushNamed(Routes.labelScanScreen); + }, + child: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.black, + ), + child: Icon( + FontAwesomeIcons.barcode, + size: 7.1 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + SizedBox( + width: 2 * _deviceBlockSize, + ), + InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushReplacementNamed(Routes.labelAddScreen); + }, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.redAccent, + ), + child: Icon( + Icons.add, + size: 10 * _deviceBlockSize, + color: Colors.white, + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/LabelScreens/Result/search_box.dart b/lib/widgets/LabelScreens/Result/search_box.dart new file mode 100644 index 0000000..582f8c0 --- /dev/null +++ b/lib/widgets/LabelScreens/Result/search_box.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import '../../../providers/labels.dart'; + +class LabelSearchBox extends StatelessWidget { + const LabelSearchBox({ + Key key, + @required this.searchCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final TextEditingController searchCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return TextField( + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + onChanged: (value) { + Provider.of(context, listen: false).search(value); + }, + controller: searchCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.search, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Search by lable ID', + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + ); + } +} diff --git a/lib/widgets/LabelScreens/Scan/input_box.dart b/lib/widgets/LabelScreens/Scan/input_box.dart new file mode 100644 index 0000000..67085e4 --- /dev/null +++ b/lib/widgets/LabelScreens/Scan/input_box.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class LabelScanInputBox extends StatelessWidget { + const LabelScanInputBox({ + Key key, + @required this.idCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final TextEditingController idCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return TextFormField( + validator: (val) { + if (val.isEmpty) { + return 'Id required!!'; + } + return null; + }, + controller: idCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.sortNumericDown, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Or enter a label ID', + isDense: true, + contentPadding: EdgeInsets.symmetric( + vertical: 2, + horizontal: 3, + ), + focusedBorder: UnderlineInputBorder( + // borderRadius: BorderRadius.only(Radius.circular(4)), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + ); + } +} diff --git a/lib/widgets/LabelScreens/Scan/save_button.dart b/lib/widgets/LabelScreens/Scan/save_button.dart new file mode 100644 index 0000000..b1ac456 --- /dev/null +++ b/lib/widgets/LabelScreens/Scan/save_button.dart @@ -0,0 +1,53 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; + +class FilterScanSaveButton extends StatelessWidget { + const FilterScanSaveButton({ + Key key, + @required GlobalKey form, + @required this.idCTRL, + @required double deviceBlockSize, + }) : _form = form, _deviceBlockSize = deviceBlockSize, super(key: key); + + final GlobalKey _form; + final TextEditingController idCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (! _form.currentState.validate()) { + return; + } + Navigator.of(context).pushNamed( + Routes.labelDetailScreen, + arguments: idCTRL.text, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + margin: EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'GO!', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/LabelScreens/Scan/scan_box.dart b/lib/widgets/LabelScreens/Scan/scan_box.dart new file mode 100644 index 0000000..f760692 --- /dev/null +++ b/lib/widgets/LabelScreens/Scan/scan_box.dart @@ -0,0 +1,88 @@ +import 'package:barcode_scan/barcode_scan.dart'; +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class LabelScanBox extends StatelessWidget { + const LabelScanBox({ + Key key, + }) : super(key: key); + Future scan() async { + try { + var barcode = await BarcodeScanner.scan(); + if (barcode.type.name == 'Cancelled') { + return 'cancel'; + } else if (barcode.type.name == 'Failed') { + return 'error'; + } // print(barcode.split('/')); + try { + var id = barcode.rawContent.contains('www.cssd-doc.com') + ? barcode.rawContent.split('/')[5] + : barcode.rawContent; + return id; + } catch (_) { + return 'null'; + } + } on PlatformException catch (_) { + return 'access'; + } + catch (_){ + return 'error'; + } + + // } on FormatException { + // setState(() => this.testCode = + // 'null (User returned using the "back"-button before scanning anything. Result)'); + // } catch (e) { + // setState(() => this.testCode = 'Unknown error: $e'); + // } + // return null; + } + + @override + Widget build(BuildContext context) { + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return GestureDetector( + child: Container( + margin: EdgeInsets.symmetric(vertical: 10), + height: 200, + decoration: BoxDecoration(border: Border.all()), + child: Center( + child: Text( + 'Please Scan The Label Barcode', + style: TextStyle( + color: Colors.black, + fontSize: 5 * _deviceBlockSize, + fontWeight: FontWeight.w100, + letterSpacing: 3, + ), + textAlign: TextAlign.center, + ), + ), + ), + onTap: () { + scan().then( + (String result) { + if (result == 'cancel') { + print('cancel'); + } else if (result == 'error') { + print('error'); + } + else if(result == 'access'){ + print('access'); + } + else { + Navigator.of(context).pushNamed( + Routes.labelDetailScreen, + arguments: result, + ); + } + }, + ); + }, + ); + } +} diff --git a/lib/widgets/MyInfo/input_box.dart b/lib/widgets/MyInfo/input_box.dart new file mode 100644 index 0000000..e6b386b --- /dev/null +++ b/lib/widgets/MyInfo/input_box.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class InfoInputBox extends StatelessWidget { + const InfoInputBox({ + Key key, + @required this.controller, + @required double deviceBlockSize, + @required String label, + @required IconData icon, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + _icon = icon, + super(key: key); + + final TextEditingController controller; + final double _deviceBlockSize; + final String _label; + final IconData _icon; + + @override + Widget build(BuildContext context) { + return TextFormField( + controller: controller, + decoration: InputDecoration( + icon: Icon( + _icon, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: _label, + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + ); + } +} diff --git a/lib/widgets/TestResultScreens/Add/form_creator.dart b/lib/widgets/TestResultScreens/Add/form_creator.dart new file mode 100644 index 0000000..336f8c3 --- /dev/null +++ b/lib/widgets/TestResultScreens/Add/form_creator.dart @@ -0,0 +1,379 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; +import 'package:multiselect_formfield/multiselect_formfield.dart'; + +class FormCreator extends StatefulWidget { + const FormCreator({ + @required this.form, + @required this.onChanged, + this.padding, + }); + + final dynamic form; + final double padding; + final ValueChanged onChanged; + + @override + _FormCreatorState createState() => _FormCreatorState(form); +} + +class _FormCreatorState extends State { + final dynamic formItems; + DateTime selectedDate = DateTime.now(); + + int rangeValue; + String selectValue; + + Future _selectDate() async { + final DateTime picked = await showDatePicker( + context: context, + initialDate: selectedDate, + firstDate: DateTime(2015, 8), + lastDate: DateTime(2101)); + if (picked != null && picked != selectedDate) + setState(() { + selectedDate = picked; + }); + } + + List jsonToForm() { + List listWidgets = List(); + + for (var count = 0; count < formItems.length; count++) { + Map item = formItems[count]; + + if (item['type'] == "Date") { + selectedDate = formItems[count]['value']; + listWidgets.add( + OutlineButton( + onPressed: () { + _selectDate().then((_) { + formItems[count]['value'] = selectedDate; + _handleChanged(); + }); + }, + child: Text( + 'Date: ${selectedDate.year}/${selectedDate.month}/${selectedDate.day}'), + padding: EdgeInsets.symmetric(vertical: 20), + ), + ); + } + + if (item['type'] == "Label") { + listWidgets.add( + Container( + decoration: BoxDecoration( + border: Border.all(), + borderRadius: BorderRadius.circular(30), + color: Colors.black, + ), + padding: EdgeInsets.only(top: 20, bottom: 20), + margin: EdgeInsets.only(bottom: 20), + child: Text( + item['name'], + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 20), + ), + ), + ); + } + + if (item['type'] == "Text") { + listWidgets.add( + Padding( + padding: const EdgeInsets.all(8.0), + child: TextFormField( + decoration: InputDecoration( + labelText: item['name'] ?? "", + border: UnderlineInputBorder(), + contentPadding: EdgeInsets.all(0), + ), + initialValue: item['value'] ?? '', + onChanged: (String value) { + formItems[count]['value'] = value; + _handleChanged(); + }, + ), + ), + ); + } + + if (item['type'] == "Range" || + item['type'] == "Temperature" || + item['type'] == "Pressure") { + double startValue, endValue; + if (item['type'] == "Range") { + startValue = double.parse(item['options'][0]['title']); + endValue = double.parse(item['options'][1]['title']); + } else { + startValue = item['type'] == "Temperature" ? 0.0 : -1.0; + endValue = item['type'] == "Temperature" ? 200.0 : 3.0; + } + + formItems[count]['value'] = formItems[count]['value'] ?? startValue; + int divisions = (endValue - startValue).round(); + listWidgets.add( + Padding( + padding: EdgeInsets.only(top: 35), + child: Slider( + min: startValue, + max: endValue, + value: formItems[count]['value'], + label: '${formItems[count]['value'].round()}', + divisions: divisions, + onChanged: (double value) { + setState(() { + formItems[count]['value'] = value; + }); + }, + semanticFormatterCallback: (double newValue) { + return '${newValue.round()}'; + }, + ), + ), + ); + } + + if (item['type'] == "Time") { + listWidgets.add( + Padding( + padding: const EdgeInsets.all(8.0), + child: TextFormField( + inputFormatters: [ + LengthLimitingTextInputFormatter(5), + WhitelistingTextInputFormatter.digitsOnly, + // BlacklistingTextInputFormatter.singleLineFormatter, + TextInputFormatter.withFunction( + (TextEditingValue oldValue, TextEditingValue newValue) { + final int newTextLength = newValue.text.length; + int selectionIndex = newValue.selection.end; + int usedSubstringIndex = 0; + final StringBuffer newText = StringBuffer(); + if (newTextLength >= 2) { + newText.write( + newValue.text.substring(0, usedSubstringIndex = 2) + + ':'); + if (newValue.selection.end >= 2) selectionIndex++; + } + // Dump the rest. + if (newTextLength >= usedSubstringIndex) + newText.write(newValue.text.substring(usedSubstringIndex)); + return TextEditingValue( + text: newText.toString(), + selection: TextSelection.collapsed(offset: selectionIndex), + ); + }) + ], + keyboardType: TextInputType.datetime, + decoration: InputDecoration( + labelText: item['name'] ?? "", + border: UnderlineInputBorder(), + contentPadding: EdgeInsets.all(0), + ), + initialValue: item['value'] ?? '', + onChanged: (String value) { + formItems[count]['value'] = value; + _handleChanged(); + }, + ), + ), + ); + } + + if (item['type'] == "Select") { + var listItems = item['options'] as List; + listWidgets.add(MultiSelectFormField( + autovalidate: false, + titleText: item['name'], + dataSource: listItems, + textField: 'title', + valueField: 'id', + okButtonLabel: 'OK', + cancelButtonLabel: 'CANCEL', + hintText: 'Please choose one or more', + value: item['value'], + onSaved: (value) { + if (value == null) return; + setState(() { + item['value'] = value; + }); + _handleChanged(); + }, + )); + + // listWidgets.add( + // DropdownButtonFormField( + // items: listItems.map((dynamic value) { + // String stringValue = value['id'].toString(); + // String textValue = value['title'].toString(); + // return DropdownMenuItem( + // value: stringValue, + // child: Text(textValue), + // ); + // }).toList(), + // isDense: true, + // value: item['value'], + // hint: Text(item['name']), + + // onChanged: (String value) { + // this.setState( + // () { + // _setInput(item['name'], value); + // formItems[count]['value'] = value; + // _handleChanged(); + // }, + // ); + // }, + // ), + // ); + } + + if (item['type'] == "Radiobutton") { + listWidgets.add( + Container( + margin: EdgeInsets.only(top: 14.0, bottom: 0), + child: Text( + item['name'], + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0), + ), + ), + ); + var valueOrFirst = + formItems[count]['value'] ?? formItems[count]['options'][0]['id']; + for (var i = 0; i < item['options'].length; i++) { + var isSelected = formItems[count]['options'][i]['id'] == valueOrFirst; + formItems[count]['value'] = valueOrFirst; + listWidgets.add( + RadioListTile( + dense: true, + controlAffinity: ListTileControlAffinity.trailing, + title: Text(formItems[count]['options'][i]['title']), + value: formItems[count]['options'][i]['id'], + selected: isSelected, + groupValue: formItems[count]['value'], + onChanged: (int value) { + this.setState( + () { + _setInput(item['name'], value.toString()); + formItems[count]['value'] = value; + _handleChanged(); + }, + ); + }, + ), + ); + } + } + + if (item['type'] == "Switch") { + listWidgets.add(SwitchListTile( + activeColor: Colors.green, + inactiveTrackColor: Colors.red.withAlpha(150), + inactiveThumbColor: Colors.red, + title: Text(item['name']), + value: item['value'] ?? false, + onChanged: (bool value) { + this.setState(() { + formItems[count]['value'] = value; + _handleChanged(); + }); + })); + } + + if (item['type'] == "Form") { + listWidgets.add( + Container( + margin: EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration(border: Border.all()), + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10), + child: Text( + item['name'], + style: + TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0), + ), + ), + FormCreator( + form: item['children'], + padding: 4, + onChanged: (value) { + // _handleChanged(); + }, + ), + ], + ), + ), + ); + } + + if (item['type'] == "Checkbox") { + formItems[count]['value'] = formItems[count]['value'] ?? []; + listWidgets.add( + Container( + margin: EdgeInsets.only(top: 14.0, bottom: 0), + child: Text( + item['name'], + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0), + ), + ), + ); + for (var i = 0; i < item['options'].length; i++) { + listWidgets.add( + CheckboxListTile( + title: Text(formItems[count]['options'][i]['title']), + value: (formItems[count]['value'] ?? []) + .contains(formItems[count]['options'][i]['id']), + onChanged: (bool value) { + this.setState( + () { + setState(() { + if (value) { + (formItems[count]['value'] as List) + .add(formItems[count]['options'][i]['id']); + } else { + (formItems[count]['value'] as List) + .remove(formItems[count]['options'][i]['id']); + } + }); + _handleChanged(); + }, + ); + }, + ), + ); + } + } + // listWidgets.add( + // TestResultAddSaveButton( + // deviceBlockSize: null, + // ), + // ); + } + return listWidgets; + } + + _FormCreatorState(this.formItems); + + void _handleChanged() { + widget.onChanged(formItems); + } + + void _setInput(String key, String value) {} + + @override + Widget build(BuildContext context) { + return ListView.builder( + padding: EdgeInsets.all(widget.padding ?? 16.0), + itemCount: jsonToForm().length, + itemBuilder: (context, index) { + return jsonToForm()[index]; + }, + shrinkWrap: true, + controller: ScrollController(keepScrollOffset: false), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Add/save_button.dart b/lib/widgets/TestResultScreens/Add/save_button.dart new file mode 100644 index 0000000..4a1dafc --- /dev/null +++ b/lib/widgets/TestResultScreens/Add/save_button.dart @@ -0,0 +1,56 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; + +class TestResultAddSaveButton extends StatelessWidget { + const TestResultAddSaveButton({ + Key key, + // @required GlobalKey form, + // @required this.idCTRL, + @required double deviceBlockSize, + }) : + // _form = form, + _deviceBlockSize = deviceBlockSize, + super(key: key); + + // final GlobalKey _form; + // final TextEditingController idCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + // if (! _form.currentState.validate()) { + // return; + // } + Navigator.of(context).pushNamed( + Routes.labelDetailScreen, + // arguments: idCTRL.text, + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 5 * _deviceBlockSize, + vertical: 10, + ), + margin: EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue, Colors.green], + ), + borderRadius: BorderRadius.circular(7), + ), + child: Align( + alignment: Alignment.center, + child: Text( + 'GO!', + style: TextStyle( + color: Colors.white, + fontSize: 5 * _deviceBlockSize, + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Add/selector_box.dart b/lib/widgets/TestResultScreens/Add/selector_box.dart new file mode 100644 index 0000000..5c3c878 --- /dev/null +++ b/lib/widgets/TestResultScreens/Add/selector_box.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class TestResultAddSelectorBox extends StatefulWidget { + const TestResultAddSelectorBox({ + Key key, + @required double deviceBlockSize, + @required this.dataCTRL, + @required this.dataVals, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController dataCTRL; + final List dataVals; + final String _label; + + @override + _TestResultAddSelectorBoxState createState() => + _TestResultAddSelectorBoxState(); +} + +class _TestResultAddSelectorBoxState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 6 * widget._deviceBlockSize, + ), + SizedBox( + width: 4 * widget._deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + widget._label, + style: TextStyle( + fontSize: 3 * widget._deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w100, + ), + ), + ], + ), + Container( + height: 40, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 0), + // border: InputBorder.none, + ), + iconSize: 7 * widget._deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric(horizontal: 0), + child: Text( + widget.dataCTRL.text, + // textDirection: TextDirection.rtl, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + fontSize: 4 * widget._deviceBlockSize, + ), + ), + // TextFormField( + // controller: widget.dataCTRL, + // decoration: InputDecoration( + // contentPadding: EdgeInsets.only(bottom: 15), + // isDense: true, + // ), + // style: TextStyle( + // fontWeight: FontWeight.w700, + // color: Colors.black, + // ), + // // minLines: 1, + // // maxLines: 3, + // ), + ), + isDense: true, + items: widget.dataVals.map((val) { + return new DropdownMenuItem( + value: val, + child: Container( + child: Text( + val, + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * widget._deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + widget.dataCTRL.text = val; + }); + }, + ), + ), + ]), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Details/datas_box.dart b/lib/widgets/TestResultScreens/Details/datas_box.dart new file mode 100644 index 0000000..3bb229f --- /dev/null +++ b/lib/widgets/TestResultScreens/Details/datas_box.dart @@ -0,0 +1,228 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class DatasBox extends StatelessWidget { + const DatasBox({ + Key key, + @required this.datas, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final Map datas; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(20), + child: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: Color.fromRGBO(230, 230, 230, 1), + border: Border( + left: BorderSide( + color: Colors.pink, + width: 2, + ), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + DateFormat.yMMMd().format( + DateTime.parse( + datas['date'], + ), + ), + style: TextStyle( + color: Colors.red, + ), + ), + Divider(), + Text( + datas['test_type_name'], + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.w700, + ), + ), + SizedBox( + height: 30, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'CSSD ID', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas['id'].toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Autocleave ID', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas['auto_cleave_id'].toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Test Code', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas['test_code'].toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Date', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + DateFormat('d-M-y').format( + DateTime.parse( + datas['date'], + ), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Status', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas['verified'] == 'NotVerified' + ? 'Rejected' + : 'Verified', + style: TextStyle( + fontWeight: FontWeight.w700, + color: datas['verified'] == 'NotVerified' + ? Colors.red + : Colors.blueAccent, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + SizedBox( + height: 5, + ), + Row( + children: [ + Container( + width: 35 * _deviceBlockSize, + child: Text( + 'Description', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + Container( + width: 45 * _deviceBlockSize, + child: Text( + datas['description'].toString(), + style: TextStyle( + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + ), + ), + ], + ), + Divider(), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Filter/date_picker.dart b/lib/widgets/TestResultScreens/Filter/date_picker.dart new file mode 100644 index 0000000..f7d7de7 --- /dev/null +++ b/lib/widgets/TestResultScreens/Filter/date_picker.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart' as DateEditor; + +class TestResultFilterDatePicker extends StatefulWidget { + TestResultFilterDatePicker({ + Key key, + @required this.dateCTRL, + @required double deviceBlockSize, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + super(key: key); + + final TextEditingController dateCTRL; + final double _deviceBlockSize; + final String _label; + + @override + _TestResultFilterDatePickerState createState() => _TestResultFilterDatePickerState(); +} + +class _TestResultFilterDatePickerState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () async { + var res = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2010, 1), + lastDate: DateTime(2101), + ); + if (res != null) { + setState( + () { + widget.dateCTRL.text = DateEditor.DateFormat('y-M-d').format(res); + // sDateValue = + // DateEditor.DateFormat('y-M-d').format( + // dateTimeS, + // ); // baraye tavize makane gharar giri baraye api + }, + ); + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: TextField( + enabled: false, + controller: widget.dateCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.calendarAlt, + size: 7 * widget._deviceBlockSize, + ), + labelText: widget._label, + isDense: true, + contentPadding: EdgeInsets.only(bottom: 12, right: 3, left: 3), + // border: InputBorder.none, + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * widget._deviceBlockSize, + ), + ), + ), + Icon(FontAwesomeIcons.angleDown) + ], + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Filter/drop_down_box.dart b/lib/widgets/TestResultScreens/Filter/drop_down_box.dart new file mode 100644 index 0000000..ba41556 --- /dev/null +++ b/lib/widgets/TestResultScreens/Filter/drop_down_box.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class DropDownBox extends StatefulWidget { + + DropDownBox({ + Key key, + @required this.values, + }) : super(key: key); + + final List values; + + @override + _DropDownBoxState createState() => _DropDownBoxState(); +} + +class _DropDownBoxState extends State { + String _curValue; + + @override + void initState() { + _curValue = widget.values[0]; + super.initState(); + } + + @override + Widget build(BuildContext context) { + // _curValue = widget.values[0]; + // final ThemeData _theme = Theme.of(context); + // final Color _mainFontColor = _theme.textSelectionColor; + final _media = MediaQuery.of(context); + // final double _pixelRatio = (_media.size.height / _media.size.width * 7 / 5); + final double _devicewidth = _media.size.width; + final double _deviceBlockSize = _devicewidth / 100; + return Row( + // width: double.infinity, + children: [ + Icon( + FontAwesomeIcons.sortNumericDown, + color: Colors.grey, + size: 4 * _deviceBlockSize, + ), + SizedBox( + width: _deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: DropdownButton( + focusColor: Colors.red, + icon: Icon(FontAwesomeIcons.angleDown), + isExpanded: true, + hint: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + _curValue, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + // color: _mainFontColor, + fontSize: 3.5 * _deviceBlockSize, + ), + ), + ), + isDense: true, + items: widget.values.map((String value) { + return new DropdownMenuItem( + value: value, + child: Container( + child: Text( + value, + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * _deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + _curValue = val; + }); + }, + ), + ), + ]); + } +} diff --git a/lib/widgets/TestResultScreens/Filter/selector_box.dart b/lib/widgets/TestResultScreens/Filter/selector_box.dart new file mode 100644 index 0000000..56a3507 --- /dev/null +++ b/lib/widgets/TestResultScreens/Filter/selector_box.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class TestResultFilterSelectorBox extends StatefulWidget { + const TestResultFilterSelectorBox({ + Key key, + @required double deviceBlockSize, + @required this.dataCTRL, + @required this.dataVals, + @required String label, + }) : _deviceBlockSize = deviceBlockSize, + _label = label, + super(key: key); + + final double _deviceBlockSize; + final TextEditingController dataCTRL; + final List dataVals; + final String _label; + + @override + _TestResultFilterSelectorBoxState createState() => + _TestResultFilterSelectorBoxState(); +} + +class _TestResultFilterSelectorBoxState + extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric(vertical: 5), + // height: 65, + child: Row( + // width: double.infinity, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.alignLeft, + color: Colors.grey, + size: 7 * widget._deviceBlockSize, + ), + SizedBox( + width: 4 * widget._deviceBlockSize, + ), + Expanded( + // width: MediaQuery.of(context).size.width - 70, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + widget._label, + style: TextStyle( + fontSize: 3.5 * widget._deviceBlockSize, + color: Colors.grey, + fontWeight: FontWeight.w100, + ), + ), + ], + ), + Container( + // height: 30, + child: DropdownButtonFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 0), + // border: InputBorder.none, + ), + iconSize: 7 * widget._deviceBlockSize, + icon: Icon( + FontAwesomeIcons.angleDown, + color: Colors.black, + ), + isExpanded: true, + hint: Container( + // width: 100, + height: 70, + padding: const EdgeInsets.symmetric(horizontal: 0), + child: Text( + widget.dataCTRL.text, + // textDirection: TextDirection.rtl, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.black, + fontSize: 5 * widget._deviceBlockSize), + ), + // TextFormField( + // controller: widget.dataCTRL, + // decoration: InputDecoration( + // contentPadding: EdgeInsets.only(bottom: 15), + // isDense: true, + // ), + // style: TextStyle( + // fontWeight: FontWeight.w700, + // color: Colors.black, + // ), + // // minLines: 1, + // // maxLines: 3, + // ), + ), + isDense: true, + items: widget.dataVals.map((val) { + return new DropdownMenuItem( + value: val, + child: Container( + child: Text( + val, + style: TextStyle( + // color: _mainFontColor, + fontSize: 4 * widget._deviceBlockSize, + ), + ), + ), + ); + }).toList(), + onChanged: (val) { + setState(() { + widget.dataCTRL.text = val; + }); + }, + ), + ), + ]), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Main/add_button.dart b/lib/widgets/TestResultScreens/Main/add_button.dart new file mode 100644 index 0000000..2725781 --- /dev/null +++ b/lib/widgets/TestResultScreens/Main/add_button.dart @@ -0,0 +1,34 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; + +class TestResultAddButton extends StatelessWidget { + const TestResultAddButton({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + customBorder: CircleBorder(), + onTap: () { + Navigator.of(context).pushNamed(Routes.testResultAddScreen); + }, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.redAccent, + ), + child: Icon( + Icons.add, + size: 10 * _deviceBlockSize, + color: Colors.white, + ), + ), + ); + } +} diff --git a/lib/widgets/TestResultScreens/Main/filter_chip_box.dart b/lib/widgets/TestResultScreens/Main/filter_chip_box.dart new file mode 100644 index 0000000..d78c13d --- /dev/null +++ b/lib/widgets/TestResultScreens/Main/filter_chip_box.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../../../providers/test_results.dart'; + +class TestResultChip extends StatelessWidget { + const TestResultChip({ + Key key, + @required double deviceBlockSize, + @required String label, + @required String id, + @required String labelID, + @required String testType, + @required String hospital, + @required String username, + @required String fDate, + @required String uDate, + }) : _deviceBlockSize = deviceBlockSize, + _id = id, + _labelID = labelID, + _testType = testType, + _hispotal = hospital, + _label = label, + _username = username, + _fDate = fDate, + _uDate = uDate, + super(key: key); + + final double _deviceBlockSize; + final String _id; + final String _labelID; + final String _testType; + final String _hispotal; + final String _label; + final String _username; + final String _fDate; + final String _uDate; + + @override + Widget build(BuildContext context) { + return Row(children: [ + SizedBox( + width: _deviceBlockSize, + ), + Chip( + backgroundColor: Colors.black, + label: Text( + _label, + style: TextStyle( + color: Colors.white, + ), + ), + deleteIcon: Icon( + Icons.close, + color: Colors.white, + ), + onDeleted: () { + var labelProviderObject = Provider.of(context); + labelProviderObject.setFilters( + _id, + _labelID, + _username, + _testType, + _hispotal, + _fDate, + _uDate, + ); + labelProviderObject.setLoading(); + labelProviderObject.getTestResults().then((_) { + labelProviderObject.resetLoading(); + }); + }, + ), + ]); + } +} diff --git a/lib/widgets/TestResultScreens/Main/floating_button.dart b/lib/widgets/TestResultScreens/Main/floating_button.dart new file mode 100644 index 0000000..2f24bc8 --- /dev/null +++ b/lib/widgets/TestResultScreens/Main/floating_button.dart @@ -0,0 +1,33 @@ +import 'package:cssd/config/routes.dart'; +import 'package:flutter/material.dart'; + +class TestResultFloatingButton extends StatelessWidget { + const TestResultFloatingButton({ + Key key, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Navigator.of(context).popAndPushNamed(Routes.testResultAddScreen); + }, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Color.fromRGBO(0, 190, 190, 1), + ), + child: Icon( + Icons.add, + size: 10 * _deviceBlockSize, + color: Colors.white, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/TestResultScreens/Main/search_box.dart b/lib/widgets/TestResultScreens/Main/search_box.dart new file mode 100644 index 0000000..b1f0e5f --- /dev/null +++ b/lib/widgets/TestResultScreens/Main/search_box.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; +import '../../../providers/test_results.dart'; + +class TestResultSearchBox extends StatelessWidget { + const TestResultSearchBox({ + Key key, + @required this.searchCTRL, + @required double deviceBlockSize, + }) : _deviceBlockSize = deviceBlockSize, + super(key: key); + + final TextEditingController searchCTRL; + final double _deviceBlockSize; + + @override + Widget build(BuildContext context) { + return TextField( + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + onChanged: (value) { + Provider.of(context, listen: false).search(value); + }, + controller: searchCTRL, + decoration: InputDecoration( + icon: Icon( + FontAwesomeIcons.search, + size: 6 * _deviceBlockSize, + ), + labelStyle: TextStyle( + fontWeight: FontWeight.w100, + fontSize: 4 * _deviceBlockSize, + ), + labelText: 'Search by test name', + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 2, horizontal: 3), + ), + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 5 * _deviceBlockSize, + ), + keyboardType: TextInputType.visiblePassword, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..83d5451 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,362 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + barcode_scan: + dependency: "direct main" + description: + name: barcode_scan + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.11" + connectivity: + dependency: "direct main" + description: + name: connectivity + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.8+5" + connectivity_macos: + dependency: transitive + description: + name: connectivity_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+3" + connectivity_platform_interface: + dependency: transitive + description: + name: connectivity_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + double_back_to_close_app: + dependency: "direct main" + description: + name: double_back_to_close_app + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + dropdown_formfield: + dependency: "direct main" + description: + name: dropdown_formfield + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.11" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_phoenix: + dependency: "direct main" + description: + name: flutter_phoenix + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" + 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" + font_awesome_flutter: + dependency: "direct main" + description: + name: font_awesome_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "8.8.1" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.1+1" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0+4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.4" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" + incrementally_loading_listview: + dependency: "direct main" + description: + name: incrementally_loading_listview + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.6" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.8" + multiselect_formfield: + dependency: "direct main" + description: + name: multiselect_formfield + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + protobuf: + dependency: transitive + description: + name: protobuf + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.23.1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.7" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+7" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2+4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.5" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.11" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" +sdks: + dart: ">=2.6.0 <3.0.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..b119830 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,100 @@ +name: cssd +description: A new Flutter project. + +# 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 used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.1.0+1 + +environment: + sdk: ">=2.2.2 <3.0.0" + +dependencies: + flutter: + sdk: flutter + http: ^0.12.0+3 + provider: ^3.2.0 + barcode_scan: ^3.0.0 + # flutter_barcode_scanner: ^1.0.0 + connectivity: ^0.4.8+5 + + shared_preferences: ^0.5.6 + multiselect_formfield: ^0.1.2 + flutter_phoenix: ^0.1.0 + font_awesome_flutter: ^8.8.1 + intl: ^0.16.1 + double_back_to_close_app: ^1.2.0 + hive: ^1.4.1+1 + + # loadmore: ^1.0.4 + incrementally_loading_listview: ^0.3.0 + dropdown_formfield: ^0.1.2 + + + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + +# 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. +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/Images/ + # - 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: montserrat + fonts: + - asset: assets/Fonts/Montserrat-Regular.ttf + - asset: assets/Fonts/Montserrat-Bold.ttf + weight: 700 + - family: montserratlight + fonts: + - asset: assets/Fonts/Montserrat-Light.ttf + - asset: assets/Fonts/Montserrat-Bold.ttf + weight: 700 + - family: montserratmedium + fonts: + - asset: assets/Fonts/Montserrat-Medium.ttf + - asset: assets/Fonts/Montserrat-Bold.ttf + weight: 700 + # - asset: assets/Fonts/Montserrat-Light.ttf + # - asset: assets/Fonts/Montserrat-Italic.ttf + + + # 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..eb2c626 --- /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 that Flutter provides. 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:cssd/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +}