commit c12d33c1dbc8e6b73e885407ff911b9c930f5a48 Author: FlutterFlow <140657486+FlutterFlowEng@users.noreply.github.com> Date: Mon Jun 10 11:44:03 2024 +0000 Updating to latest FlutterFlow output. diff --git a/README.md b/README.md new file mode 100644 index 00000000..600088c7 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# FREHub + +A new Flutter project. + +## Getting Started + +FlutterFlow projects are built to run on the Flutter _stable_ release. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..78e77505 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,35 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + unnecessary_string_escapes: false + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options + + +analyzer: + exclude: + - lib/custom_code/** + - lib/flutter_flow/custom_functions.dart diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 00000000..0a741cb4 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,11 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 00000000..9883c333 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,79 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" + + +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + +android { + compileSdkVersion 34 + + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + checkReleaseBuilds false + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.freaccess.hub" + minSdkVersion 21 + targetSdkVersion 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + + 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:1.7.10" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..288304cb --- /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 00000000..08fca23b --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt b/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt new file mode 100644 index 00000000..f6d5d1f0 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/my_project/MainActivity.kt @@ -0,0 +1,6 @@ +package com.freaccess.hub + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} 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 00000000..f74085f3 --- /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 00000000..db77bb4b 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 00000000..17987b79 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 00000000..09d43914 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 00000000..d5f1c8d3 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 00000000..4d6372ee Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml new file mode 100644 index 00000000..f93aa34d --- /dev/null +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..f93aa34d --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml new file mode 100644 index 00000000..d74aa35c --- /dev/null +++ b/android/app/src/main/res/values-v31/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..d5c63adc --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + + FREHub + + \ No newline at end of file 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 00000000..d74aa35c --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..288304cb --- /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 00000000..cf9fba7e --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..498c33b7 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx4608m +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..6b665338 --- /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-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 00000000..e699619d --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,27 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false + + +} + +include ":app" \ No newline at end of file diff --git a/assets/audios/favicon.png b/assets/audios/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/audios/favicon.png differ diff --git a/assets/fonts/Nunito-Medium.ttf b/assets/fonts/Nunito-Medium.ttf new file mode 100644 index 00000000..f9881a02 Binary files /dev/null and b/assets/fonts/Nunito-Medium.ttf differ diff --git a/assets/fonts/Nunito-Regular.ttf b/assets/fonts/Nunito-Regular.ttf new file mode 100644 index 00000000..dfd0fcb4 Binary files /dev/null and b/assets/fonts/Nunito-Regular.ttf differ diff --git a/assets/fonts/SFPRODISPLAYBOLD.OTF b/assets/fonts/SFPRODISPLAYBOLD.OTF new file mode 100644 index 00000000..025b25c2 Binary files /dev/null and b/assets/fonts/SFPRODISPLAYBOLD.OTF differ diff --git a/assets/fonts/SFPRODISPLAYMEDIUM.OTF b/assets/fonts/SFPRODISPLAYMEDIUM.OTF new file mode 100644 index 00000000..b2f7daca Binary files /dev/null and b/assets/fonts/SFPRODISPLAYMEDIUM.OTF differ diff --git a/assets/fonts/SFPRODISPLAYREGULAR.OTF b/assets/fonts/SFPRODISPLAYREGULAR.OTF new file mode 100644 index 00000000..09aaca9f Binary files /dev/null and b/assets/fonts/SFPRODISPLAYREGULAR.OTF differ diff --git a/assets/fonts/favicon.png b/assets/fonts/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/fonts/favicon.png differ diff --git a/assets/fonts/icons.ttf b/assets/fonts/icons.ttf new file mode 100644 index 00000000..967993d2 Binary files /dev/null and b/assets/fonts/icons.ttf differ diff --git a/assets/fonts/menu.ttf b/assets/fonts/menu.ttf new file mode 100644 index 00000000..96dead6b Binary files /dev/null and b/assets/fonts/menu.ttf differ diff --git a/assets/images/adaptive_background_icon.svg b/assets/images/adaptive_background_icon.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/assets/images/adaptive_background_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/adaptive_foreground_icon.svg b/assets/images/adaptive_foreground_icon.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/assets/images/adaptive_foreground_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/app_launcher_icon.svg b/assets/images/app_launcher_icon.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/assets/images/app_launcher_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/error_image.svg b/assets/images/error_image.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/assets/images/error_image.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/images/logo.svg b/assets/images/logo.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/assets/images/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/lottie_animations/favicon.png b/assets/lottie_animations/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/lottie_animations/favicon.png differ diff --git a/assets/pdfs/favicon.png b/assets/pdfs/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/pdfs/favicon.png differ diff --git a/assets/rive_animations/favicon.png b/assets/rive_animations/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/rive_animations/favicon.png differ diff --git a/assets/videos/favicon.png b/assets/videos/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/assets/videos/favicon.png differ diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 00000000..eb86478d --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,33 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +build/ +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 00000000..d57061dd --- /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 + 13.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/ImageNotification/Info.plist b/ios/ImageNotification/Info.plist new file mode 100644 index 00000000..9f280602 --- /dev/null +++ b/ios/ImageNotification/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ImageNotification + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/ios/ImageNotification/NotificationService.swift b/ios/ImageNotification/NotificationService.swift new file mode 100644 index 00000000..d16342e0 --- /dev/null +++ b/ios/ImageNotification/NotificationService.swift @@ -0,0 +1,27 @@ +import FirebaseMessaging +import UserNotifications + +class NotificationService: UNNotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + bestAttemptContent = request.content + .mutableCopy() as? UNMutableNotificationContent + guard let bestAttemptContent = bestAttemptContent else { return } + FIRMessagingExtensionHelper().populateNotificationContent( + bestAttemptContent, + withContentHandler: contentHandler) + } + + override func serviceExtensionTimeWillExpire() { + // Called just before the extension will be terminated by the system. + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + contentHandler(bestAttemptContent) + } + } + +} diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 00000000..23464e32 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,45 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! :linkage => :static + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + target.build_configurations.each do |config| + config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' + + end + end +end diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..5f2695cd --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*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 */; }; + 44A671D52BC7AFBA0042F967 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 44A671D42BC7AFBA0042F967 /* PrivacyInfo.xcprivacy */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 6436409A27A31CD800820AF7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6436409C27A31CD800820AF7 /* InfoPlist.strings */; }; + 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 = ( + ); + 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 = ""; }; + 44A671D42BC7AFBA0042F967 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 6436409527A31CDE00820AF7 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = ""; }; + 6436409227A31CDC00820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; 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 = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 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 */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + 6436409C27A31CD800820AF7 /* InfoPlist.strings */, + 44A671D42BC7AFBA0042F967 /* PrivacyInfo.xcprivacy */, + ); + path = Runner; + 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 = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = pt; + hasScannedForEncodings = 0; + knownRegions = ( + pt, + 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 */, + 44A671D52BC7AFBA0042F967 /* PrivacyInfo.xcprivacy in Resources */, + 6436409A27A31CD800820AF7 /* InfoPlist.strings 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\" embed_and_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 */ + 6436409C27A31CD800820AF7 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 6436409527A31CDE00820AF7 /* pt */, + 6436409227A31CDC00820AF7 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.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.freaccess.hub; + 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; + 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 = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.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.freaccess.hub; + 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.freaccess.hub; + 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 00000000..1d526a16 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..a28140cf --- /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 00000000..1d526a16 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..f52eb22e --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,14 @@ +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 00000000..d36b1fab --- /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 00000000..dc9ada47 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 00000000..28c6bf03 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 00000000..2ccbfd96 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 00000000..f091b6b0 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 00000000..4cde1211 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 00000000..d0ef06e7 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 00000000..dcdc2306 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 00000000..2ccbfd96 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 00000000..c8f9ed8f 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 00000000..a6d6b860 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 00000000..a6d6b860 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 00000000..75b2d164 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 00000000..c4df70d3 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 00000000..6a84f41e 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 00000000..d0e1f585 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 00000000..0bedcf2f --- /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 00000000..9da19eac 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 00000000..9da19eac 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 00000000..9da19eac 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 00000000..89c2725b --- /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 00000000..f2e259c7 --- /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 00000000..f3c28516 --- /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 00000000..ed9b52db --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,78 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + FREHub + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + FREHub + CFBundlePackageType + APPL + CFBundleLocalizations + + pt + en + + + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleURLTypes + + CFBundleTypeRole + Editor + CFBundleURLName + frehub.com + CFBundleURLSchemes + + frehub + + + + FlutterDeepLinkingEnabled + + + + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + + NSCameraUsageDescription + In order to take a picture or video, this app requires permission to access the camera. + NSPhotoLibraryUsageDescription + In order to upload data, this app requires permission to access the photo library. + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + + diff --git a/ios/Runner/PrivacyInfo.xcprivacy b/ios/Runner/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/ios/Runner/PrivacyInfo.xcprivacy @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 00000000..6631ffa6 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,6 @@ + + + + + + diff --git a/ios/Runner/en.lproj/InfoPlist.strings b/ios/Runner/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..9b1e3bbf --- /dev/null +++ b/ios/Runner/en.lproj/InfoPlist.strings @@ -0,0 +1 @@ +NSCameraUsageDescription = "dd/mm/yyyy"; diff --git a/ios/Runner/pt.lproj/InfoPlist.strings b/ios/Runner/pt.lproj/InfoPlist.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/ios/Runner/pt.lproj/InfoPlist.strings @@ -0,0 +1 @@ + diff --git a/lib/actions/actions.dart b/lib/actions/actions.dart new file mode 100644 index 00000000..6cbc3c59 --- /dev/null +++ b/lib/actions/actions.dart @@ -0,0 +1,275 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/actions/index.dart' as actions; +import '/flutter_flow/random_data_util.dart' as random_data; +import 'package:flutter/material.dart'; + +Future repeatVisitScheduleAction( + BuildContext context, { + List? visitorJsonList, + String? visitorStrList, + String? visitStartDateStr, + String? visitEndDateStr, + String? visitReasonStr, + String? visitLevelStr, + bool? visitTempBol, + String? visitObsStr, +}) async { + context.pushNamed( + 'scheduleCompleteVisitPage', + queryParameters: { + 'visitStartDateStr': serializeParam( + visitStartDateStr, + ParamType.String, + ), + 'visitEndDateStr': serializeParam( + visitEndDateStr, + ParamType.String, + ), + 'visitReasonStr': serializeParam( + visitReasonStr, + ParamType.String, + ), + 'visitLevelStr': serializeParam( + visitLevelStr, + ParamType.String, + ), + 'visitTempBol': serializeParam( + visitTempBol, + ParamType.bool, + ), + 'visitObsStr': serializeParam( + visitObsStr, + ParamType.String, + ), + 'visitorStrList': serializeParam( + visitorStrList, + ParamType.String, + ), + 'visitorJsonList': serializeParam( + visitorJsonList, + ParamType.JSON, + true, + ), + }.withoutNulls, + ); +} + +Future manageStatusColorAction( + BuildContext context, { + required String? visitStatusStr, +}) async { + if (visitStatusStr == 'A') { + return FlutterFlowTheme.of(context).success; + } else if ((visitStatusStr == 'C') || + (visitStatusStr == 'F') || + (visitStatusStr == 'B') || + (visitStatusStr == 'I')) { + return FlutterFlowTheme.of(context).error; + } + + return FlutterFlowTheme.of(context).warning; +} + +Future singInActionApp( + BuildContext context, { + String? emailAdress, + String? password, +}) async { + String? devUUID; + ApiCallResponse? loginCall; + + await Future.wait([ + Future(() async { + FFAppState().email = emailAdress!; + }), + Future(() async { + FFAppState().passwd = password!; + }), + ]); + if ((FFAppState().email != '') && + (FFAppState().passwd != '')) { + devUUID = await actions.getDevUUID(); + FFAppState().devUUID = devUUID!; + loginCall = await PhpGroup.loginCall.call( + email: FFAppState().email, + password: FFAppState().passwd, + uuid: FFAppState().devUUID, + type: FFAppState().device, + description: random_data.randomString( + 10, + 10, + true, + false, + false, + ), + ); + FFAppState().userUUID = PhpGroup.loginCall.userUUID( + (loginCall.jsonBody ?? ''), + )!; + if (PhpGroup.loginCall.error( + (loginCall.jsonBody ?? ''), + ) == + false) { + FFAppState().isLogged = true; + + context.goNamed( + 'homePage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.fade, + ), + }, + ); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: PhpGroup.loginCall.msg( + (loginCall?.jsonBody ?? ''), + )!, + ), + ); + }, + ); + + FFAppState().email = ''; + FFAppState().passwd = ''; + FFAppState().update(() {}); + } + } else { + return; + } +} + +Future signUpActionApp( + BuildContext context, { + required String? name, + String? passwd, + required String? email, + String? device, +}) async { + ApiCallResponse? registerCall; + + if ((email != null && email != '') && + (passwd != null && passwd != '') && + (name != null && name != '')) { + registerCall = await PhpGroup.registerCall.call( + name: name, + password: passwd, + email: email, + token: random_data.randomString( + 36, + 36, + false, + false, + true, + ), + uuid: random_data.randomString( + 36, + 36, + false, + false, + true, + ), + tipo: device, + descricao: random_data.randomString( + 36, + 36, + true, + false, + false, + ), + ); + if (PhpGroup.registerCall.error( + (registerCall.jsonBody ?? ''), + ) == + false) { + return true; + } + + await showDialog( + context: context, + builder: (alertDialogContext) { + return AlertDialog( + title: const Text('ERROR2'), + content: const Text('ERROR2'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(alertDialogContext), + child: const Text('ERROR2 '), + ), + ], + ); + }, + ); + return false; + } else { + await showDialog( + context: context, + builder: (alertDialogContext) { + return AlertDialog( + title: const Text('ERROR1'), + content: const Text('ERROR1'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(alertDialogContext), + child: const Text('ERROR1 '), + ), + ], + ); + }, + ); + return false; + } +} + +Future forgotPasswdAction( + BuildContext context, { + required String? email, +}) async { + ApiCallResponse? forgotPasswd; + + forgotPasswd = await PhpGroup.forgotPasswordCall.call( + email: email, + ); + if (PhpGroup.forgotPasswordCall.error( + (forgotPasswd.jsonBody ?? ''), + ) == + false) { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': serializeParam( + FFAppState().device, + ParamType.String, + ), + }.withoutNulls, + ); + } else { + return; + } +} + +Future cachingLoginActionApp(BuildContext context) async { + if (FFAppState().isLogged == true) { + context.pushNamed('homePage'); + } else { + if (isAndroid == true) { + FFAppState().device = 'Android'; + } else if (isiOS == true) { + FFAppState().device = 'iOS'; + } else { + FFAppState().device = 'Web'; + } + } +} diff --git a/lib/app_state.dart b/lib/app_state.dart new file mode 100644 index 00000000..f0256969 --- /dev/null +++ b/lib/app_state.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class FFAppState extends ChangeNotifier { + static FFAppState _instance = FFAppState._internal(); + + factory FFAppState() { + return _instance; + } + + FFAppState._internal(); + + static void reset() { + _instance = FFAppState._internal(); + } + + Future initializePersistedState() async { + prefs = await SharedPreferences.getInstance(); + _safeInit(() { + _cliUUID = prefs.getString('ff_cliUUID') ?? _cliUUID; + }); + _safeInit(() { + _ownerUUID = prefs.getString('ff_ownerUUID') ?? _ownerUUID; + }); + _safeInit(() { + _userUUID = prefs.getString('ff_userUUID') ?? _userUUID; + }); + _safeInit(() { + _devUUID = prefs.getString('ff_devUUID') ?? _devUUID; + }); + _safeInit(() { + _email = prefs.getString('ff_email') ?? _email; + }); + _safeInit(() { + _passwd = prefs.getString('ff_passwd') ?? _passwd; + }); + _safeInit(() { + _device = prefs.getString('ff_device') ?? _device; + }); + _safeInit(() { + _isLogged = prefs.getBool('ff_isLogged') ?? _isLogged; + }); + _safeInit(() { + _local = prefs.getString('ff_local') ?? _local; + }); + } + + void update(VoidCallback callback) { + callback(); + notifyListeners(); + } + + late SharedPreferences prefs; + + String _cliUUID = ''; + String get cliUUID => _cliUUID; + set cliUUID(String value) { + _cliUUID = value; + prefs.setString('ff_cliUUID', value); + } + + String _ownerUUID = ''; + String get ownerUUID => _ownerUUID; + set ownerUUID(String value) { + _ownerUUID = value; + prefs.setString('ff_ownerUUID', value); + } + + String _userUUID = ''; + String get userUUID => _userUUID; + set userUUID(String value) { + _userUUID = value; + prefs.setString('ff_userUUID', value); + } + + String _devUUID = ''; + String get devUUID => _devUUID; + set devUUID(String value) { + _devUUID = value; + prefs.setString('ff_devUUID', value); + } + + String _email = ''; + String get email => _email; + set email(String value) { + _email = value; + prefs.setString('ff_email', value); + } + + String _passwd = ''; + String get passwd => _passwd; + set passwd(String value) { + _passwd = value; + prefs.setString('ff_passwd', value); + } + + String _device = ''; + String get device => _device; + set device(String value) { + _device = value; + prefs.setString('ff_device', value); + } + + bool _isLogged = false; + bool get isLogged => _isLogged; + set isLogged(bool value) { + _isLogged = value; + prefs.setBool('ff_isLogged', value); + } + + String _local = ''; + String get local => _local; + set local(String value) { + _local = value; + prefs.setString('ff_local', value); + } +} + +void _safeInit(Function() initializeField) { + try { + initializeField(); + } catch (_) {} +} + +Future _safeInitAsync(Function() initializeField) async { + try { + await initializeField(); + } catch (_) {} +} diff --git a/lib/application_components/atomic_components/text_field_component/text_field_component_model.dart b/lib/application_components/atomic_components/text_field_component/text_field_component_model.dart new file mode 100644 index 00000000..30f54431 --- /dev/null +++ b/lib/application_components/atomic_components/text_field_component/text_field_component_model.dart @@ -0,0 +1,22 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'text_field_component_widget.dart' show TextFieldComponentWidget; +import 'package:flutter/material.dart'; + +class TextFieldComponentModel + extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode; + TextEditingController? textController; + String? Function(BuildContext, String?)? textControllerValidator; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode?.dispose(); + textController?.dispose(); + } +} diff --git a/lib/application_components/atomic_components/text_field_component/text_field_component_widget.dart b/lib/application_components/atomic_components/text_field_component/text_field_component_widget.dart new file mode 100644 index 00000000..e9ab116f --- /dev/null +++ b/lib/application_components/atomic_components/text_field_component/text_field_component_widget.dart @@ -0,0 +1,117 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'text_field_component_model.dart'; +export 'text_field_component_model.dart'; + +class TextFieldComponentWidget extends StatefulWidget { + const TextFieldComponentWidget({ + super.key, + this.initialValueStrParam, + this.labelTextStrParam, + this.hintTextStrParam, + }); + + final String? initialValueStrParam; + final String? labelTextStrParam; + final String? hintTextStrParam; + + @override + State createState() => + _TextFieldComponentWidgetState(); +} + +class _TextFieldComponentWidgetState extends State { + late TextFieldComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => TextFieldComponentModel()); + + _model.textController ??= + TextEditingController(text: widget.initialValueStrParam); + _model.textFieldFocusNode ??= FocusNode(); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB(8.0, 10.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController, + focusNode: _model.textFieldFocusNode, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: widget.labelTextStrParam, + labelStyle: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintText: widget.hintTextStrParam, + hintStyle: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).secondaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), + ), + validator: _model.textControllerValidator.asValidator(context), + ), + ); + } +} diff --git a/lib/application_components/molecular_components/opt_modal/opt_modal_model.dart b/lib/application_components/molecular_components/opt_modal/opt_modal_model.dart new file mode 100644 index 00000000..c05b8e19 --- /dev/null +++ b/lib/application_components/molecular_components/opt_modal/opt_modal_model.dart @@ -0,0 +1,11 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'opt_modal_widget.dart' show OptModalWidget; +import 'package:flutter/material.dart'; + +class OptModalModel extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/molecular_components/opt_modal/opt_modal_widget.dart b/lib/application_components/molecular_components/opt_modal/opt_modal_widget.dart new file mode 100644 index 00000000..536c2e80 --- /dev/null +++ b/lib/application_components/molecular_components/opt_modal/opt_modal_widget.dart @@ -0,0 +1,68 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'opt_modal_model.dart'; +export 'opt_modal_model.dart'; + +class OptModalWidget extends StatefulWidget { + const OptModalWidget({super.key}); + + @override + State createState() => _OptModalWidgetState(); +} + +class _OptModalWidgetState extends State { + late OptModalModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => OptModalModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + width: double.infinity, + height: 400.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Icon( + Icons.settings, + color: FlutterFlowTheme.of(context).primary, + size: 24.0, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_model.dart b/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_model.dart new file mode 100644 index 00000000..d9448232 --- /dev/null +++ b/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'option_selection_modal_widget.dart' show OptionSelectionModalWidget; +import 'package:flutter/material.dart'; + +class OptionSelectionModalModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_widget.dart b/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_widget.dart new file mode 100644 index 00000000..8baf37ac --- /dev/null +++ b/lib/application_components/molecular_components/option_selection_modal/option_selection_modal_widget.dart @@ -0,0 +1,389 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'option_selection_modal_model.dart'; +export 'option_selection_modal_model.dart'; + +class OptionSelectionModalWidget extends StatefulWidget { + const OptionSelectionModalWidget({super.key}); + + @override + State createState() => + _OptionSelectionModalWidgetState(); +} + +class _OptionSelectionModalWidgetState extends State + with TickerProviderStateMixin { + late OptionSelectionModalModel _model; + + final animationsMap = {}; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => OptionSelectionModalModel()); + + animationsMap.addAll({ + 'wrapOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 100.0.ms, + begin: const Offset(0.0, 0.0), + end: const Offset(1.0, 1.0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Wrap( + spacing: 17.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + }, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).customColor1, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.schedule_send, + color: FlutterFlowTheme.of(context) + .accent1, + size: 34.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'omxabblt' /* Agenda +Rápida */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + + context.pushNamed('scheduleProvisionalVisitPage'); + }, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).customColor1, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.hourglass_bottom, + color: FlutterFlowTheme.of(context) + .accent1, + size: 34.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'vpy51li0' /* Agenda +Provisória */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + + context.pushNamed('scheduleCompleteVisitPage'); + }, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).customColor1, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.scale, + color: FlutterFlowTheme.of(context) + .accent1, + size: 34.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '8ad3hms9' /* Agenda +Completa */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ), + ], + ).animateOnPageLoad(animationsMap['wrapOnPageLoadAnimation']!), + ), + ], + ); + } +} diff --git a/lib/application_components/molecular_components/throw_exception/throw_exception_model.dart b/lib/application_components/molecular_components/throw_exception/throw_exception_model.dart new file mode 100644 index 00000000..31b6cee7 --- /dev/null +++ b/lib/application_components/molecular_components/throw_exception/throw_exception_model.dart @@ -0,0 +1,11 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'throw_exception_widget.dart' show ThrowExceptionWidget; +import 'package:flutter/material.dart'; + +class ThrowExceptionModel extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/molecular_components/throw_exception/throw_exception_widget.dart b/lib/application_components/molecular_components/throw_exception/throw_exception_widget.dart new file mode 100644 index 00000000..684115dd --- /dev/null +++ b/lib/application_components/molecular_components/throw_exception/throw_exception_widget.dart @@ -0,0 +1,125 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'throw_exception_model.dart'; +export 'throw_exception_model.dart'; + +class ThrowExceptionWidget extends StatefulWidget { + const ThrowExceptionWidget({ + super.key, + required this.msg, + }); + + final String? msg; + + @override + State createState() => _ThrowExceptionWidgetState(); +} + +class _ThrowExceptionWidgetState extends State + with TickerProviderStateMixin { + late ThrowExceptionModel _model; + + final animationsMap = {}; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ThrowExceptionModel()); + + animationsMap.addAll({ + 'stackOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 600.0.ms, + begin: 0.0, + end: 1.0, + ), + ], + ), + }); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.circle_outlined, + color: FlutterFlowTheme.of(context).error, + size: 200.0, + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.close_outlined, + color: FlutterFlowTheme.of(context).error, + size: 200.0, + ), + ), + ], + ).animateOnPageLoad(animationsMap['stackOnPageLoadAnimation']!), + Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + FFLocalizations.of(context).getText( + 'e58xxxiq' /* ERRO */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, + fontSize: 20.0, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Text( + valueOrDefault( + widget.msg, + 'Message Not Found', + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ].addToStart(const SizedBox(height: 50.0)), + ), + ], + ); + } +} diff --git a/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_model.dart b/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_model.dart new file mode 100644 index 00000000..f89f479d --- /dev/null +++ b/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_model.dart @@ -0,0 +1,13 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'visitor_not_found_component_widget.dart' + show VisitorNotFoundComponentWidget; +import 'package:flutter/material.dart'; + +class VisitorNotFoundComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_widget.dart b/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_widget.dart new file mode 100644 index 00000000..a6b63538 --- /dev/null +++ b/lib/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_widget.dart @@ -0,0 +1,177 @@ +import '/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'visitor_not_found_component_model.dart'; +export 'visitor_not_found_component_model.dart'; + +class VisitorNotFoundComponentWidget extends StatefulWidget { + const VisitorNotFoundComponentWidget({super.key}); + + @override + State createState() => + _VisitorNotFoundComponentWidgetState(); +} + +class _VisitorNotFoundComponentWidgetState + extends State { + late VisitorNotFoundComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => VisitorNotFoundComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Container( + width: 350.0, + height: 350.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Align( + alignment: const AlignmentDirectional(1.0, -1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 5.0, 5.0, 0.0), + child: FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.close, + color: FlutterFlowTheme.of(context).accent1, + size: 24.0, + ), + onPressed: () async { + Navigator.pop(context); + }, + ), + ), + ), + Icon( + Icons.notifications_none, + color: FlutterFlowTheme.of(context).accent1, + size: 72.0, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 16.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '1p9mykbj' /* Usuário não encontrado */, + ), + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: + FlutterFlowTheme.of(context).headlineMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(10.0, 4.0, 10.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'kt937sp6' /* O documento inserido não corre... */, + ), + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontStyle: FontStyle.italic, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + ), + ), + Expanded( + child: Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: FFButtonWidget( + onPressed: () async { + Navigator.pop(context); + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const RegisiterVistorComponentWidget(), + ); + }, + ).then((value) => safeSetState(() {})); + }, + text: FFLocalizations.of(context).getText( + 'y2x4nfcn' /* Adicionar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 30.0, + padding: + const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: + FlutterFlowTheme.of(context).titleSmallFamily, + color: Colors.white, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).titleSmallFamily), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_model.dart b/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_model.dart new file mode 100644 index 00000000..f0b590e3 --- /dev/null +++ b/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_model.dart @@ -0,0 +1,13 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'bottom_arrow_linked_locals_component_widget.dart' + show BottomArrowLinkedLocalsComponentWidget; +import 'package:flutter/material.dart'; + +class BottomArrowLinkedLocalsComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart b/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart new file mode 100644 index 00000000..7637f47f --- /dev/null +++ b/lib/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart @@ -0,0 +1,247 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'bottom_arrow_linked_locals_component_model.dart'; +export 'bottom_arrow_linked_locals_component_model.dart'; + +class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget { + const BottomArrowLinkedLocalsComponentWidget({super.key}); + + @override + State createState() => + _BottomArrowLinkedLocalsComponentWidgetState(); +} + +class _BottomArrowLinkedLocalsComponentWidgetState + extends State { + late BottomArrowLinkedLocalsComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = + createModel(context, () => BottomArrowLinkedLocalsComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + width: double.infinity, + height: 150.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 150.0, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: FutureBuilder( + future: PhpGroup.getLocalsCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } + final gridViewGetLocalsResponse = snapshot.data!; + return Builder( + builder: (context) { + final eachLocals = (PhpGroup.getLocalsCall + .locais( + gridViewGetLocalsResponse.jsonBody, + ) + ?.map((e) => e) + .toList() + .toList() ?? + []) + .take(2) + .toList(); + return GridView.builder( + padding: EdgeInsets.zero, + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + crossAxisSpacing: 10.0, + mainAxisSpacing: 0.0, + childAspectRatio: 1.0, + ), + scrollDirection: Axis.horizontal, + itemCount: eachLocals.length, + itemBuilder: (context, eachLocalsIndex) { + final eachLocalsItem = + eachLocals[eachLocalsIndex]; + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + FFAppState().cliUUID = getJsonField( + eachLocalsItem, + r'''$.CLI_ID''', + ).toString(); + setState(() {}); + FFAppState().local = getJsonField( + eachLocalsItem, + r'''$.CLI_NOME''', + ).toString(); + setState(() {}); + FFAppState().ownerUUID = getJsonField( + eachLocalsItem, + r'''$.CLU_OWNER_ID''', + ).toString(); + setState(() {}); + Navigator.pop(context); + }, + child: Container( + width: 50.0, + height: double.infinity, + decoration: const BoxDecoration(), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryText, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: + Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + border: Border.all( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 3.0, + ), + ), + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: + Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + child: Image.network( + 'https://freaccess.com.br/freaccess/Images/Clients/${getJsonField( + eachLocalsItem, + r'''$.CLI_ID''', + ).toString()}.png', + width: double.infinity, + height: double.infinity, + fit: BoxFit.fill, + alignment: const Alignment(0.0, 0.0), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Text( + getJsonField( + eachLocalsItem, + r'''$.CLI_NOME''', + ).toString(), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ], + ), + ), + ); + }, + ); + }, + ); + }, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/organism_components/local_profile_component/local_profile_component_model.dart b/lib/application_components/organism_components/local_profile_component/local_profile_component_model.dart new file mode 100644 index 00000000..25442482 --- /dev/null +++ b/lib/application_components/organism_components/local_profile_component/local_profile_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'local_profile_component_widget.dart' show LocalProfileComponentWidget; +import 'package:flutter/material.dart'; + +class LocalProfileComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/organism_components/local_profile_component/local_profile_component_widget.dart b/lib/application_components/organism_components/local_profile_component/local_profile_component_widget.dart new file mode 100644 index 00000000..ec4c3b0a --- /dev/null +++ b/lib/application_components/organism_components/local_profile_component/local_profile_component_widget.dart @@ -0,0 +1,151 @@ +import '/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/custom_functions.dart' as functions; +import '/flutter_flow/random_data_util.dart' as random_data; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'local_profile_component_model.dart'; +export 'local_profile_component_model.dart'; + +class LocalProfileComponentWidget extends StatefulWidget { + const LocalProfileComponentWidget({super.key}); + + @override + State createState() => + _LocalProfileComponentWidgetState(); +} + +class _LocalProfileComponentWidgetState + extends State { + late LocalProfileComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => LocalProfileComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Visibility( + visible: random_data.randomInteger(0, 10) != null, + child: Container( + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Material( + color: Colors.transparent, + elevation: 0.0, + child: Container( + width: double.infinity, + height: 119.0, + decoration: BoxDecoration( + color: const Color(0xFF1AAB5F), + border: Border.all( + color: const Color(0xFF1AAB5F), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(2.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + showModalBottomSheet( + isScrollControlled: true, + backgroundColor: const Color(0x00FFFFFF), + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const SizedBox( + height: double.infinity, + child: + BottomArrowLinkedLocalsComponentWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(200.0), + child: Image.network( + valueOrDefault( + 'https://freaccess.com.br/freaccess/Images/Clients/${FFAppState().cliUUID}.png', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: 80.0, + height: 80.0, + fit: BoxFit.cover, + alignment: const Alignment(0.0, 0.0), + errorBuilder: (context, error, stackTrace) => + Image.asset( + 'assets/images/error_image.svg', + width: 80.0, + height: 80.0, + fit: BoxFit.cover, + alignment: const Alignment(0.0, 0.0), + ), + ), + ), + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + valueOrDefault( + functions.convertToUppercase(FFAppState().local), + 'NOME DO LOCAL', + ), + style: + FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context).info, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + ], + ), + ] + .divide(const SizedBox(width: 20.0)) + .addToStart(const SizedBox(width: 20.0)) + .addToEnd(const SizedBox(width: 20.0)), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_model.dart b/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_model.dart new file mode 100644 index 00000000..7ce9985b --- /dev/null +++ b/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'menu_list_view_component_widget.dart' show MenuListViewComponentWidget; +import 'package:flutter/material.dart'; + +class MenuListViewComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart b/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart new file mode 100644 index 00000000..607e68af --- /dev/null +++ b/lib/application_components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart @@ -0,0 +1,630 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'menu_list_view_component_model.dart'; +export 'menu_list_view_component_model.dart'; + +class MenuListViewComponentWidget extends StatefulWidget { + const MenuListViewComponentWidget({ + super.key, + required this.changeMenuStyle, + required this.registerVisitorAction, + required this.scheduleVisitAction, + }); + + final Future Function()? changeMenuStyle; + final Future Function()? registerVisitorAction; + final Future Function()? scheduleVisitAction; + + @override + State createState() => + _MenuListViewComponentWidgetState(); +} + +class _MenuListViewComponentWidgetState + extends State { + late MenuListViewComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => MenuListViewComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Wrap( + spacing: 0.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(5.0, 0.0, 5.0, 0.0), + child: Container( + width: double.infinity, + height: 125.0, + decoration: const BoxDecoration(), + child: ListView( + padding: const EdgeInsets.fromLTRB( + 10.0, + 0, + 10.0, + 0, + ), + scrollDirection: Axis.horizontal, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 20.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.scheduleVisitAction?.call(); + }, + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kvector1, + color: FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'utgue9a5' /* Agendar +Visita */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 20.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.registerVisitorAction?.call(); + }, + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kvector, + color: FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '82b5f8yz' /* Cadastrar +Visitante */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 20.0), + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.khome, + color: FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 't4ie13ut' /* Vincular +Condomínio */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 20.0), + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kpets, + color: FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'n3n76pha' /* Cadastrar +Pet */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 20.0), + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kvector2, + color: FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'l6b9o7yn' /* QR Code +de Acesso */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + ].divide(const SizedBox(width: 15.0)), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 50.0, + fillColor: const Color(0x00FFFFFF), + icon: Icon( + Icons.keyboard_arrow_down_outlined, + color: FlutterFlowTheme.of(context).primary, + ), + onPressed: () async { + await widget.changeMenuStyle?.call(); + }, + ), + ), + ], + ); + } +} diff --git a/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_model.dart b/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_model.dart new file mode 100644 index 00000000..8aebfc69 --- /dev/null +++ b/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_model.dart @@ -0,0 +1,13 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'menu_staggered_view_component_widget.dart' + show MenuStaggeredViewComponentWidget; +import 'package:flutter/material.dart'; + +class MenuStaggeredViewComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart b/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart new file mode 100644 index 00000000..8fc6e479 --- /dev/null +++ b/lib/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart @@ -0,0 +1,667 @@ +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'menu_staggered_view_component_model.dart'; +export 'menu_staggered_view_component_model.dart'; + +class MenuStaggeredViewComponentWidget extends StatefulWidget { + const MenuStaggeredViewComponentWidget({ + super.key, + required this.changeMenuStyleAction, + required this.registerVisitorOptAction, + required this.scheduleVisitOptAction, + }); + + final Future Function()? changeMenuStyleAction; + final Future Function()? registerVisitorOptAction; + final Future Function()? scheduleVisitOptAction; + + @override + State createState() => + _MenuStaggeredViewComponentWidgetState(); +} + +class _MenuStaggeredViewComponentWidgetState + extends State { + late MenuStaggeredViewComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => MenuStaggeredViewComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Wrap( + spacing: 0.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * 0.35, + decoration: const BoxDecoration(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: MasonryGridView.builder( + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverSimpleGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + ), + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + itemCount: 5, + shrinkWrap: true, + itemBuilder: (context, index) { + return [ + () => InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.scheduleVisitOptAction?.call(); + }, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: + FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Icon( + FFIcons.kvector1, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'ee33l0ms' /* Agendar +Visita */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + () => InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.registerVisitorOptAction?.call(); + }, + child: Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: + FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Icon( + FFIcons.kvector, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'ya37l3jt' /* Cadastrar + Visitante */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ), + () => Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.khome, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'h8s3adu8' /* Vincular +Condomínio */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + () => Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kpets, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'j6tfixen' /* Cadastrar +Pet */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + () => Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 4.0, + color: FlutterFlowTheme.of(context).customColor5, + offset: const Offset( + 0.0, + 2.0, + ), + ) + ], + borderRadius: BorderRadius.circular(24.0), + shape: BoxShape.rectangle, + border: Border.all( + color: FlutterFlowTheme.of(context).alternate, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 0.0, 0.0), + child: Container( + width: 30.0, + height: 30.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .primaryBackground, + shape: BoxShape.circle, + ), + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Icon( + FFIcons.kvector2, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '9tli4i2x' /* QR Code +de Acesso */ + , + ), + style: FlutterFlowTheme.of(context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ], + ), + ), + ].divide(const SizedBox(height: 0.0)), + ), + ), + ), + ][index](); + }, + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 50.0, + fillColor: const Color(0x00FFFFFF), + icon: Icon( + Icons.keyboard_arrow_up_sharp, + color: FlutterFlowTheme.of(context).primary, + ), + onPressed: () async { + await widget.changeMenuStyleAction?.call(); + }, + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_model.dart b/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_model.dart new file mode 100644 index 00000000..d30b8442 --- /dev/null +++ b/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_model.dart @@ -0,0 +1,60 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'schedule_visit_detail_widget.dart' show ScheduleVisitDetailWidget; +import 'package:flutter/material.dart'; + +class ScheduleVisitDetailModel + extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode4; + TextEditingController? textController4; + String? Function(BuildContext, String?)? textController4Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode5; + TextEditingController? textController5; + String? Function(BuildContext, String?)? textController5Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode6; + TextEditingController? textController6; + String? Function(BuildContext, String?)? textController6Validator; + // Stores action output result for [Backend Call - API (postScheduleVisit)] action in Icon widget. + ApiCallResponse? postScheduleVisit; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + + textFieldFocusNode4?.dispose(); + textController4?.dispose(); + + textFieldFocusNode5?.dispose(); + textController5?.dispose(); + + textFieldFocusNode6?.dispose(); + textController6?.dispose(); + } +} diff --git a/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart b/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart new file mode 100644 index 00000000..83d530d2 --- /dev/null +++ b/lib/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart @@ -0,0 +1,976 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/custom_functions.dart' as functions; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'schedule_visit_detail_model.dart'; +export 'schedule_visit_detail_model.dart'; + +class ScheduleVisitDetailWidget extends StatefulWidget { + const ScheduleVisitDetailWidget({ + super.key, + required this.visitorJsonList, + required this.visitorStrList, + this.visitorImgPath, + required this.visitStartDate, + required this.visitEndDate, + required this.visitResonStr, + required this.visitLevelStr, + required this.visitTempStr, + required this.visitObsStr, + }); + + final List? visitorJsonList; + final String? visitorStrList; + final String? visitorImgPath; + final String? visitStartDate; + final String? visitEndDate; + final String? visitResonStr; + final String? visitLevelStr; + final String? visitTempStr; + final String? visitObsStr; + + @override + State createState() => + _ScheduleVisitDetailWidgetState(); +} + +class _ScheduleVisitDetailWidgetState extends State { + late ScheduleVisitDetailModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ScheduleVisitDetailModel()); + + _model.textController1 ??= TextEditingController(text: widget.visitTempStr); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= + TextEditingController(text: widget.visitStartDate); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.textController3 ??= TextEditingController(text: widget.visitEndDate); + _model.textFieldFocusNode3 ??= FocusNode(); + + _model.textController4 ??= TextEditingController( + text: functions.extractDescToStr(widget.visitResonStr!)); + _model.textFieldFocusNode4 ??= FocusNode(); + + _model.textController5 ??= TextEditingController( + text: functions.extractDescToStr(widget.visitLevelStr!)); + _model.textFieldFocusNode5 ??= FocusNode(); + + _model.textController6 ??= TextEditingController(text: widget.visitObsStr); + _model.textFieldFocusNode6 ??= FocusNode(); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 35.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Container( + width: double.infinity, + height: 35.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Visibility( + visible: widget.visitorStrList != null && + widget.visitorStrList != '', + child: Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 0.0, 0.0), + child: FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.keyboard_return, + color: FlutterFlowTheme.of(context).primaryBackground, + size: 24.0, + ), + onPressed: () async { + Navigator.pop(context); + }, + ), + ), + ), + ), + ), + ), + Container( + decoration: const BoxDecoration( + shape: BoxShape.rectangle, + ), + child: Stack( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 5.0, 0.0, 5.0, 20.0), + child: Container( + width: 100.0, + decoration: const BoxDecoration(), + child: Builder( + builder: (context) { + final visitorsData = widget.visitorJsonList! + .toList() + .take(1) + .toList(); + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(visitorsData.length, + (visitorsDataIndex) { + final visitorsDataItem = + visitorsData[visitorsDataIndex]; + return Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(100.0), + ), + child: Align( + alignment: + const AlignmentDirectional(1.0, -1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: + Colors.transparent, + useSafeArea: true, + context: context, + builder: (context) { + return Padding( + padding: + MediaQuery.viewInsetsOf( + context), + child: + const VisitorDetailsModalWidget(), + ); + }, + ).then((value) => + safeSetState(() {})); + }, + child: ClipRRect( + borderRadius: + BorderRadius.circular(100.0), + child: CachedNetworkImage( + fadeInDuration: + const Duration(milliseconds: 500), + fadeOutDuration: + const Duration(milliseconds: 500), + imageUrl: + valueOrDefault( + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + visitorsDataItem, + r'''$.VTE_DOCUMENTO''', + ).toString()}&tipo=E', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + ), + ), + ); + }), + ), + ); + }, + ), + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: const BoxDecoration(), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController1, + focusNode: _model.textFieldFocusNode1, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + isDense: false, + labelText: + FFLocalizations.of(context).getText( + '7w4fohoa' /* Encerramento da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController1Validator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 10.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController2, + focusNode: _model.textFieldFocusNode2, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'snah4iet' /* Início */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + '0cp1e31d' /* dd/mm/yyyy */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController2Validator + .asValidator(context), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController3, + focusNode: _model.textFieldFocusNode3, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'abppdgz3' /* Término */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + 'kqralft4' /* dd/mm/yyyy */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController3Validator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 10.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController4, + focusNode: _model.textFieldFocusNode4, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'xjxhzqqm' /* Motivo da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + '47oezdm6' /* Motivo */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController4Validator + .asValidator(context), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController5, + focusNode: _model.textFieldFocusNode5, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + '2ujg7u18' /* Nível de Acesso */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + '3emmbbfv' /* Nível de Acesso */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController5Validator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Container( + decoration: const BoxDecoration(), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController6, + focusNode: _model.textFieldFocusNode6, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'ritce5uw' /* Observações da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController6Validator + .asValidator(context), + ), + ), + ), + ], + ), + Container( + width: double.infinity, + height: 22.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).secondaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + ), + ] + .divide(const SizedBox(height: 30.0)) + .addToStart(const SizedBox(height: 100.0)), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 6.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: 35.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + _model.postScheduleVisit = + await PhpGroup.postScheduleVisitCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + atividade: 'putVisita', + devDesc: widget.visitObsStr, + idVisitante: widget.visitorStrList, + dtInicio: widget.visitStartDate, + dtFim: widget.visitEndDate, + unica: widget.visitTempStr, + idMotivo: + functions.extractIdToStr(widget.visitResonStr!), + idNAC: functions.extractIdToStr(widget.visitLevelStr!), + obs: widget.visitObsStr, + cliID: FFAppState().cliUUID, + ); + if (PhpGroup.postScheduleVisitCall.error( + (_model.postScheduleVisit?.jsonBody ?? ''), + ) == + false) { + Navigator.pop(context); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: PhpGroup.postScheduleVisitCall.errorMsg( + (_model.postScheduleVisit?.jsonBody ?? ''), + )!, + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + child: Icon( + Icons.save_alt, + color: FlutterFlowTheme.of(context).secondaryText, + size: 24.0, + ), + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_model.dart b/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_model.dart new file mode 100644 index 00000000..e4db1d96 --- /dev/null +++ b/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_model.dart @@ -0,0 +1,13 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'up_arrow_linked_locals_component_widget.dart' + show UpArrowLinkedLocalsComponentWidget; +import 'package:flutter/material.dart'; + +class UpArrowLinkedLocalsComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart b/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart new file mode 100644 index 00000000..49237edc --- /dev/null +++ b/lib/application_components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart @@ -0,0 +1,241 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'up_arrow_linked_locals_component_model.dart'; +export 'up_arrow_linked_locals_component_model.dart'; + +class UpArrowLinkedLocalsComponentWidget extends StatefulWidget { + const UpArrowLinkedLocalsComponentWidget({super.key}); + + @override + State createState() => + _UpArrowLinkedLocalsComponentWidgetState(); +} + +class _UpArrowLinkedLocalsComponentWidgetState + extends State { + late UpArrowLinkedLocalsComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => UpArrowLinkedLocalsComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Container( + width: double.infinity, + height: 150.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 150.0, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: FutureBuilder( + future: PhpGroup.getLocalsCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } + final gridViewGetLocalsResponse = snapshot.data!; + return Builder( + builder: (context) { + final eachLocals = (PhpGroup.getLocalsCall + .locais( + gridViewGetLocalsResponse.jsonBody, + ) + ?.map((e) => e) + .toList() + .toList() ?? + []) + .take(2) + .toList(); + return GridView.builder( + padding: EdgeInsets.zero, + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + crossAxisSpacing: 10.0, + mainAxisSpacing: 0.0, + childAspectRatio: 1.0, + ), + scrollDirection: Axis.horizontal, + itemCount: eachLocals.length, + itemBuilder: (context, eachLocalsIndex) { + final eachLocalsItem = + eachLocals[eachLocalsIndex]; + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + FFAppState().cliUUID = getJsonField( + eachLocalsItem, + r'''$.CLI_ID''', + ).toString(); + setState(() {}); + FFAppState().local = getJsonField( + eachLocalsItem, + r'''$.CLI_NOME''', + ).toString(); + setState(() {}); + Navigator.pop(context); + }, + child: Container( + width: 50.0, + height: double.infinity, + decoration: const BoxDecoration(), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryText, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: + Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + border: Border.all( + color: + FlutterFlowTheme.of(context) + .secondaryText, + width: 3.0, + ), + ), + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: + Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + child: Image.network( + 'https://freaccess.com.br/freaccess/Images/Clients/${getJsonField( + eachLocalsItem, + r'''$.CLI_ID''', + ).toString()}.png', + width: double.infinity, + height: double.infinity, + fit: BoxFit.fill, + alignment: const Alignment(0.0, 0.0), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Text( + getJsonField( + eachLocalsItem, + r'''$.CLI_NOME''', + ).toString(), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ], + ), + ), + ); + }, + ); + }, + ); + }, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/organism_components/view_visit_detail/view_visit_detail_model.dart b/lib/application_components/organism_components/view_visit_detail/view_visit_detail_model.dart new file mode 100644 index 00000000..32e250ab --- /dev/null +++ b/lib/application_components/organism_components/view_visit_detail/view_visit_detail_model.dart @@ -0,0 +1,61 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'view_visit_detail_widget.dart' show ViewVisitDetailWidget; +import 'package:flutter/material.dart'; + +class ViewVisitDetailModel extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // Stores action output result for [Action Block - manageStatusColorAction] action in viewVisitDetail widget. + Color? visitStatusColor; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode4; + TextEditingController? textController4; + String? Function(BuildContext, String?)? textController4Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode5; + TextEditingController? textController5; + String? Function(BuildContext, String?)? textController5Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode6; + TextEditingController? textController6; + String? Function(BuildContext, String?)? textController6Validator; + // Stores action output result for [Backend Call - API (deleteVisit)] action in IconButton widget. + ApiCallResponse? deleteVisit; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + + textFieldFocusNode4?.dispose(); + textController4?.dispose(); + + textFieldFocusNode5?.dispose(); + textController5?.dispose(); + + textFieldFocusNode6?.dispose(); + textController6?.dispose(); + } +} diff --git a/lib/application_components/organism_components/view_visit_detail/view_visit_detail_widget.dart b/lib/application_components/organism_components/view_visit_detail/view_visit_detail_widget.dart new file mode 100644 index 00000000..a19cff25 --- /dev/null +++ b/lib/application_components/organism_components/view_visit_detail/view_visit_detail_widget.dart @@ -0,0 +1,928 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/actions/actions.dart' as action_blocks; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'view_visit_detail_model.dart'; +export 'view_visit_detail_model.dart'; + +class ViewVisitDetailWidget extends StatefulWidget { + const ViewVisitDetailWidget({ + super.key, + this.visitorImgPath, + required this.visitStartDate, + required this.visitEndDate, + required this.visitReasonStr, + required this.visitLevelStr, + required this.visitTempStr, + required this.visitObsStr, + required this.visitStatusStr, + required this.visitorStrList, + this.visitorJsonList, + required this.visitIdStr, + required this.updateToggleIdx, + this.repeatVisitScheduleActionBlock, + }); + + final String? visitorImgPath; + final String? visitStartDate; + final String? visitEndDate; + final String? visitReasonStr; + final String? visitLevelStr; + final String? visitTempStr; + final String? visitObsStr; + final String? visitStatusStr; + final String? visitorStrList; + final List? visitorJsonList; + final String? visitIdStr; + final Future Function()? updateToggleIdx; + final Future Function()? repeatVisitScheduleActionBlock; + + @override + State createState() => _ViewVisitDetailWidgetState(); +} + +class _ViewVisitDetailWidgetState extends State { + late ViewVisitDetailModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ViewVisitDetailModel()); + + // On component load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + _model.visitStatusColor = await action_blocks.manageStatusColorAction( + context, + visitStatusStr: widget.visitStatusStr, + ); + }); + + _model.textController1 ??= TextEditingController( + text: widget.visitTempStr == 'null' ? '' : widget.visitTempStr); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= + TextEditingController(text: widget.visitStartDate); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.textController3 ??= TextEditingController(text: widget.visitEndDate); + _model.textFieldFocusNode3 ??= FocusNode(); + + _model.textController4 ??= + TextEditingController(text: widget.visitReasonStr); + _model.textFieldFocusNode4 ??= FocusNode(); + + _model.textController5 ??= + TextEditingController(text: widget.visitLevelStr); + _model.textFieldFocusNode5 ??= FocusNode(); + + _model.textController6 ??= TextEditingController(text: widget.visitObsStr); + _model.textFieldFocusNode6 ??= FocusNode(); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 35.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Container( + width: double.infinity, + height: 35.0, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Align( + alignment: const AlignmentDirectional(1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(15.0, 0.0, 15.0, 0.0), + child: FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.close, + color: FlutterFlowTheme.of(context).accent1, + size: 24.0, + ), + onPressed: () async { + Navigator.pop(context); + }, + ), + ), + ), + ), + ), + Container( + decoration: const BoxDecoration( + shape: BoxShape.rectangle, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Align( + alignment: const AlignmentDirectional(1.0, -1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 20.0, 20.0), + child: Container( + width: 100.0, + decoration: const BoxDecoration(), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100.0), + ), + child: Align( + alignment: const AlignmentDirectional(1.0, -1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + useSafeArea: true, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const VisitorDetailsModalWidget(), + ); + }, + ).then((value) => safeSetState(() {})); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(100.0), + child: CachedNetworkImage( + fadeInDuration: const Duration(milliseconds: 500), + fadeOutDuration: const Duration(milliseconds: 500), + imageUrl: valueOrDefault( + widget.visitorImgPath, + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: 100.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ), + ), + ), + Container( + decoration: const BoxDecoration(), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(8.0, 0.0, 8.0, 10.0), + child: TextFormField( + controller: _model.textController1, + focusNode: _model.textFieldFocusNode1, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + '9yu35pzg' /* Encerramento da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController1Validator + .asValidator(context), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 10.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController2, + focusNode: _model.textFieldFocusNode2, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'aj6scczp' /* Início */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + 'ub084nhy' /* dd/mm/yyyy */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController2Validator + .asValidator(context), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController3, + focusNode: _model.textFieldFocusNode3, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'rvi5z7wg' /* Término */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + 'ixs67mrz' /* dd/mm/yyyy */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController3Validator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 10.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController4, + focusNode: _model.textFieldFocusNode4, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'yxilg7ek' /* Motivo da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + 'ypeydbem' /* Motivo */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController4Validator + .asValidator(context), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController5, + focusNode: _model.textFieldFocusNode5, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'dgr3pk3a' /* Nível de Acesso */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + 'rs3d4gb8' /* Nível de Acesso */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController5Validator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Container( + decoration: const BoxDecoration(), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController6, + focusNode: _model.textFieldFocusNode6, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'lppn9rxa' /* Observações da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController6Validator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 6.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: 35.0, + decoration: BoxDecoration( + color: valueOrDefault( + _model.visitStatusColor, + FlutterFlowTheme.of(context).primary, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: Builder( + builder: (context) { + if (widget.visitStatusStr == 'A') { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.block_sharp, + color: FlutterFlowTheme.of(context) + .primaryBackground, + size: 24.0, + ), + onPressed: () async { + _model.deleteVisit = + await PhpGroup.deleteVisitCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'cancelaVisita', + idVisita: widget.visitIdStr, + ); + if (PhpGroup.deleteVisitCall.error( + (_model.deleteVisit?.jsonBody ?? ''), + ) == + false) { + Navigator.pop(context); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: PhpGroup.deleteVisitCall.msg( + (_model.deleteVisit?.jsonBody ?? + ''), + )!, + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + ), + FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.share, + color: FlutterFlowTheme.of(context) + .primaryBackground, + size: 24.0, + ), + onPressed: () { + print('IconButton pressed ...'); + }, + ), + ], + ); + } else if ((widget.visitStatusStr == 'C') || + (widget.visitStatusStr == 'F') || + (widget.visitStatusStr == 'B') || + (widget.visitStatusStr == 'I')) { + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.updateToggleIdx?.call(); + Navigator.pop(context); + + context.pushNamed( + 'scheduleCompleteVisitPage', + queryParameters: { + 'visitStartDateStr': serializeParam( + dateTimeFormat( + 'd/M/y H:mm:ss', + getCurrentTimestamp, + locale: FFLocalizations.of(context) + .languageCode, + ), + ParamType.String, + ), + 'visitEndDateStr': serializeParam( + '', + ParamType.String, + ), + 'visitReasonStr': serializeParam( + widget.visitReasonStr, + ParamType.String, + ), + 'visitLevelStr': serializeParam( + widget.visitLevelStr, + ParamType.String, + ), + 'visitTempBol': serializeParam( + widget.visitTempStr == 'Sim' ? true : false, + ParamType.bool, + ), + 'visitObsStr': serializeParam( + widget.visitObsStr, + ParamType.String, + ), + 'visitorStrList': serializeParam( + widget.visitorStrList, + ParamType.String, + ), + 'visitorJsonList': serializeParam( + widget.visitorJsonList, + ParamType.JSON, + true, + ), + }.withoutNulls, + ); + }, + child: Icon( + Icons.repeat, + color: FlutterFlowTheme.of(context).secondaryText, + size: 24.0, + ), + ); + } else { + return Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + ); + } + }, + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_model.dart b/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_model.dart new file mode 100644 index 00000000..a63f3b06 --- /dev/null +++ b/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_model.dart @@ -0,0 +1,13 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'arrow_linked_locals_component_widget.dart' + show ArrowLinkedLocalsComponentWidget; +import 'package:flutter/material.dart'; + +class ArrowLinkedLocalsComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_widget.dart b/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_widget.dart new file mode 100644 index 00000000..0738f46c --- /dev/null +++ b/lib/application_components/templates_components/arrow_linked_locals_component/arrow_linked_locals_component_widget.dart @@ -0,0 +1,41 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'arrow_linked_locals_component_model.dart'; +export 'arrow_linked_locals_component_model.dart'; + +class ArrowLinkedLocalsComponentWidget extends StatefulWidget { + const ArrowLinkedLocalsComponentWidget({super.key}); + + @override + State createState() => + _ArrowLinkedLocalsComponentWidgetState(); +} + +class _ArrowLinkedLocalsComponentWidgetState + extends State { + late ArrowLinkedLocalsComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ArrowLinkedLocalsComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/lib/application_components/templates_components/menu_component/menu_component_model.dart b/lib/application_components/templates_components/menu_component/menu_component_model.dart new file mode 100644 index 00000000..b7be1afb --- /dev/null +++ b/lib/application_components/templates_components/menu_component/menu_component_model.dart @@ -0,0 +1,57 @@ +import '/application_components/molecular_components/option_selection_modal/option_selection_modal_widget.dart'; +import '/application_components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart'; +import '/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'menu_component_widget.dart' show MenuComponentWidget; +import 'package:flutter/material.dart'; + +class MenuComponentModel extends FlutterFlowModel { + /// Local state fields for this component. + + bool isGrid = false; + + /// State fields for stateful widgets in this component. + + // Model for menuListViewComponent. + late MenuListViewComponentModel menuListViewComponentModel; + // Model for menuStaggeredViewComponent. + late MenuStaggeredViewComponentModel menuStaggeredViewComponentModel; + + @override + void initState(BuildContext context) { + menuListViewComponentModel = + createModel(context, () => MenuListViewComponentModel()); + menuStaggeredViewComponentModel = + createModel(context, () => MenuStaggeredViewComponentModel()); + } + + @override + void dispose() { + menuListViewComponentModel.dispose(); + menuStaggeredViewComponentModel.dispose(); + } + + /// Action blocks. + Future changeMenuStyle(BuildContext context) async { + isGrid = !isGrid; + } + + Future scheduleVisitOptAction(BuildContext context) async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const OptionSelectionModalWidget(), + ); + }, + ); + } + + Future registerVisitorOptAction(BuildContext context) async { + context.pushNamed('registerVisitorPage'); + } +} diff --git a/lib/application_components/templates_components/menu_component/menu_component_widget.dart b/lib/application_components/templates_components/menu_component/menu_component_widget.dart new file mode 100644 index 00000000..b03e32ff --- /dev/null +++ b/lib/application_components/templates_components/menu_component/menu_component_widget.dart @@ -0,0 +1,88 @@ +import '/application_components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart'; +import '/application_components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'menu_component_model.dart'; +export 'menu_component_model.dart'; + +class MenuComponentWidget extends StatefulWidget { + const MenuComponentWidget({super.key}); + + @override + State createState() => _MenuComponentWidgetState(); +} + +class _MenuComponentWidgetState extends State { + late MenuComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => MenuComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Builder( + builder: (context) { + if (_model.isGrid == true) { + return wrapWithModel( + model: _model.menuListViewComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: MenuListViewComponentWidget( + changeMenuStyle: () async { + await _model.changeMenuStyle(context); + setState(() {}); + }, + registerVisitorAction: () async { + await _model.registerVisitorOptAction(context); + setState(() {}); + }, + scheduleVisitAction: () async { + await _model.scheduleVisitOptAction(context); + setState(() {}); + }, + ), + ); + } else { + return wrapWithModel( + model: _model.menuStaggeredViewComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: MenuStaggeredViewComponentWidget( + changeMenuStyleAction: () async { + await _model.changeMenuStyle(context); + setState(() {}); + }, + registerVisitorOptAction: () async { + await _model.registerVisitorOptAction(context); + setState(() {}); + }, + scheduleVisitOptAction: () async { + await _model.scheduleVisitOptAction(context); + setState(() {}); + }, + ), + ); + } + }, + ), + ); + } +} diff --git a/lib/application_components/templates_components/message_well_component/message_well_component_model.dart b/lib/application_components/templates_components/message_well_component/message_well_component_model.dart new file mode 100644 index 00000000..3da2a723 --- /dev/null +++ b/lib/application_components/templates_components/message_well_component/message_well_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'message_well_component_widget.dart' show MessageWellComponentWidget; +import 'package:flutter/material.dart'; + +class MessageWellComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/templates_components/message_well_component/message_well_component_widget.dart b/lib/application_components/templates_components/message_well_component/message_well_component_widget.dart new file mode 100644 index 00000000..3109dce7 --- /dev/null +++ b/lib/application_components/templates_components/message_well_component/message_well_component_widget.dart @@ -0,0 +1,125 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'message_well_component_model.dart'; +export 'message_well_component_model.dart'; + +class MessageWellComponentWidget extends StatefulWidget { + const MessageWellComponentWidget({super.key}); + + @override + State createState() => + _MessageWellComponentWidgetState(); +} + +class _MessageWellComponentWidgetState + extends State { + late MessageWellComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => MessageWellComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 40.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: 167.0, + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + FFLocalizations.of(context).getText( + '8fworxmb' /* Mural de Mensagens */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Nunito Sans', + letterSpacing: 0.0, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Nunito Sans'), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 5.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () { + print('Button pressed ...'); + }, + text: FFLocalizations.of(context).getText( + 'yikill36' /* Todos */, + ), + options: FFButtonOptions( + width: 260.0, + height: 20.0, + padding: + const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: const Color(0xFF1AAB5F), + textStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).secondaryText, + letterSpacing: 0.0, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Container( + width: 464.0, + height: 127.0, + decoration: const BoxDecoration( + shape: BoxShape.rectangle, + ), + child: ListView( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + children: const [], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_model.dart b/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_model.dart new file mode 100644 index 00000000..3cf3c27f --- /dev/null +++ b/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_model.dart @@ -0,0 +1,57 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'regisiter_vistor_component_widget.dart' + show RegisiterVistorComponentWidget; +import 'package:flutter/material.dart'; + +class RegisiterVistorComponentModel + extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + bool isDataUploading = false; + FFUploadedFile uploadedLocalFile = + FFUploadedFile(bytes: Uint8List.fromList([])); + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + // State field(s) for DropDown widget. + String? dropDownValue; + FormFieldController? dropDownValueController; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode4; + TextEditingController? textController4; + String? Function(BuildContext, String?)? textController4Validator; + // Stores action output result for [Custom Action - convertImageFileToBase64] action in Button widget. + String? imgBase64; + // Stores action output result for [Backend Call - API (postScheduleVisitor)] action in Button widget. + ApiCallResponse? registerVisitor; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + + textFieldFocusNode4?.dispose(); + textController4?.dispose(); + } +} diff --git a/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_widget.dart b/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_widget.dart new file mode 100644 index 00000000..d8d2d7ea --- /dev/null +++ b/lib/application_components/templates_components/regisiter_vistor_component/regisiter_vistor_component_widget.dart @@ -0,0 +1,819 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_drop_down.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/flutter_flow/form_field_controller.dart'; +import '/flutter_flow/upload_data.dart'; +import '/custom_code/actions/index.dart' as actions; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'regisiter_vistor_component_model.dart'; +export 'regisiter_vistor_component_model.dart'; + +class RegisiterVistorComponentWidget extends StatefulWidget { + const RegisiterVistorComponentWidget({super.key}); + + @override + State createState() => + _RegisiterVistorComponentWidgetState(); +} + +class _RegisiterVistorComponentWidgetState + extends State { + late RegisiterVistorComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => RegisiterVistorComponentModel()); + + _model.textController1 ??= TextEditingController(); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= TextEditingController(); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.textController3 ??= TextEditingController(); + _model.textFieldFocusNode3 ??= FocusNode(); + + _model.textController4 ??= TextEditingController(); + _model.textFieldFocusNode4 ??= FocusNode(); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 30.0, 0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, -1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(20.0, 0.0, 0.0, 20.0), + child: Text( + FFLocalizations.of(context).getText( + 'wnhkedzt' /* Cadastrar Visitante */, + ), + style: FlutterFlowTheme.of(context).bodyLarge.override( + fontFamily: 'Nunito', + fontSize: 21.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w800, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + ), + ), + Builder( + builder: (context) { + if ((_model.uploadedLocalFile.bytes?.isNotEmpty ?? false)) { + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + setState(() { + _model.isDataUploading = false; + _model.uploadedLocalFile = + FFUploadedFile(bytes: Uint8List.fromList([])); + }); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.memory( + _model.uploadedLocalFile.bytes ?? + Uint8List.fromList([]), + width: 300.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + ); + } else { + return Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.01, 0.0), + child: FFButtonWidget( + onPressed: () async { + final selectedMedia = + await selectMediaWithSourceBottomSheet( + context: context, + maxWidth: 300.00, + maxHeight: 300.00, + imageQuality: 0, + allowPhoto: true, + includeDimensions: true, + ); + if (selectedMedia != null && + selectedMedia.every((m) => + validateFileFormat( + m.storagePath, context))) { + setState(() => _model.isDataUploading = true); + var selectedUploadedFiles = + []; + + try { + showUploadMessage( + context, + 'Uploading file...', + showLoading: true, + ); + selectedUploadedFiles = selectedMedia + .map((m) => FFUploadedFile( + name: + m.storagePath.split('/').last, + bytes: m.bytes, + height: m.dimensions?.height, + width: m.dimensions?.width, + blurHash: m.blurHash, + )) + .toList(); + } finally { + ScaffoldMessenger.of(context) + .hideCurrentSnackBar(); + _model.isDataUploading = false; + } + if (selectedUploadedFiles.length == + selectedMedia.length) { + setState(() { + _model.uploadedLocalFile = + selectedUploadedFiles.first; + }); + showUploadMessage(context, 'Success!'); + } else { + setState(() {}); + showUploadMessage( + context, 'Failed to upload data'); + return; + } + } + }, + text: '', + icon: Icon( + Icons.photo_camera, + color: FlutterFlowTheme.of(context).accent1, + size: 30.0, + ), + options: FFButtonOptions( + width: 300.0, + height: 80.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: const EdgeInsetsDirectional.fromSTEB( + 14.0, 0.0, 0.0, 20.0), + color: FlutterFlowTheme.of(context) + .primaryBackground, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 50.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'kpd31z4d' /* Clique para adicionar a foto p... */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ); + } + }, + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'q986vs4m' /* Preencha o formulário com os d... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController1, + focusNode: _model.textFieldFocusNode1, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'llcw2tei' /* Nome */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.person, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + maxLines: null, + keyboardType: TextInputType.name, + validator: + _model.textController1Validator.asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Container( + decoration: const BoxDecoration(), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 10.0, 20.0, 10.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '67ykbznt' /* Selecione o tipo: */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 5.0), + child: FlutterFlowDropDown( + controller: _model.dropDownValueController ??= + FormFieldController(null), + options: [ + FFLocalizations.of(context).getText( + 'ugjkeiz7' /* Visitante */, + ), + FFLocalizations.of(context).getText( + '8nlk5xlk' /* Prestador de Serviço */, + ) + ], + onChanged: (val) => + setState(() => _model.dropDownValue = val), + width: 200.0, + height: 48.0, + textStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + 'kw07i43y' /* Selecione... */, + ), + icon: Icon( + Icons.keyboard_arrow_down_rounded, + color: FlutterFlowTheme.of(context).primaryText, + size: 24.0, + ), + elevation: 2.0, + borderColor: FlutterFlowTheme.of(context).accent1, + borderWidth: 0.5, + borderRadius: 8.0, + margin: const EdgeInsetsDirectional.fromSTEB( + 16.0, 4.0, 16.0, 4.0), + hidesUnderline: true, + isOverButton: true, + isSearchable: false, + isMultiSelect: false, + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController2, + focusNode: _model.textFieldFocusNode2, + autofocus: false, + textCapitalization: TextCapitalization.none, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + '96ayre48' /* Documento */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.document_scanner, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + validator: + _model.textController2Validator.asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'j0g7ggs2' /* Contatos */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController3, + focusNode: _model.textFieldFocusNode3, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'ybdjabnd' /* Telefone */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.phone, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + validator: + _model.textController3Validator.asValidator(context), + ), + ), + Padding( + padding: const EdgeInsets.all(24.0), + child: TextFormField( + controller: _model.textController4, + focusNode: _model.textFieldFocusNode4, + autofocus: false, + textInputAction: TextInputAction.done, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'tlr6uxo4' /* Email */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.email, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + keyboardType: TextInputType.emailAddress, + validator: + _model.textController4Validator.asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + if (((_model.uploadedLocalFile.bytes?.isNotEmpty ?? + false)) && + (_model.textController1.text != '') && + (_model.dropDownValue != null && + _model.dropDownValue != '') && + (_model.textController2.text != '')) { + _model.imgBase64 = + await actions.convertImageFileToBase64( + _model.uploadedLocalFile, + ); + _model.registerVisitor = + await PhpGroup.postScheduleVisitorCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'putVisitante', + documento: _model.textController2.text, + nome: _model.textController1.text, + tipo: (_model.dropDownValue == 'Visitante') || + (_model.dropDownValue == 'Visitor') + ? 'V' + : 'P', + foto: 'base64;jpeg,klajsalkjslkajslkajl', + ); + if (PhpGroup.postScheduleVisitorCall.error( + (_model.registerVisitor?.jsonBody ?? ''), + ) == + false) { + setState(() { + _model.textController1?.clear(); + _model.textController2?.clear(); + _model.textController3?.clear(); + _model.textController4?.clear(); + }); + setState(() { + _model.dropDownValueController?.reset(); + }); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: + '\\devUUID=${FFAppState().devUUID}\\userUUID=${FFAppState().userUUID}\\cliID=${FFAppState().cliUUID}\\Documento=${_model.textController2.text}\\Nome=${_model.textController1.text}\\dropdown${_model.dropDownValue}\\${PhpGroup.postScheduleVisitorCall.errorMsg( + (_model.registerVisitor?.jsonBody ?? ''), + )}', + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: + 'Você esqueceu de adicionar algum dado obrigatório. Verifique se a imagem, nome, tipo e documento estão foram preenchidos corretamente.- devUUID=${FFAppState().devUUID}- userUUID=${FFAppState().userUUID}- cliID=${FFAppState().cliUUID}- Documento=${_model.textController2.text}- Nome=${_model.textController1.text}- Tipo=${_model.dropDownValue}', + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + text: FFLocalizations.of(context).getText( + '65puvap9' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 36.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 80.0, 0.0, 80.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context).titleSmallFamily, + color: FlutterFlowTheme.of(context).info, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: const BorderSide( + color: Colors.transparent, + width: 30.0, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/application_components/templates_components/visit_details_modal/visit_details_modal_model.dart b/lib/application_components/templates_components/visit_details_modal/visit_details_modal_model.dart new file mode 100644 index 00000000..af6db9a6 --- /dev/null +++ b/lib/application_components/templates_components/visit_details_modal/visit_details_modal_model.dart @@ -0,0 +1,31 @@ +import '/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart'; +import '/application_components/organism_components/view_visit_detail/view_visit_detail_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'visit_details_modal_widget.dart' show VisitDetailsModalWidget; +import 'package:flutter/material.dart'; + +class VisitDetailsModalModel extends FlutterFlowModel { + /// Local state fields for this component. + + Color statusColor = const Color(0xff000000); + + /// State fields for stateful widgets in this component. + + // Model for viewVisitDetail component. + late ViewVisitDetailModel viewVisitDetailModel; + // Model for scheduleVisitDetail component. + late ScheduleVisitDetailModel scheduleVisitDetailModel; + + @override + void initState(BuildContext context) { + viewVisitDetailModel = createModel(context, () => ViewVisitDetailModel()); + scheduleVisitDetailModel = + createModel(context, () => ScheduleVisitDetailModel()); + } + + @override + void dispose() { + viewVisitDetailModel.dispose(); + scheduleVisitDetailModel.dispose(); + } +} diff --git a/lib/application_components/templates_components/visit_details_modal/visit_details_modal_widget.dart b/lib/application_components/templates_components/visit_details_modal/visit_details_modal_widget.dart new file mode 100644 index 00000000..1e2dca21 --- /dev/null +++ b/lib/application_components/templates_components/visit_details_modal/visit_details_modal_widget.dart @@ -0,0 +1,122 @@ +import '/application_components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart'; +import '/application_components/organism_components/view_visit_detail/view_visit_detail_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'visit_details_modal_model.dart'; +export 'visit_details_modal_model.dart'; + +class VisitDetailsModalWidget extends StatefulWidget { + const VisitDetailsModalWidget({ + super.key, + this.visitStatusStr, + this.visitStartDateStr, + this.visitEndDateStr, + this.visitReasonStr, + this.visitLevelStr, + this.visitTempStr, + this.visitObsStr, + this.visitorStrList, + this.visitorJsonList, + this.visitorImgPath, + this.visitorImgList, + this.visitIdStr, + this.updateToggleIdx, + this.repeatVisitSchedule, + }); + + final String? visitStatusStr; + final String? visitStartDateStr; + final String? visitEndDateStr; + final String? visitReasonStr; + final String? visitLevelStr; + final String? visitTempStr; + final String? visitObsStr; + final String? visitorStrList; + final List? visitorJsonList; + final String? visitorImgPath; + final List? visitorImgList; + final String? visitIdStr; + final Future Function()? updateToggleIdx; + final Future Function()? repeatVisitSchedule; + + @override + State createState() => + _VisitDetailsModalWidgetState(); +} + +class _VisitDetailsModalWidgetState extends State { + late VisitDetailsModalModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => VisitDetailsModalModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Builder( + builder: (context) { + if (widget.visitStatusStr != null && widget.visitStatusStr != '') { + return wrapWithModel( + model: _model.viewVisitDetailModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: ViewVisitDetailWidget( + visitorImgPath: widget.visitorImgPath, + visitStartDate: widget.visitStartDateStr!, + visitEndDate: widget.visitEndDateStr!, + visitReasonStr: widget.visitReasonStr!, + visitLevelStr: widget.visitLevelStr!, + visitTempStr: widget.visitTempStr!, + visitObsStr: widget.visitObsStr!, + visitStatusStr: widget.visitStatusStr!, + visitorStrList: widget.visitorStrList!, + visitorJsonList: widget.visitorJsonList, + visitIdStr: widget.visitIdStr!, + updateToggleIdx: () async { + await widget.updateToggleIdx?.call(); + }, + repeatVisitScheduleActionBlock: () async { + await widget.repeatVisitSchedule?.call(); + }, + ), + ); + } else { + return wrapWithModel( + model: _model.scheduleVisitDetailModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: ScheduleVisitDetailWidget( + visitorStrList: widget.visitorStrList!, + visitorImgPath: widget.visitorImgPath, + visitStartDate: widget.visitStartDateStr!, + visitEndDate: widget.visitEndDateStr!, + visitResonStr: widget.visitReasonStr!, + visitLevelStr: widget.visitLevelStr!, + visitTempStr: widget.visitTempStr!, + visitObsStr: widget.visitObsStr!, + visitorJsonList: widget.visitorJsonList!, + ), + ); + } + }, + ), + ); + } +} diff --git a/lib/application_components/templates_components/visit_history_component/visit_history_component_model.dart b/lib/application_components/templates_components/visit_history_component/visit_history_component_model.dart new file mode 100644 index 00000000..03f37209 --- /dev/null +++ b/lib/application_components/templates_components/visit_history_component/visit_history_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'visit_history_component_widget.dart' show VisitHistoryComponentWidget; +import 'package:flutter/material.dart'; + +class VisitHistoryComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/templates_components/visit_history_component/visit_history_component_widget.dart b/lib/application_components/templates_components/visit_history_component/visit_history_component_widget.dart new file mode 100644 index 00000000..b33ddd82 --- /dev/null +++ b/lib/application_components/templates_components/visit_history_component/visit_history_component_widget.dart @@ -0,0 +1,388 @@ +import '/application_components/molecular_components/opt_modal/opt_modal_widget.dart'; +import '/application_components/templates_components/visit_details_modal/visit_details_modal_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/custom_functions.dart' as functions; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'visit_history_component_model.dart'; +export 'visit_history_component_model.dart'; + +class VisitHistoryComponentWidget extends StatefulWidget { + const VisitHistoryComponentWidget({ + super.key, + this.parameter1, + }); + + final FFUploadedFile? parameter1; + + @override + State createState() => + _VisitHistoryComponentWidgetState(); +} + +class _VisitHistoryComponentWidgetState + extends State { + late VisitHistoryComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => VisitHistoryComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Container( + width: double.infinity, + height: 900.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.settings_sharp, + color: FlutterFlowTheme.of(context).primary, + size: 24.0, + ), + onPressed: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const OptModalWidget(), + ); + }, + ).then((value) => safeSetState(() {})); + }, + ), + ], + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(14.0), + child: FutureBuilder( + future: PhpGroup.getVisitsCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'getVisitas', + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } + final gridViewGetVisitsResponse = snapshot.data!; + return Builder( + builder: (context) { + final visitHistory = (PhpGroup.getVisitsCall + .visitasList( + gridViewGetVisitsResponse.jsonBody, + ) + ?.toList() ?? + []) + .take(10) + .toList(); + return GridView.builder( + padding: EdgeInsets.zero, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + childAspectRatio: 1.0, + ), + scrollDirection: Axis.vertical, + itemCount: visitHistory.length, + itemBuilder: (context, visitHistoryIndex) { + final visitHistoryItem = + visitHistory[visitHistoryIndex]; + return Container( + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(50.0), + bottomRight: Radius.circular(50.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + shape: BoxShape.rectangle, + ), + child: Stack( + children: [ + Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: valueOrDefault( + () { + if (functions.jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"A\"') { + return FlutterFlowTheme.of(context) + .success; + } else if (functions + .jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"C\"') { + return FlutterFlowTheme.of(context) + .error; + } else if (functions + .jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"I\"') { + return FlutterFlowTheme.of(context) + .warning; + } else { + return FlutterFlowTheme.of(context) + .primary; + } + }(), + FlutterFlowTheme.of(context).primary, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(10.0), + bottomRight: Radius.circular(10.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + shape: BoxShape.rectangle, + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + useSafeArea: true, + context: context, + builder: (context) { + return Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: VisitDetailsModalWidget( + visitStatusStr: getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS ''', + ).toString(), + visitStartDateStr: getJsonField( + visitHistoryItem, + r'''$.VAW_DTINICIO''', + ).toString(), + visitEndDateStr: getJsonField( + visitHistoryItem, + r'''$.VAW_DTFIM''', + ).toString(), + visitReasonStr: getJsonField( + visitHistoryItem, + r'''$.MOT_DESCRICAO''', + ).toString(), + visitLevelStr: getJsonField( + visitHistoryItem, + r'''$.NAC_DESCRICAO''', + ).toString(), + visitTempStr: getJsonField( + visitHistoryItem, + r'''$.VTE_UNICA ''', + ).toString(), + visitObsStr: getJsonField( + visitHistoryItem, + r'''$.VAW_OBS''', + ).toString(), + visitorImgPath: + valueOrDefault( + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + visitHistoryItem, + r'''$.VTE_DOCUMENTO''', + ).toString()}&tipo=E', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + visitorStrList: getJsonField( + visitHistoryItem, + r'''$.VTE_DOCUMENTO''', + ).toString(), + visitIdStr: getJsonField( + visitHistoryItem, + r'''$.VAW_ID''', + ).toString(), + visitorJsonList: PhpGroup + .getVisitsCall + .visitasList( + gridViewGetVisitsResponse + .jsonBody, + ), + updateToggleIdx: () async { + setState(() {}); + }, + repeatVisitSchedule: () async {}, + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(25.0), + bottomRight: Radius.circular(25.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + child: CachedNetworkImage( + fadeInDuration: + const Duration(milliseconds: 500), + fadeOutDuration: + const Duration(milliseconds: 500), + imageUrl: valueOrDefault( + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + visitHistoryItem, + r'''$.VTE_DOCUMENTO''', + ).toString()}&tipo=E', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: double.infinity, + height: double.infinity, + fit: BoxFit.cover, + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Container( + width: 200.0, + height: 20.0, + decoration: BoxDecoration( + color: valueOrDefault( + () { + if (functions.jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"A\"') { + return FlutterFlowTheme.of(context) + .success; + } else if (functions + .jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"C\"') { + return FlutterFlowTheme.of(context) + .error; + } else if (functions + .jsonToStr(getJsonField( + visitHistoryItem, + r'''$.VAW_STATUS''', + )) == + '\"I\"') { + return FlutterFlowTheme.of(context) + .warning; + } else { + return FlutterFlowTheme.of(context) + .primary; + } + }(), + FlutterFlowTheme.of(context).primary, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + getJsonField( + visitHistoryItem, + r'''$.VTE_NOME''', + ).toString(), + textAlign: TextAlign.center, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .info, + fontSize: 12.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ), + ); + }, + ); + }, + ); + }, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_model.dart b/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_model.dart new file mode 100644 index 00000000..06aee0b3 --- /dev/null +++ b/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'visitor_details_modal_widget.dart' show VisitorDetailsModalWidget; +import 'package:flutter/material.dart'; + +class VisitorDetailsModalModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart b/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart new file mode 100644 index 00000000..bb280e11 --- /dev/null +++ b/lib/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart @@ -0,0 +1,280 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'visitor_details_modal_model.dart'; +export 'visitor_details_modal_model.dart'; + +class VisitorDetailsModalWidget extends StatefulWidget { + const VisitorDetailsModalWidget({super.key}); + + @override + State createState() => + _VisitorDetailsModalWidgetState(); +} + +class _VisitorDetailsModalWidgetState extends State { + late VisitorDetailsModalModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => VisitorDetailsModalModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 35.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: BorderRadius.circular(25.0), + ), + child: Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + width: double.infinity, + height: 34.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryText, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(20.0, 40.0, 20.0, 0.0), + child: Container( + decoration: const BoxDecoration( + shape: BoxShape.rectangle, + ), + child: Stack( + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: 100.0, + height: 100.0, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Image.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + fit: BoxFit.cover, + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 20.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'kqzf7nx2' /* Nome do Visitante */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 20.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'hz7ivuqn' /* Tipo de Visitante */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + Icons.phone, + color: FlutterFlowTheme.of(context).primary, + size: 24.0, + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 20.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'rwqn0det' /* (00) 0 0000-0000 */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + Icons.email, + color: FlutterFlowTheme.of(context).primary, + size: 24.0, + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 20.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '0wqbiekp' /* email@provider.etc */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(-1.0, -1.0), + child: Container( + width: double.infinity, + height: 34.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryText, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + shape: BoxShape.rectangle, + ), + child: Align( + alignment: const AlignmentDirectional(1.0, -1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(10.0, 5.0, 15.0, 0.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + Navigator.pop(context); + }, + child: Icon( + Icons.close, + color: FlutterFlowTheme.of(context).primaryBackground, + size: 24.0, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/application_components/templates_components/visitor_search_component/visitor_search_component_model.dart b/lib/application_components/templates_components/visitor_search_component/visitor_search_component_model.dart new file mode 100644 index 00000000..19e2c235 --- /dev/null +++ b/lib/application_components/templates_components/visitor_search_component/visitor_search_component_model.dart @@ -0,0 +1,44 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'visitor_search_component_widget.dart' show VisitorSearchComponentWidget; +import 'package:flutter/material.dart'; + +class VisitorSearchComponentModel + extends FlutterFlowModel { + /// Local state fields for this component. + + List visitors = []; + void addToVisitors(dynamic item) => visitors.add(item); + void removeFromVisitors(dynamic item) => visitors.remove(item); + void removeAtIndexFromVisitors(int index) => visitors.removeAt(index); + void insertAtIndexInVisitors(int index, dynamic item) => + visitors.insert(index, item); + void updateVisitorsAtIndex(int index, Function(dynamic) updateFn) => + visitors[index] = updateFn(visitors[index]); + + List docs = []; + void addToDocs(String item) => docs.add(item); + void removeFromDocs(String item) => docs.remove(item); + void removeAtIndexFromDocs(int index) => docs.removeAt(index); + void insertAtIndexInDocs(int index, String item) => docs.insert(index, item); + void updateDocsAtIndex(int index, Function(String) updateFn) => + docs[index] = updateFn(docs[index]); + + /// State fields for stateful widgets in this component. + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode; + TextEditingController? textController; + String? Function(BuildContext, String?)? textControllerValidator; + // Stores action output result for [Backend Call - API (getVisitorByDoc)] action in TextField widget. + ApiCallResponse? getVisitorByDoc; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode?.dispose(); + textController?.dispose(); + } +} diff --git a/lib/application_components/templates_components/visitor_search_component/visitor_search_component_widget.dart b/lib/application_components/templates_components/visitor_search_component/visitor_search_component_widget.dart new file mode 100644 index 00000000..42495373 --- /dev/null +++ b/lib/application_components/templates_components/visitor_search_component/visitor_search_component_widget.dart @@ -0,0 +1,527 @@ +import '/application_components/molecular_components/visitor_not_found_component/visitor_not_found_component_widget.dart'; +import '/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'visitor_search_component_model.dart'; +export 'visitor_search_component_model.dart'; + +class VisitorSearchComponentWidget extends StatefulWidget { + const VisitorSearchComponentWidget({ + super.key, + this.getVisitors, + this.getDocs, + }); + + final Future Function(List? visitorsParam)? getVisitors; + final Future Function(List? docsParam)? getDocs; + + @override + State createState() => + _VisitorSearchComponentWidgetState(); +} + +class _VisitorSearchComponentWidgetState + extends State with TickerProviderStateMixin { + late VisitorSearchComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => VisitorSearchComponentModel()); + + _model.textController ??= TextEditingController(); + _model.textFieldFocusNode ??= FocusNode(); + + WidgetsBinding.instance.addPostFrameCallback((_) => setState(() { + _model.textController?.text = FFLocalizations.of(context).getText( + 'oj12tamm' /* test */, + ); + })); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 300.0, 0.0, 0.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 10.0, 16.0, 0.0), + child: TextFormField( + controller: _model.textController, + focusNode: _model.textFieldFocusNode, + onFieldSubmitted: (_) async { + setState(() { + _model.textController?.text = valueOrDefault( + _model.textController.text, + '69696777', + ); + }); + _model.getVisitorByDoc = + await PhpGroup.getVisitorByDocCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'getVisitante', + documento: _model.textController.text, + ); + if (PhpGroup.getVisitorByDocCall.vistanteId( + (_model.getVisitorByDoc?.jsonBody ?? ''), + ) != + '0') { + _model + .addToVisitors(PhpGroup.getVisitorByDocCall.visitante( + (_model.getVisitorByDoc?.jsonBody ?? ''), + )); + setState(() {}); + _model.addToDocs(_model.textController.text); + setState(() {}); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const VisitorNotFoundComponentWidget(), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + autofocus: false, + textInputAction: TextInputAction.done, + obscureText: false, + decoration: InputDecoration( + isDense: false, + labelText: FFLocalizations.of(context).getText( + 'cjlpru1m' /* Procure pelo documento do visi... */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintText: FFLocalizations.of(context).getText( + '8i1qszba' /* test */, + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15.0), + bottomRight: Radius.circular(15.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15.0), + bottomRight: Radius.circular(15.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15.0), + bottomRight: Radius.circular(15.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15.0), + bottomRight: Radius.circular(15.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context).primaryBackground, + prefixIcon: Icon( + Icons.search_outlined, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + keyboardType: TextInputType.number, + validator: + _model.textControllerValidator.asValidator(context), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '9coywebh' /* Visitantes encontrados */, + ), + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: + FlutterFlowTheme.of(context).labelMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(4.0, 12.0, 16.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '6f5p0fv6' /* 24 */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ], + ), + Expanded( + child: Builder( + builder: (context) { + if (_model.visitors.isNotEmpty) { + return Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(8.0, 8.0, 8.0, 0.0), + child: Builder( + builder: (context) { + final visitor = + _model.visitors.map((e) => e).toList(); + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + itemCount: visitor.length, + itemBuilder: (context, visitorIndex) { + final visitorItem = visitor[visitorIndex]; + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await showModalBottomSheet( + isScrollControlled: true, + enableDrag: false, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf( + context), + child: const SizedBox( + height: 610.0, + child: + VisitorDetailsModalWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + child: Container( + width: 100.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + boxShadow: [ + BoxShadow( + blurRadius: 0.0, + color: FlutterFlowTheme.of(context) + .alternate, + offset: const Offset( + 0.0, + 1.0, + ), + ) + ], + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + ClipRRect( + borderRadius: + BorderRadius.circular(40.0), + child: CachedNetworkImage( + fadeInDuration: + const Duration(milliseconds: 500), + fadeOutDuration: + const Duration(milliseconds: 500), + imageUrl: + valueOrDefault( + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + visitorItem, + r'''$.VTE_DOCUMENTO''', + ).toString()}&tipo=E', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: 60.0, + height: 60.0, + fit: BoxFit.cover, + ), + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(12.0, 0.0, + 0.0, 0.0), + child: Text( + valueOrDefault( + getJsonField( + visitorItem, + r'''$.VTE_NOME''', + )?.toString(), + 'NOT FOUND', + ), + style: + FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyLargeFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyLargeFamily), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(4.0, 4.0, + 0.0, 0.0), + child: Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Align( + alignment: + const AlignmentDirectional( + 0.0, -1.0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 0.0, + 0.0), + child: Text( + getJsonField( + visitorItem, + r'''$.VTE_TELEFONE''', + ).toString(), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .primary, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.restore_from_trash, + color: + FlutterFlowTheme.of(context) + .primary, + size: 20.0, + ), + onPressed: () async { + _model.removeFromVisitors( + visitorItem); + setState(() {}); + }, + ), + ], + ), + ), + ), + ), + ); + }, + ); + }, + ), + ); + } else { + return Container( + width: 100.0, + height: 100.0, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).secondaryBackground, + ), + ); + } + }, + ), + ), + FFButtonWidget( + onPressed: () async { + await widget.getVisitors?.call( + _model.visitors, + ); + await widget.getDocs?.call( + _model.docs, + ); + Navigator.pop(context); + }, + text: FFLocalizations.of(context).getText( + 'ug6qzyla' /* Adicionar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 30.0, + padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: + FlutterFlowTheme.of(context).titleSmallFamily, + color: Colors.white, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).titleSmallFamily), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/application_pages/fast_pass_page/fast_pass_page_model.dart b/lib/application_pages/fast_pass_page/fast_pass_page_model.dart new file mode 100644 index 00000000..2b4d9d53 --- /dev/null +++ b/lib/application_pages/fast_pass_page/fast_pass_page_model.dart @@ -0,0 +1,17 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'fast_pass_page_widget.dart' show FastPassPageWidget; +import 'package:flutter/material.dart'; + +class FastPassPageModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + unfocusNode.dispose(); + } +} diff --git a/lib/application_pages/fast_pass_page/fast_pass_page_widget.dart b/lib/application_pages/fast_pass_page/fast_pass_page_widget.dart new file mode 100644 index 00000000..5edf4ae4 --- /dev/null +++ b/lib/application_pages/fast_pass_page/fast_pass_page_widget.dart @@ -0,0 +1,44 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'fast_pass_page_model.dart'; +export 'fast_pass_page_model.dart'; + +class FastPassPageWidget extends StatefulWidget { + const FastPassPageWidget({super.key}); + + @override + State createState() => _FastPassPageWidgetState(); +} + +class _FastPassPageWidgetState extends State { + late FastPassPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => FastPassPageModel()); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + ), + ); + } +} diff --git a/lib/application_pages/home_page/home_page_model.dart b/lib/application_pages/home_page/home_page_model.dart new file mode 100644 index 00000000..ca2e9e8b --- /dev/null +++ b/lib/application_pages/home_page/home_page_model.dart @@ -0,0 +1,46 @@ +import '/application_components/organism_components/local_profile_component/local_profile_component_widget.dart'; +import '/application_components/templates_components/menu_component/menu_component_widget.dart'; +import '/application_components/templates_components/message_well_component/message_well_component_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'home_page_widget.dart' show HomePageWidget; +import 'package:flutter/material.dart'; + +class HomePageModel extends FlutterFlowModel { + /// Local state fields for this page. + + bool isGrid = false; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode; + TextEditingController? textController; + String? Function(BuildContext, String?)? textControllerValidator; + // Model for localComponent. + late LocalProfileComponentModel localComponentModel; + // Model for menuComponent component. + late MenuComponentModel menuComponentModel; + // Model for messageWellComponent component. + late MessageWellComponentModel messageWellComponentModel; + + @override + void initState(BuildContext context) { + localComponentModel = + createModel(context, () => LocalProfileComponentModel()); + menuComponentModel = createModel(context, () => MenuComponentModel()); + messageWellComponentModel = + createModel(context, () => MessageWellComponentModel()); + } + + @override + void dispose() { + unfocusNode.dispose(); + textFieldFocusNode?.dispose(); + textController?.dispose(); + + localComponentModel.dispose(); + menuComponentModel.dispose(); + messageWellComponentModel.dispose(); + } +} diff --git a/lib/application_pages/home_page/home_page_widget.dart b/lib/application_pages/home_page/home_page_widget.dart new file mode 100644 index 00000000..cfe4a776 --- /dev/null +++ b/lib/application_pages/home_page/home_page_widget.dart @@ -0,0 +1,1080 @@ +import '/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; +import '/application_components/organism_components/local_profile_component/local_profile_component_widget.dart'; +import '/application_components/templates_components/menu_component/menu_component_widget.dart'; +import '/application_components/templates_components/message_well_component/message_well_component_widget.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'home_page_model.dart'; +export 'home_page_model.dart'; + +class HomePageWidget extends StatefulWidget { + const HomePageWidget({super.key}); + + @override + State createState() => _HomePageWidgetState(); +} + +class _HomePageWidgetState extends State { + late HomePageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => HomePageModel()); + + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + if (FFAppState().cliUUID == '') { + showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const BottomArrowLinkedLocalsComponentWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } else { + return; + } + }); + + _model.textController ??= TextEditingController(); + _model.textFieldFocusNode ??= FocusNode(); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).secondaryBackground, + drawer: SizedBox( + width: 750.0, + child: Drawer( + elevation: 16.0, + child: Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + shape: BoxShape.rectangle, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(5.0), + bottomRight: Radius.circular(5.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + shape: BoxShape.rectangle, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 30.0, 0.0, 0.0), + child: Container( + width: 100.0, + height: 100.0, + decoration: const BoxDecoration(), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 50.0, + height: 50.0, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Image.network( + valueOrDefault( + 'https://freaccess.com.br/freaccess/Images/Clients/${FFAppState().cliUUID}.png', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + fit: BoxFit.cover, + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Container( + decoration: const BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'lyiat6s2' /* NOME DO MORADOR */, + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: 'Nunito Sans', + color: + FlutterFlowTheme.of( + context) + .info, + letterSpacing: 0.0, + fontWeight: + FontWeight.normal, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito Sans'), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + Container( + width: 100.0, + height: 100.0, + decoration: const BoxDecoration(), + child: FlutterFlowIconButton( + borderRadius: 100.0, + borderWidth: 1.0, + buttonSize: 1.0, + icon: Icon( + Icons.close_sharp, + color: FlutterFlowTheme.of(context).info, + size: 24.0, + ), + onPressed: () async { + if (scaffoldKey.currentState!.isDrawerOpen || + scaffoldKey.currentState!.isEndDrawerOpen) { + Navigator.pop(context); + } + }, + ), + ), + ], + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 8.0, 0.0, 8.0, 0.0), + child: TextFormField( + controller: _model.textController, + focusNode: _model.textFieldFocusNode, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + alignLabelWithHint: false, + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .customColor1, + width: 2.0, + ), + borderRadius: BorderRadius.circular(6.0), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 2.0, + ), + borderRadius: BorderRadius.circular(6.0), + ), + errorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(6.0), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(6.0), + ), + prefixIcon: const Icon( + Icons.search_sharp, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textControllerValidator + .asValidator(context), + ), + ), + ), + ], + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(10.0, 20.0, 10.0, 0.0), + child: ListView( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + children: [ + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kfast, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'dlaeicxd' /* Auto-Visita */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.khome, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + '53jd930v' /* Condominio */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kpets, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'ptsx0rln' /* Cadastrar Pet */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kvector1, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'rgxgw626' /* Cadastrar Visitante */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kvector2, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'j2tn9lpw' /* QR Code de Acesso */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kvector3, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + '9weuwgs1' /* Histórico de Acesso */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + Divider( + thickness: 1.0, + color: + FlutterFlowTheme.of(context).customColor1, + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 1.0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 40.0, + height: 40.0, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + FFIcons.kvector1, + color: FlutterFlowTheme.of(context) + .primary, + size: 24.0, + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'vuk5bjau' /* Agendar Visita */, + ), + style: FlutterFlowTheme.of( + context) + .titleLarge + .override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap() + .containsKey( + 'Nunito'), + ), + ), + ), + ), + Icon( + Icons.chevron_right_rounded, + color: FlutterFlowTheme.of(context) + .customColor1, + size: 24.0, + ), + ], + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + FFAppState().isLogged = false; + setState(() {}); + + context.goNamed( + 'onBoardingPage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.scale, + alignment: Alignment.bottomCenter, + ), + }, + ); + }, + text: FFLocalizations.of(context).getText( + 'xx0db4wi' /* Sair */, + ), + options: FFButtonOptions( + height: 40.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: const Color(0x00D70000), + textStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + elevation: 0.0, + borderSide: const BorderSide( + width: 0.0, + ), + borderRadius: BorderRadius.circular(50.0), + ), + ), + ), + ), + ].addToEnd(const SizedBox(height: 64.0)), + ), + ), + ), + ), + body: Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Wrap( + spacing: 0.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Container( + width: 100.0, + height: 100.0, + decoration: const BoxDecoration( + color: Color(0xFF1AAB5F), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + height: 50.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: FlutterFlowIconButton( + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + fillColor: + FlutterFlowTheme.of(context) + .primary, + icon: const Icon( + Icons.menu_rounded, + color: Colors.white, + size: 28.0, + ), + onPressed: () async { + scaffoldKey.currentState! + .openDrawer(); + }, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 60.0, 15.0, 0.0, 0.0), + child: ClipRRect( + borderRadius: + BorderRadius.circular(8.0), + child: Image.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/8r2vsbd9i03k/logo.png', + width: 50.0, + height: 200.0, + fit: BoxFit.none, + ), + ), + ), + ), + Align( + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 15.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'rg9pzkpz' /* FRE ACCESS */, + ), + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme + .of(context) + .info, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + width: 100.0, + height: 50.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional(1.0, 1.0), + child: FlutterFlowIconButton( + borderColor: + FlutterFlowTheme.of(context) + .primary, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + fillColor: FlutterFlowTheme.of(context) + .accent1, + icon: Icon( + Icons.notifications_sharp, + color: + FlutterFlowTheme.of(context).info, + size: 24.0, + ), + onPressed: () { + print('IconButton pressed ...'); + }, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + wrapWithModel( + model: _model.localComponentModel, + updateCallback: () => setState(() {}), + child: const LocalProfileComponentWidget(), + ), + Wrap( + spacing: 0.0, + runSpacing: 0.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: [ + wrapWithModel( + model: _model.menuComponentModel, + updateCallback: () => setState(() {}), + child: const MenuComponentWidget(), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: wrapWithModel( + model: _model.messageWellComponentModel, + updateCallback: () => setState(() {}), + child: const MessageWellComponentWidget(), + ), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/application_pages/register_visitor_page/register_visitor_page_model.dart b/lib/application_pages/register_visitor_page/register_visitor_page_model.dart new file mode 100644 index 00000000..81633e4d --- /dev/null +++ b/lib/application_pages/register_visitor_page/register_visitor_page_model.dart @@ -0,0 +1,58 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'register_visitor_page_widget.dart' show RegisterVisitorPageWidget; +import 'package:flutter/material.dart'; + +class RegisterVisitorPageModel + extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + bool isDataUploading = false; + FFUploadedFile uploadedLocalFile = + FFUploadedFile(bytes: Uint8List.fromList([])); + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + // State field(s) for DropDown widget. + String? dropDownValue; + FormFieldController? dropDownValueController; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode4; + TextEditingController? textController4; + String? Function(BuildContext, String?)? textController4Validator; + // Stores action output result for [Custom Action - convertImageFileToBase64] action in Button widget. + String? imgBase64; + // Stores action output result for [Backend Call - API (postScheduleVisitor)] action in Button widget. + ApiCallResponse? scheduleVisitor; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + unfocusNode.dispose(); + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + + textFieldFocusNode4?.dispose(); + textController4?.dispose(); + } +} diff --git a/lib/application_pages/register_visitor_page/register_visitor_page_widget.dart b/lib/application_pages/register_visitor_page/register_visitor_page_widget.dart new file mode 100644 index 00000000..cb72f361 --- /dev/null +++ b/lib/application_pages/register_visitor_page/register_visitor_page_widget.dart @@ -0,0 +1,898 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_drop_down.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/flutter_flow/form_field_controller.dart'; +import '/flutter_flow/upload_data.dart'; +import '/custom_code/actions/index.dart' as actions; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'register_visitor_page_model.dart'; +export 'register_visitor_page_model.dart'; + +class RegisterVisitorPageWidget extends StatefulWidget { + const RegisterVisitorPageWidget({super.key}); + + @override + State createState() => + _RegisterVisitorPageWidgetState(); +} + +class _RegisterVisitorPageWidgetState extends State { + late RegisterVisitorPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => RegisterVisitorPageModel()); + + _model.textController1 ??= TextEditingController(); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= TextEditingController(); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.textController3 ??= TextEditingController(); + _model.textFieldFocusNode3 ??= FocusNode(); + + _model.textController4 ??= TextEditingController(); + _model.textFieldFocusNode4 ??= FocusNode(); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(25.0), + topRight: Radius.circular(25.0), + ), + ), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 30.0, 0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, -1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 20.0), + child: Text( + FFLocalizations.of(context).getText( + 'q8cct5lk' /* Cadastrar Visitante */, + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Nunito', + fontSize: 21.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w800, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + ), + ), + Builder( + builder: (context) { + if ((_model.uploadedLocalFile.bytes?.isNotEmpty ?? + false)) { + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + setState(() { + _model.isDataUploading = false; + _model.uploadedLocalFile = FFUploadedFile( + bytes: Uint8List.fromList([])); + }); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.memory( + _model.uploadedLocalFile.bytes ?? + Uint8List.fromList([]), + width: 300.0, + height: 100.0, + fit: BoxFit.cover, + ), + ), + ); + } else { + return Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.01, 0.0), + child: FFButtonWidget( + onPressed: () async { + final selectedMedia = + await selectMediaWithSourceBottomSheet( + context: context, + maxWidth: 300.00, + maxHeight: 300.00, + imageQuality: 0, + allowPhoto: true, + includeDimensions: true, + ); + if (selectedMedia != null && + selectedMedia.every((m) => + validateFileFormat( + m.storagePath, context))) { + setState(() => + _model.isDataUploading = true); + var selectedUploadedFiles = + []; + + try { + showUploadMessage( + context, + 'Uploading file...', + showLoading: true, + ); + selectedUploadedFiles = selectedMedia + .map((m) => FFUploadedFile( + name: m.storagePath + .split('/') + .last, + bytes: m.bytes, + height: + m.dimensions?.height, + width: m.dimensions?.width, + blurHash: m.blurHash, + )) + .toList(); + } finally { + ScaffoldMessenger.of(context) + .hideCurrentSnackBar(); + _model.isDataUploading = false; + } + if (selectedUploadedFiles.length == + selectedMedia.length) { + setState(() { + _model.uploadedLocalFile = + selectedUploadedFiles.first; + }); + showUploadMessage( + context, 'Success!'); + } else { + setState(() {}); + showUploadMessage( + context, 'Failed to upload data'); + return; + } + } + }, + text: '', + icon: Icon( + Icons.photo_camera, + color: + FlutterFlowTheme.of(context).accent1, + size: 30.0, + ), + options: FFButtonOptions( + width: 300.0, + height: 80.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 14.0, 0.0, 0.0, 20.0), + color: FlutterFlowTheme.of(context) + .primaryBackground, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 50.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'p4ftwxcy' /* Clique para adicionar a foto p... */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ], + ); + } + }, + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'zazj5d8b' /* Preencha o formulário com os d... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController1, + focusNode: _model.textFieldFocusNode1, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'v7g73yik' /* Nome */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.person, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + maxLines: null, + keyboardType: TextInputType.name, + validator: _model.textController1Validator + .asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Container( + decoration: const BoxDecoration(), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 10.0, 20.0, 10.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'yp23q90m' /* Selecione o tipo: */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 20.0, 0.0, 5.0), + child: FlutterFlowDropDown( + controller: + _model.dropDownValueController ??= + FormFieldController(null), + options: [ + FFLocalizations.of(context).getText( + 'n8vddmcq' /* Visitante */, + ), + FFLocalizations.of(context).getText( + '9luaa09e' /* Prestador de Serviço */, + ) + ], + onChanged: (val) => setState( + () => _model.dropDownValue = val), + width: 200.0, + height: 48.0, + textStyle: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + 'pmezihb4' /* Selecione... */, + ), + icon: Icon( + Icons.keyboard_arrow_down_rounded, + color: FlutterFlowTheme.of(context) + .primaryText, + size: 24.0, + ), + elevation: 2.0, + borderColor: + FlutterFlowTheme.of(context).accent1, + borderWidth: 0.5, + borderRadius: 8.0, + margin: const EdgeInsetsDirectional.fromSTEB( + 16.0, 4.0, 16.0, 4.0), + hidesUnderline: true, + isOverButton: true, + isSearchable: false, + isMultiSelect: false, + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController2, + focusNode: _model.textFieldFocusNode2, + autofocus: false, + textCapitalization: TextCapitalization.none, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'rl8tvwnr' /* Documento */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.document_scanner, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController2Validator + .asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'bqpucwh0' /* Contatos */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController3, + focusNode: _model.textFieldFocusNode3, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'h84ls2r6' /* Telefone */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.phone, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + validator: _model.textController3Validator + .asValidator(context), + ), + ), + Padding( + padding: const EdgeInsets.all(24.0), + child: TextFormField( + controller: _model.textController4, + focusNode: _model.textFieldFocusNode4, + autofocus: false, + textInputAction: TextInputAction.done, + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'fqp7qmka' /* Email */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primary, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 0.5, + ), + borderRadius: BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.email, + color: FlutterFlowTheme.of(context).accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + keyboardType: TextInputType.emailAddress, + validator: _model.textController4Validator + .asValidator(context), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 50.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + if (((_model.uploadedLocalFile.bytes + ?.isNotEmpty ?? + false)) && + (_model.textController1.text != '') && + (_model.dropDownValue != null && + _model.dropDownValue != '') && + (_model.textController2.text != '')) { + _model.imgBase64 = + await actions.convertImageFileToBase64( + _model.uploadedLocalFile, + ); + _model.scheduleVisitor = + await PhpGroup.postScheduleVisitorCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'putVisitante', + documento: '7654553234232342', + nome: 'Test', + tipo: 'V', + foto: 'base64;jpeg,klajsalkjslkajslkajl', + ); + if (PhpGroup.postScheduleVisitorCall.error( + (_model.scheduleVisitor?.jsonBody ?? ''), + ) == + false) { + setState(() { + _model.textController1?.clear(); + _model.textController2?.clear(); + _model.textController3?.clear(); + _model.textController4?.clear(); + }); + setState(() { + _model.dropDownValueController?.reset(); + }); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus( + _model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: + '\\devUUID=${FFAppState().devUUID}\\userUUID=${FFAppState().userUUID}\\cliID=${FFAppState().cliUUID}\\Documento=${_model.textController2.text}\\Nome=${_model.textController1.text}\\dropdown${_model.dropDownValue}\\${PhpGroup.postScheduleVisitorCall.errorMsg( + (_model.scheduleVisitor + ?.jsonBody ?? + ''), + )}', + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: + 'Você esqueceu de adicionar algum dado obrigatório. Verifique se a imagem, nome, tipo e documento estão foram preenchidos corretamente.- devUUID=${FFAppState().devUUID}- userUUID=${FFAppState().userUUID}- cliID=${FFAppState().cliUUID}- Documento=${_model.textController2.text}- Nome=${_model.textController1.text}- Tipo=${_model.dropDownValue}', + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + text: FFLocalizations.of(context).getText( + 'okbw0aiu' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 36.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 80.0, 0.0, 80.0, 0.0), + iconPadding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context).info, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: const BorderSide( + color: Colors.transparent, + width: 30.0, + ), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart b/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart new file mode 100644 index 00000000..061b4853 --- /dev/null +++ b/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart @@ -0,0 +1,92 @@ +import '/components/select_header_component_widget.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/form_field_controller.dart'; +import 'schedule_complete_visit_page_widget.dart' + show ScheduleCompleteVisitPageWidget; +import 'package:flutter/material.dart'; + +class ScheduleCompleteVisitPageModel + extends FlutterFlowModel { + /// Local state fields for this page. + + List visitorJsonList = []; + void addToVisitorJsonList(dynamic item) => visitorJsonList.add(item); + void removeFromVisitorJsonList(dynamic item) => visitorJsonList.remove(item); + void removeAtIndexFromVisitorJsonList(int index) => + visitorJsonList.removeAt(index); + void insertAtIndexInVisitorJsonList(int index, dynamic item) => + visitorJsonList.insert(index, item); + void updateVisitorJsonListAtIndex(int index, Function(dynamic) updateFn) => + visitorJsonList[index] = updateFn(visitorJsonList[index]); + + String visitorStrList = '0'; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for selectHeaderComponent component. + late SelectHeaderComponentModel selectHeaderComponentModel; + // Stores action output result for [Action Block - toggleCurrentSelectionHeader] action in selectHeaderComponent widget. + bool? toggleIndexValue; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + DateTime? datePicked1; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + DateTime? datePicked2; + // State field(s) for DropDown widget. + String? dropDownValue1; + FormFieldController? dropDownValueController1; + // State field(s) for DropDown widget. + String? dropDownValue2; + FormFieldController? dropDownValueController2; + // State field(s) for Switch widget. + bool? switchValue; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + + @override + void initState(BuildContext context) { + selectHeaderComponentModel = + createModel(context, () => SelectHeaderComponentModel()); + } + + @override + void dispose() { + unfocusNode.dispose(); + selectHeaderComponentModel.dispose(); + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + } + + /// Action blocks. + Future getVisitorsActionPage( + BuildContext context, { + List? visitorsJsonList, + }) async { + visitorJsonList = visitorsJsonList!.toList().cast(); + } + + Future toggleCurrentSelectionHeader( + BuildContext context, { + required bool? toggleIndexValue, + }) async { + if (toggleIndexValue == true) { + return true; + } + + return false; + } +} diff --git a/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart b/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart new file mode 100644 index 00000000..71159cbe --- /dev/null +++ b/lib/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart @@ -0,0 +1,2539 @@ +import '/application_components/molecular_components/opt_modal/opt_modal_widget.dart'; +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/application_components/templates_components/visit_details_modal/visit_details_modal_widget.dart'; +import '/application_components/templates_components/visitor_details_modal/visitor_details_modal_widget.dart'; +import '/application_components/templates_components/visitor_search_component/visitor_search_component_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/components/select_header_component_widget.dart'; +import '/flutter_flow/flutter_flow_drop_down.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/flutter_flow/form_field_controller.dart'; +import '/flutter_flow/custom_functions.dart' as functions; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'schedule_complete_visit_page_model.dart'; +export 'schedule_complete_visit_page_model.dart'; + +class ScheduleCompleteVisitPageWidget extends StatefulWidget { + const ScheduleCompleteVisitPageWidget({ + super.key, + this.visitorStrList, + this.visitStartDateStr, + this.visitEndDateStr, + this.visitReasonStr, + this.visitLevelStr, + this.visitTempBol, + this.visitObsStr, + this.visitorJsonList, + }); + + final String? visitorStrList; + final String? visitStartDateStr; + final String? visitEndDateStr; + final String? visitReasonStr; + final String? visitLevelStr; + final bool? visitTempBol; + final String? visitObsStr; + final List? visitorJsonList; + + @override + State createState() => + _ScheduleCompleteVisitPageWidgetState(); +} + +class _ScheduleCompleteVisitPageWidgetState + extends State { + late ScheduleCompleteVisitPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ScheduleCompleteVisitPageModel()); + + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + if ((widget.visitorStrList != null && widget.visitorStrList != '') && + ((widget.visitorJsonList != null && + (widget.visitorJsonList)!.isNotEmpty) != + null)) { + _model.visitorJsonList = widget.visitorJsonList! + .where((e) => + widget.visitorStrList == + getJsonField( + e, + r'''$.VTE_DOCUMENTO''', + )) + .toList() + .toList() + .cast(); + _model.visitorStrList = widget.visitorStrList!; + setState(() {}); + } else { + return; + } + }); + + _model.textController1 ??= TextEditingController(); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= TextEditingController(); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.switchValue = true; + _model.textController3 ??= TextEditingController(); + _model.textFieldFocusNode3 ??= FocusNode(); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: FlutterFlowTheme.of(context).primaryText, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + FFLocalizations.of(context).getText( + '61lcxdgm' /* Agendar Visita */, + ), + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + actions: const [], + centerTitle: true, + ), + body: SafeArea( + top: true, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + wrapWithModel( + model: _model.selectHeaderComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: SelectHeaderComponentWidget( + toggleIndexValue: _model.toggleIndexValue, + selectToggle: (toggleIndex) async { + _model.toggleIndexValue = + await _model.toggleCurrentSelectionHeader( + context, + toggleIndexValue: toggleIndex, + ); + + setState(() {}); + }, + ), + ), + if (valueOrDefault( + _model.toggleIndexValue == true, + true, + )) + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Stack( + children: [ + Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'qo0pg2at' /* Quais visitantes você deseja c... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + if (_model.visitorJsonList.isNotEmpty) + Builder( + builder: (context) { + final visitorListView = _model + .visitorJsonList + .map((e) => e) + .toList(); + return ListView.separated( + padding: const EdgeInsets.fromLTRB( + 0, + 0, + 0, + 20.0, + ), + shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: visitorListView.length, + separatorBuilder: (_, __) => + const SizedBox(height: 5.0), + itemBuilder: (context, + visitorListViewIndex) { + final visitorListViewItem = + visitorListView[ + visitorListViewIndex]; + return InkWell( + splashColor: + Colors.transparent, + focusColor: + Colors.transparent, + hoverColor: + Colors.transparent, + highlightColor: + Colors.transparent, + onTap: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: + Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode + .canRequestFocus + ? FocusScope.of( + context) + .requestFocus( + _model + .unfocusNode) + : FocusScope.of( + context) + .unfocus(), + child: Padding( + padding: MediaQuery + .viewInsetsOf( + context), + child: + const VisitorDetailsModalWidget(), + ), + ); + }, + ).then((value) => + safeSetState(() {})); + }, + onLongPress: () async { + _model + .removeFromVisitorJsonList( + visitorListViewItem); + setState(() {}); + }, + child: Container( + width: 100.0, + height: 70.0, + decoration: BoxDecoration( + color: FlutterFlowTheme + .of(context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 50.0, + height: 50.0, + clipBehavior: + Clip.antiAlias, + decoration: + const BoxDecoration( + shape: + BoxShape.circle, + ), + child: + CachedNetworkImage( + fadeInDuration: + const Duration( + milliseconds: + 500), + fadeOutDuration: + const Duration( + milliseconds: + 500), + imageUrl: + valueOrDefault< + String>( + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + visitorListViewItem, + r'''$.VTE_DOCUMENTO''', + ).toString()}&tipo=E', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + fit: BoxFit.cover, + ), + ), + Column( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + Text( + getJsonField( + visitorListViewItem, + r'''$.VTE_NOME''', + ).toString(), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + Text( + getJsonField( + visitorListViewItem, + r'''$.VTE_TIPO''', + ).toString(), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ], + ), + ] + .divide(const SizedBox( + width: 30.0)) + .addToStart(const SizedBox( + width: 30.0)), + ), + ), + ); + }, + ); + }, + ), + Stack( + children: [ + Align( + alignment: + const AlignmentDirectional(0.01, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 20.0), + child: FFButtonWidget( + onPressed: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: + FlutterFlowTheme.of( + context) + .primaryBackground, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode + .canRequestFocus + ? FocusScope.of( + context) + .requestFocus(_model + .unfocusNode) + : FocusScope.of( + context) + .unfocus(), + child: Padding( + padding: MediaQuery + .viewInsetsOf( + context), + child: + VisitorSearchComponentWidget( + getVisitors: + (visitorsParam) async { + _model.visitorJsonList = + visitorsParam! + .toList() + .cast< + dynamic>(); + setState(() {}); + }, + getDocs: + (docsParam) async { + _model.visitorStrList = + functions.strListToStr( + docsParam! + .toList()); + setState(() {}); + }, + ), + ), + ); + }, + ).then((value) => + safeSetState(() {})); + }, + text: '', + icon: Icon( + Icons.add, + color: FlutterFlowTheme.of( + context) + .primary, + size: 30.0, + ), + options: FFButtonOptions( + width: + MediaQuery.sizeOf(context) + .width * + 0.8, + height: 80.0, + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(14.0, 0.0, + 0.0, 20.0), + color: FlutterFlowTheme.of( + context) + .primaryBackground, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .titleSmallFamily, + color: + FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .accent4, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 8.0), + ), + ), + ), + ), + Align( + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 50.0, 0.0, 0.0), + child: Container( + width: + MediaQuery.sizeOf(context) + .width * + 0.8, + height: 20.0, + decoration: const BoxDecoration(), + child: Align( + alignment: + const AlignmentDirectional( + 0.0, 0.0), + child: AutoSizeText( + FFLocalizations.of(context) + .getText( + 'i0jhuu3e' /* Clique para adicionar um visit... */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme + .of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 24.0, 0.0, 24.0), + child: Text( + FFLocalizations.of(context).getText( + 'z4ry3tge' /* Qual o período de validade da ... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 0.0), + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'hjp5mzbd' /* Inicio da Visita */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + Expanded( + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: SizedBox( + height: double.infinity, + child: Stack( + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 24.0, + 0.0), + child: TextFormField( + controller: _model + .textController1, + focusNode: _model + .textFieldFocusNode1, + autofocus: false, + obscureText: false, + decoration: + InputDecoration( + isDense: true, + labelStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintText: + FFLocalizations.of( + context) + .getText( + 'ce6xryf4' /* Quando você inicia a visita? */, + ), + hintStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + lineHeight: + 1.0, + ), + enabledBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .accent4, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + suffixIcon: Icon( + Icons.date_range, + color: FlutterFlowTheme + .of(context) + .accent1, + ), + ), + style: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + lineHeight: + 1.0, + ), + textAlign: + TextAlign.center, + validator: _model + .textController1Validator + .asValidator( + context), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 24.0, + 0.0), + child: InkWell( + splashColor: + Colors.transparent, + focusColor: + Colors.transparent, + hoverColor: + Colors.transparent, + highlightColor: + Colors.transparent, + onTap: () async { + final datePicked1Date = + await showDatePicker( + context: context, + initialDate: + getCurrentTimestamp, + firstDate: + getCurrentTimestamp, + lastDate: + DateTime(2050), + builder: (context, + child) { + return wrapInMaterialDatePickerTheme( + context, + child!, + headerBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + headerForegroundColor: + FlutterFlowTheme.of( + context) + .info, + headerTextStyle: + FlutterFlowTheme.of( + context) + .headlineLarge + .override( + fontFamily: + FlutterFlowTheme.of(context).headlineLargeFamily, + fontSize: + 32.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: + GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineLargeFamily), + ), + pickerBackgroundColor: + FlutterFlowTheme.of( + context) + .secondaryBackground, + pickerForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + selectedDateTimeBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + selectedDateTimeForegroundColor: + FlutterFlowTheme.of( + context) + .info, + actionButtonForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + iconSize: 24.0, + ); + }, + ); + + TimeOfDay? + datePicked1Time; + if (datePicked1Date != + null) { + datePicked1Time = + await showTimePicker( + context: context, + initialTime: TimeOfDay + .fromDateTime( + getCurrentTimestamp), + builder: (context, + child) { + return wrapInMaterialTimePickerTheme( + context, + child!, + headerBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + headerForegroundColor: + FlutterFlowTheme.of( + context) + .info, + headerTextStyle: FlutterFlowTheme.of( + context) + .headlineLarge + .override( + fontFamily: + FlutterFlowTheme.of(context).headlineLargeFamily, + fontSize: + 32.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: + GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineLargeFamily), + ), + pickerBackgroundColor: + FlutterFlowTheme.of( + context) + .secondaryBackground, + pickerForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + selectedDateTimeBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + selectedDateTimeForegroundColor: + FlutterFlowTheme.of( + context) + .info, + actionButtonForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + iconSize: + 24.0, + ); + }, + ); + } + + if (datePicked1Date != + null && + datePicked1Time != + null) { + safeSetState(() { + _model.datePicked1 = + DateTime( + datePicked1Date + .year, + datePicked1Date + .month, + datePicked1Date + .day, + datePicked1Time! + .hour, + datePicked1Time + .minute, + ); + }); + } + setState(() { + _model.textController1 + ?.text = + dateTimeFormat( + 'd/M/y H:mm:ss', + _model + .datePicked1, + locale: FFLocalizations + .of(context) + .languageCode, + ); + }); + }, + child: Container( + width: + double.infinity, + height: 55.0, + decoration: + BoxDecoration( + borderRadius: + BorderRadius + .circular( + 8.0), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 0.0), + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'jwsbk0xu' /* Fim da Visita */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + Expanded( + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: SizedBox( + height: double.infinity, + child: Stack( + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 24.0, + 0.0), + child: TextFormField( + controller: _model + .textController2, + focusNode: _model + .textFieldFocusNode2, + autofocus: false, + obscureText: false, + decoration: + InputDecoration( + isDense: true, + labelStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + ), + hintText: + FFLocalizations.of( + context) + .getText( + 'lyfe46f6' /* Quando a visita terminá? */, + ), + hintStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).labelMediumFamily), + lineHeight: + 1.0, + ), + enabledBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .accent4, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular( + 8.0), + ), + suffixIcon: Icon( + Icons.date_range, + color: FlutterFlowTheme + .of(context) + .accent1, + ), + ), + style: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + lineHeight: + 1.0, + ), + textAlign: + TextAlign.center, + validator: _model + .textController2Validator + .asValidator( + context), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 24.0, + 0.0), + child: InkWell( + splashColor: + Colors.transparent, + focusColor: + Colors.transparent, + hoverColor: + Colors.transparent, + highlightColor: + Colors.transparent, + onTap: () async { + final datePicked2Date = + await showDatePicker( + context: context, + initialDate: + getCurrentTimestamp, + firstDate: + getCurrentTimestamp, + lastDate: + DateTime(2050), + builder: (context, + child) { + return wrapInMaterialDatePickerTheme( + context, + child!, + headerBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + headerForegroundColor: + FlutterFlowTheme.of( + context) + .info, + headerTextStyle: + FlutterFlowTheme.of( + context) + .headlineLarge + .override( + fontFamily: + FlutterFlowTheme.of(context).headlineLargeFamily, + fontSize: + 32.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: + GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineLargeFamily), + ), + pickerBackgroundColor: + FlutterFlowTheme.of( + context) + .secondaryBackground, + pickerForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + selectedDateTimeBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + selectedDateTimeForegroundColor: + FlutterFlowTheme.of( + context) + .info, + actionButtonForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + iconSize: 24.0, + ); + }, + ); + + TimeOfDay? + datePicked2Time; + if (datePicked2Date != + null) { + datePicked2Time = + await showTimePicker( + context: context, + initialTime: TimeOfDay + .fromDateTime( + getCurrentTimestamp), + builder: (context, + child) { + return wrapInMaterialTimePickerTheme( + context, + child!, + headerBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + headerForegroundColor: + FlutterFlowTheme.of( + context) + .info, + headerTextStyle: FlutterFlowTheme.of( + context) + .headlineLarge + .override( + fontFamily: + FlutterFlowTheme.of(context).headlineLargeFamily, + fontSize: + 32.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: + GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineLargeFamily), + ), + pickerBackgroundColor: + FlutterFlowTheme.of( + context) + .secondaryBackground, + pickerForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + selectedDateTimeBackgroundColor: + FlutterFlowTheme.of( + context) + .primary, + selectedDateTimeForegroundColor: + FlutterFlowTheme.of( + context) + .info, + actionButtonForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, + iconSize: + 24.0, + ); + }, + ); + } + + if (datePicked2Date != + null && + datePicked2Time != + null) { + safeSetState(() { + _model.datePicked2 = + DateTime( + datePicked2Date + .year, + datePicked2Date + .month, + datePicked2Date + .day, + datePicked2Time! + .hour, + datePicked2Time + .minute, + ); + }); + } + setState(() { + _model.textController2 + ?.text = + dateTimeFormat( + 'd/M/y H:mm:ss', + _model + .datePicked2, + locale: FFLocalizations + .of(context) + .languageCode, + ); + }); + }, + child: Container( + width: + double.infinity, + height: 39.0, + decoration: + BoxDecoration( + borderRadius: + BorderRadius + .circular( + 8.0), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ].divide(const SizedBox(height: 10.0)), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 24.0, 0.0, 24.0), + child: Text( + FFLocalizations.of(context).getText( + 'p81uol2v' /* Quais são os motivos da visita... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 0.0), + child: Container( + width: 100.0, + height: 42.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'bbauep0b' /* Motivo da Visita */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 24.0, 0.0), + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: FutureBuilder< + ApiCallResponse>( + future: PhpGroup.getDadosCall + .call( + devUUID: + FFAppState().devUUID, + userUUID: + FFAppState().userUUID, + cliUUID: + FFAppState().cliUUID, + atividade: 'getDados', + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme + .of(context) + .primary, + size: 50.0, + ), + ), + ); + } + final dropDownGetDadosResponse = + snapshot.data!; + return FlutterFlowDropDown< + String>( + controller: _model + .dropDownValueController1 ??= + FormFieldController< + String>( + _model.dropDownValue1 ??= + '', + ), + options: List< + String>.from( + PhpGroup.getDadosCall + .reasonsJsonList( + dropDownGetDadosResponse + .jsonBody, + )! + .map((e) => + e.toString()) + .toList()), + optionLabels: PhpGroup + .getDadosCall + .reasonsMotDescStrList( + dropDownGetDadosResponse + .jsonBody, + )!, + onChanged: (val) => + setState(() => _model + .dropDownValue1 = + val), + width: double.infinity, + height: double.infinity, + textStyle: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + hintText: + FFLocalizations.of( + context) + .getText( + 'x1ij847i' /* Escolha um motivo aqui */, + ), + icon: Icon( + Icons + .keyboard_arrow_down_rounded, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 24.0, + ), + elevation: 2.0, + borderColor: + FlutterFlowTheme.of( + context) + .accent4, + borderWidth: 0.5, + borderRadius: 10.0, + margin: + const EdgeInsetsDirectional + .fromSTEB( + 16.0, + 0.0, + 16.0, + 0.0), + hidesUnderline: true, + isOverButton: true, + isSearchable: false, + isMultiSelect: false, + ); + }, + ), + ), + ), + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 0.0), + child: Container( + width: 100.0, + height: 42.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional( + 0.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + 'etzbm8l5' /* Nível de Acesso */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 24.0, 0.0), + child: Container( + width: 100.0, + height: 40.0, + decoration: const BoxDecoration(), + child: FutureBuilder< + ApiCallResponse>( + future: PhpGroup.getDadosCall + .call( + devUUID: + FFAppState().devUUID, + userUUID: + FFAppState().userUUID, + cliUUID: + FFAppState().cliUUID, + atividade: 'getDados', + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme + .of(context) + .primary, + size: 50.0, + ), + ), + ); + } + final dropDownGetDadosResponse = + snapshot.data!; + return FlutterFlowDropDown< + String>( + controller: _model + .dropDownValueController2 ??= + FormFieldController< + String>( + _model.dropDownValue2 ??= + '', + ), + options: List< + String>.from( + PhpGroup.getDadosCall + .levelJsonList( + dropDownGetDadosResponse + .jsonBody, + )! + .map((e) => + e.toString()) + .toList()), + optionLabels: PhpGroup + .getDadosCall + .levelNACDescricaoStrList( + dropDownGetDadosResponse + .jsonBody, + )!, + onChanged: (val) => + setState(() => _model + .dropDownValue2 = + val), + width: double.infinity, + height: double.infinity, + textStyle: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + hintText: + FFLocalizations.of( + context) + .getText( + 'kmgv5j7x' /* Escolha um nível de acesso aqu... */, + ), + icon: Icon( + Icons + .keyboard_arrow_down_rounded, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 24.0, + ), + elevation: 2.0, + borderColor: + FlutterFlowTheme.of( + context) + .accent4, + borderWidth: 0.5, + borderRadius: 10.0, + margin: + const EdgeInsetsDirectional + .fromSTEB( + 16.0, + 0.0, + 16.0, + 0.0), + hidesUnderline: true, + isOverButton: true, + isSearchable: false, + isMultiSelect: false, + ); + }, + ), + ), + ), + ), + ], + ), + ].divide(const SizedBox(height: 10.0)), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 24.0, 0.0, 24.0), + child: Text( + FFLocalizations.of(context).getText( + 'mddp33o0' /* Visita se encerra após o prime... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 30.0, 0.0, 30.0, 20.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 130.0, 0.0), + child: Text( + FFLocalizations.of(context) + .getText( + '68j9gw4h' /* Visita única */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Switch.adaptive( + value: _model.switchValue!, + onChanged: (newValue) async { + setState(() => _model + .switchValue = newValue); + }, + activeColor: + FlutterFlowTheme.of(context) + .success, + activeTrackColor: + FlutterFlowTheme.of(context) + .customColor4, + inactiveTrackColor: + FlutterFlowTheme.of(context) + .customColor4, + inactiveThumbColor: + FlutterFlowTheme.of(context) + .error, + ), + ], + ), + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 20.0, 0.0, 0.0, 24.0), + child: Text( + FFLocalizations.of(context).getText( + '9rudpkq7' /* Você tem alguma observação sob... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model.textController3, + focusNode: + _model.textFieldFocusNode3, + autofocus: false, + textInputAction: + TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + isDense: true, + labelText: + FFLocalizations.of(context) + .getText( + '4rgpxrfe' /* Observações da Visita */, + ), + labelStyle: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelMediumFamily, + color: + FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context) + .getText( + '7knytis2' /* Escreva as suas observações aq... */, + ), + hintStyle: + FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .labelMediumFamily, + color: + FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .accent4, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.text_fields, + color: + FlutterFlowTheme.of(context) + .accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + textAlign: TextAlign.start, + maxLines: null, + validator: _model + .textController3Validator + .asValidator(context), + ), + ), + ), + ], + ), + Container( + width: 100.0, + height: 54.0, + decoration: const BoxDecoration(), + ), + ], + ), + ), + ), + ], + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + if ((_model.textController1.text != '') && + (_model.textController2.text != '') && + (_model.dropDownValue1 != null && + _model.dropDownValue1 != '') && + (_model.dropDownValue2 != null && + _model.dropDownValue2 != '')) { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => + _model.unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf(context), + child: VisitDetailsModalWidget( + visitStartDateStr: + _model.textController1.text, + visitEndDateStr: + _model.textController2.text, + visitReasonStr: _model.dropDownValue1, + visitLevelStr: _model.dropDownValue2, + visitTempStr: _model.switchValue == true + ? 'Sim' + : 'Não', + visitObsStr: _model.textController3.text, + visitorStrList: _model.visitorStrList, + visitorJsonList: _model.visitorJsonList, + updateToggleIdx: () async {}, + repeatVisitSchedule: () async {}, + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => + _model.unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const ThrowExceptionWidget( + msg: 'Campos obrigatórios imcompletos.', + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + }, + child: Container( + width: MediaQuery.sizeOf(context).width * 0.5, + height: 40.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: BorderRadius.circular(10.0), + ), + alignment: const AlignmentDirectional(0.0, 1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.save_alt, + color: FlutterFlowTheme.of(context).info, + size: 24.0, + ), + ), + ), + ), + ].addToEnd(const SizedBox(height: 30.0)), + ), + if (valueOrDefault( + _model.toggleIndexValue == false, + true, + )) + Container( + width: double.infinity, + height: 900.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 20.0, + borderWidth: 1.0, + buttonSize: 40.0, + icon: Icon( + Icons.settings_sharp, + color: FlutterFlowTheme.of(context).primary, + size: 24.0, + ), + onPressed: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: const OptModalWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + ), + ], + ), + FutureBuilder( + future: PhpGroup.getVisitsCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'getVisitas', + ), + builder: (context, snapshot) { + // Customize what your widget looks like when it's loading. + if (!snapshot.hasData) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } + final wrapGetVisitsResponse = snapshot.data!; + return Builder( + builder: (context) { + final visitaWrap = PhpGroup.getVisitsCall + .visitasList( + wrapGetVisitsResponse.jsonBody, + ) + ?.toList() ?? + []; + return Wrap( + spacing: 2.0, + runSpacing: 1.0, + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + direction: Axis.horizontal, + runAlignment: WrapAlignment.start, + verticalDirection: VerticalDirection.down, + clipBehavior: Clip.none, + children: List.generate(visitaWrap.length, + (visitaWrapIndex) { + final visitaWrapItem = + visitaWrap[visitaWrapIndex]; + return Card( + clipBehavior: Clip.antiAliasWithSaveLayer, + color: FlutterFlowTheme.of(context) + .secondaryBackground, + elevation: 5.0, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(8.0), + ), + child: Container( + width: 350.0, + height: 115.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + width: 100.0, + height: 100.0, + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Text( + FFLocalizations.of( + context) + .getText( + 'd34nuw4w' /* Visitante: */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1.0, -1.0), + child: Text( + FFLocalizations.of( + context) + .getText( + 'y8geteyc' /* Lucas Martin Mota */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ].addToStart(const SizedBox( + width: 10.0)), + ), + Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Text( + FFLocalizations.of( + context) + .getText( + 'gxdykms1' /* Morador: */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + Text( + FFLocalizations.of( + context) + .getText( + 'ue7wkm9r' /* Lucas Martin Mota */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ].addToStart(const SizedBox( + width: 10.0)), + ), + Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + Text( + FFLocalizations.of( + context) + .getText( + 'zs8s0wd3' /* Validade: */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .bold, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + Text( + FFLocalizations.of( + context) + .getText( + 'z7fset9r' /* 16/10/2024 a 16/10/2024 */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + fontSize: 13.0, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ].addToStart(const SizedBox( + width: 10.0)), + ), + Align( + alignment: + const AlignmentDirectional( + -1.0, 0.0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 10.0, + 0.0, + 0.0, + 0.0), + child: Container( + width: 200.0, + height: 27.0, + decoration: + BoxDecoration( + color: FlutterFlowTheme + .of(context) + .primary, + borderRadius: + BorderRadius + .circular( + 5.0), + ), + child: Align( + alignment: + const AlignmentDirectional( + 0.0, 0.0), + child: Text( + FFLocalizations.of( + context) + .getText( + 'fcb5avae' /* Agendamento Ativo */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of( + context) + .info, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ].divide( + const SizedBox(height: 2.0)), + ), + ), + ), + ClipRRect( + borderRadius: + BorderRadius.circular(0.0), + child: Image.network( + 'https://images.unsplash.com/photo-1599566150163-29194dcaad36?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0NTYyMDF8MHwxfHNlYXJjaHwxNHx8cGVyc29ufGVufDB8fHx8MTcxNzc4MDk1Mnww&ixlib=rb-4.0.3&q=80&w=1080', + fit: BoxFit.cover, + ), + ), + ], + ), + ), + ); + }), + ); + }, + ); + }, + ), + ], + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_model.dart b/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_model.dart new file mode 100644 index 00000000..6166e387 --- /dev/null +++ b/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_model.dart @@ -0,0 +1,64 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'schedule_provisional_visit_page_widget.dart' + show ScheduleProvisionalVisitPageWidget; +import 'package:flutter/material.dart'; + +class ScheduleProvisionalVisitPageModel + extends FlutterFlowModel { + /// Local state fields for this page. + + bool toggleIdx = false; + + List visitors = []; + void addToVisitors(dynamic item) => visitors.add(item); + void removeFromVisitors(dynamic item) => visitors.remove(item); + void removeAtIndexFromVisitors(int index) => visitors.removeAt(index); + void insertAtIndexInVisitors(int index, dynamic item) => + visitors.insert(index, item); + void updateVisitorsAtIndex(int index, Function(dynamic) updateFn) => + visitors[index] = updateFn(visitors[index]); + + List docs = []; + void addToDocs(String item) => docs.add(item); + void removeFromDocs(String item) => docs.remove(item); + void removeAtIndexFromDocs(int index) => docs.removeAt(index); + void insertAtIndexInDocs(int index, String item) => docs.insert(index, item); + void updateDocsAtIndex(int index, Function(String) updateFn) => + docs[index] = updateFn(docs[index]); + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode1; + TextEditingController? textController1; + String? Function(BuildContext, String?)? textController1Validator; + DateTime? datePicked; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode2; + TextEditingController? textController2; + String? Function(BuildContext, String?)? textController2Validator; + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode3; + TextEditingController? textController3; + String? Function(BuildContext, String?)? textController3Validator; + // Stores action output result for [Backend Call - API (postProvVisitScheduling)] action in sendContainer widget. + ApiCallResponse? provisionalVisitScheduling; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + unfocusNode.dispose(); + textFieldFocusNode1?.dispose(); + textController1?.dispose(); + + textFieldFocusNode2?.dispose(); + textController2?.dispose(); + + textFieldFocusNode3?.dispose(); + textController3?.dispose(); + } +} diff --git a/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart b/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart new file mode 100644 index 00000000..f9c25f93 --- /dev/null +++ b/lib/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart @@ -0,0 +1,925 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'schedule_provisional_visit_page_model.dart'; +export 'schedule_provisional_visit_page_model.dart'; + +class ScheduleProvisionalVisitPageWidget extends StatefulWidget { + const ScheduleProvisionalVisitPageWidget({super.key}); + + @override + State createState() => + _ScheduleProvisionalVisitPageWidgetState(); +} + +class _ScheduleProvisionalVisitPageWidgetState + extends State { + late ScheduleProvisionalVisitPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ScheduleProvisionalVisitPageModel()); + + _model.textController1 ??= TextEditingController(); + _model.textFieldFocusNode1 ??= FocusNode(); + + _model.textController2 ??= TextEditingController(); + _model.textFieldFocusNode2 ??= FocusNode(); + + _model.textController3 ??= TextEditingController(); + _model.textFieldFocusNode3 ??= FocusNode(); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + _model.toggleIdx = true; + setState(() {}); + }, + child: Container( + width: 100.0, + height: 40.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(100.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(100.0), + ), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'n7bbd202' /* Agendamento Provisório */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context).info, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 10.0, 0.0, 0.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, -1.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 20.0, 0.0, 20.0), + child: Text( + FFLocalizations.of(context).getText( + 'i4xujgbn' /* Visita Provisória */, + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: 'Nunito', + fontSize: 21.0, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Nunito'), + ), + ), + ), + ), + ], + ), + ), + Divider( + thickness: 0.5, + color: FlutterFlowTheme.of(context).accent1, + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'x7at46ur' /* Quais visitantes você deseja c... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Stack( + children: [ + FFButtonWidget( + onPressed: () async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus( + _model.unfocusNode) + : FocusScope.of(context) + .unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf( + context), + child: + const BottomArrowLinkedLocalsComponentWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + text: FFAppState().local, + options: FFButtonOptions( + width: 320.0, + height: 51.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primaryBackground, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryText, + width: 0.3, + ), + borderRadius: BorderRadius.circular(24.0), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 10.0, 0.0, 0.0), + child: Container( + width: 35.0, + height: 35.0, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: CachedNetworkImage( + fadeInDuration: + const Duration(milliseconds: 100), + fadeOutDuration: + const Duration(milliseconds: 100), + imageUrl: valueOrDefault( + 'https://freaccess.com.br/freaccess/Images/Clients/${FFAppState().cliUUID}.png', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + fit: BoxFit.cover, + ), + ), + ), + ], + ), + ].addToEnd(const SizedBox(height: 20.0)), + ), + Divider( + thickness: 0.5, + color: FlutterFlowTheme.of(context).accent1, + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'shj19b2o' /* Qual o período de validade da ... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Stack( + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 50.0, 24.0, 0.0), + child: TextFormField( + controller: _model.textController1, + focusNode: _model.textFieldFocusNode1, + autofocus: false, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + '8zgsw5so' /* Ínicio da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + 'p16wm7kp' /* Quando a visitas se inicia? */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(8.0), + ), + suffixIcon: Icon( + Icons.hourglass_top, + color: FlutterFlowTheme.of(context) + .accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.center, + validator: _model.textController1Validator + .asValidator(context), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 50.0, 24.0, 0.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + final datePickedDate = + await showDatePicker( + context: context, + initialDate: getCurrentTimestamp, + firstDate: DateTime(1900), + lastDate: DateTime(2050), + builder: (context, child) { + return wrapInMaterialDatePickerTheme( + context, + child!, + headerBackgroundColor: + FlutterFlowTheme.of(context) + .primary, + headerForegroundColor: + FlutterFlowTheme.of(context) + .info, + headerTextStyle: + FlutterFlowTheme.of(context) + .headlineLarge + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .headlineLargeFamily, + fontSize: 32.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .headlineLargeFamily), + ), + pickerBackgroundColor: + FlutterFlowTheme.of(context) + .secondaryBackground, + pickerForegroundColor: + FlutterFlowTheme.of(context) + .primaryText, + selectedDateTimeBackgroundColor: + FlutterFlowTheme.of(context) + .primary, + selectedDateTimeForegroundColor: + FlutterFlowTheme.of(context) + .info, + actionButtonForegroundColor: + FlutterFlowTheme.of(context) + .primaryText, + iconSize: 24.0, + ); + }, + ); + + if (datePickedDate != null) { + safeSetState(() { + _model.datePicked = DateTime( + datePickedDate.year, + datePickedDate.month, + datePickedDate.day, + ); + }); + } + setState(() { + _model.textController1?.text = + dateTimeFormat( + 'd/M/y', + _model.datePicked, + locale: FFLocalizations.of(context) + .languageCode, + ); + }); + }, + child: Container( + width: double.infinity, + height: 50.0, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(8.0), + ), + ), + ), + ), + ], + ), + ], + ), + Divider( + thickness: 0.5, + color: FlutterFlowTheme.of(context).accent1, + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + '3zfd7uf9' /* Qual o nome do visitante? */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Container( + height: 93.0, + decoration: const BoxDecoration(), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 20.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model.textController2, + focusNode: _model.textFieldFocusNode2, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'wehvxbz4' /* Nome do Visitante */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + 'juh7f24w' /* Escreva o nome do visitante aq... */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.person, + color: FlutterFlowTheme.of(context) + .accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.start, + maxLines: null, + validator: _model.textController2Validator + .asValidator(context), + ), + ), + ), + ), + ], + ), + Divider( + thickness: 0.5, + color: FlutterFlowTheme.of(context).accent1, + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(-1.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 20.0, 30.0, 0.0, 30.0), + child: Text( + FFLocalizations.of(context).getText( + 'jhss056s' /* Você tem alguma observação sob... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 20.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model.textController3, + focusNode: _model.textFieldFocusNode3, + autofocus: false, + textInputAction: TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context).getText( + 'cw8b3tbb' /* Observações da Visita */, + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + hintText: + FFLocalizations.of(context).getText( + 'k4qkbv1f' /* Escreva as suas observações aq... */, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .accent1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primary, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(10.0), + ), + suffixIcon: Icon( + Icons.format_color_text, + color: FlutterFlowTheme.of(context) + .accent1, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + textAlign: TextAlign.start, + maxLines: null, + validator: _model.textController3Validator + .asValidator(context), + ), + ), + ), + ], + ), + Container( + width: 100.0, + height: 54.0, + decoration: const BoxDecoration(), + ), + ], + ), + ), + ), + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + _model.provisionalVisitScheduling = + await PhpGroup.postProvVisitSchedulingCall.call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'putAgendamentoProv', + data: _model.textController1.text, + motivo: _model.textController3.text, + nome: _model.textController2.text, + proID: FFAppState().ownerUUID, + ); + if (PhpGroup.postProvVisitSchedulingCall.error( + (_model.provisionalVisitScheduling?.jsonBody ?? ''), + ) == + false) { + setState(() { + _model.textController1?.clear(); + _model.textController2?.clear(); + _model.textController3?.clear(); + }); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: PhpGroup.postProvVisitSchedulingCall.msg( + (_model.provisionalVisitScheduling + ?.jsonBody ?? + ''), + )!, + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + } + + setState(() {}); + }, + child: Container( + width: 100.0, + height: 40.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15.0), + bottomRight: Radius.circular(15.0), + topLeft: Radius.circular(15.0), + topRight: Radius.circular(15.0), + ), + ), + alignment: const AlignmentDirectional(0.0, 1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Icon( + Icons.save_alt, + color: FlutterFlowTheme.of(context).info, + size: 24.0, + ), + ), + ), + ), + ], + ), + ] + .addToStart(const SizedBox(height: 40.0)) + .addToEnd(const SizedBox(height: 40.0)), + ), + ), + ), + ); + } +} diff --git a/lib/backend/api_requests/api_calls.dart b/lib/backend/api_requests/api_calls.dart new file mode 100644 index 00000000..7204e476 --- /dev/null +++ b/lib/backend/api_requests/api_calls.dart @@ -0,0 +1,1467 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; + +import '/flutter_flow/flutter_flow_util.dart'; +import 'api_manager.dart'; + +export 'api_manager.dart' show ApiCallResponse; + +const _kPrivateApiFunctionName = 'ffPrivateApiCall'; + +/// Start PHP Group Code + +class PhpGroup { + static String getBaseUrl() => 'https://freaccess.com.br/freaccess'; + static Map headers = {}; + static LoginCall loginCall = LoginCall(); + static RegisterCall registerCall = RegisterCall(); + static ForgotPasswordCall forgotPasswordCall = ForgotPasswordCall(); + static GetLocalsCall getLocalsCall = GetLocalsCall(); + static PostScheduleVisitorCall postScheduleVisitorCall = + PostScheduleVisitorCall(); + static PostScheduleVisitCall postScheduleVisitCall = PostScheduleVisitCall(); + static DebugCallCall debugCallCall = DebugCallCall(); + static GetScheduleVisitCall getScheduleVisitCall = GetScheduleVisitCall(); + static GetDadosCall getDadosCall = GetDadosCall(); + static GetVisitorByDocCall getVisitorByDocCall = GetVisitorByDocCall(); + static GetFotoVisitanteCall getFotoVisitanteCall = GetFotoVisitanteCall(); + static PostProvVisitSchedulingCall postProvVisitSchedulingCall = + PostProvVisitSchedulingCall(); + static GetVisitsCall getVisitsCall = GetVisitsCall(); + static DeleteVisitCall deleteVisitCall = DeleteVisitCall(); +} + +class LoginCall { + Future call({ + String? email = '', + String? password = '', + String? uuid = '', + String? type = '', + String? description = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'login', + apiUrl: '$baseUrl/login.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'email': email, + 'password': password, + 'uuid': uuid, + 'tipo': type, + 'descricao': description, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? msg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); + List? info(dynamic response) => getJsonField( + response, + r'''$.error_info''', + true, + ) as List?; + String? userUUID(dynamic response) => castToType(getJsonField( + response, + r'''$.uid''', + )); + dynamic userObject(dynamic response) => getJsonField( + response, + r'''$.user''', + ); + String? userName(dynamic response) => castToType(getJsonField( + response, + r'''$.user.name''', + )); + String? userEmail(dynamic response) => castToType(getJsonField( + response, + r'''$.user.email''', + )); + String? userDeviceId(dynamic response) => castToType(getJsonField( + response, + r'''$.user.dev_id''', + )); + String? userCreatAt(dynamic response) => castToType(getJsonField( + response, + r'''$.user.created_at''', + )); + String? userUpdateAt(dynamic response) => castToType(getJsonField( + response, + r'''$.user.updated_at''', + )); + String? userStatus(dynamic response) => castToType(getJsonField( + response, + r'''$.user.status''', + )); +} + +class RegisterCall { + Future call({ + String? name = '', + String? email = '', + String? password = '', + String? token = '', + String? uuid = '', + String? tipo = '', + String? descricao = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'register', + apiUrl: '$baseUrl/registro.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'name': name, + 'email': email, + 'password': password, + 'token': token, + 'uuid': uuid, + 'tipo': tipo, + 'descricao': descricao, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? uid(dynamic response) => castToType(getJsonField( + response, + r'''$.uid''', + )); + dynamic user(dynamic response) => getJsonField( + response, + r'''$.user''', + ); + String? name(dynamic response) => castToType(getJsonField( + response, + r'''$.user.name''', + )); + String? email(dynamic response) => castToType(getJsonField( + response, + r'''$.user.email''', + )); + String? devId(dynamic response) => castToType(getJsonField( + response, + r'''$.user.dev_id''', + )); + String? createdAt(dynamic response) => castToType(getJsonField( + response, + r'''$.user.created_at''', + )); +} + +class ForgotPasswordCall { + Future call({ + String? email = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'forgotPassword', + apiUrl: '$baseUrl/iforgot.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'email': email, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? msg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); +} + +class GetLocalsCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getLocals', + apiUrl: '$baseUrl/getLocais.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + List? locais(dynamic response) => getJsonField( + response, + r'''$.locais''', + true, + ) as List?; + String? cluOwnerID(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLU_OWNER_ID''', + )); + String? cluOwnerDSC(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLU_OWNER_DSC''', + )); + String? cluStatus(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLU_STATUS''', + )); + String? cluBlkMessage(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLU_BLK_MESSAGE''', + )); + String? cliID(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLI_ID''', + )); + String? cliPrefix(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLI_PREFIXO''', + )); + String? cliName(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLI_NOME''', + )); + String? userName(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].USU_NOME''', + )); + String? cliSysId(dynamic response) => castToType(getJsonField( + response, + r'''$.locais[:].CLI_SIS_ID''', + )); +} + +class PostScheduleVisitorCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = 'putVisitante', + String? documento = '', + String? nome = '', + String? tipo = '', + String? foto = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'postScheduleVisitor', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'Documento': documento, + 'Nome': nome, + 'Tipo': tipo, + 'Foto': foto, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? errorMsg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); +} + +class PostScheduleVisitCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? devDesc = '', + String? idVisitante = '', + String? dtInicio = '', + String? dtFim = '', + String? unica = '', + int? idMotivo, + int? idNAC, + String? obs = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'postScheduleVisit', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'idVisitante': idVisitante, + 'dtInicio': dtInicio, + 'dtFim': dtFim, + 'unica': unica, + 'idMotivo': idMotivo, + 'idNAC': idNAC, + 'obs': obs, + 'DevDesc': devDesc, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? errorMsg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); +} + +class DebugCallCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? devDesc = '', + String? idVisitante = '', + String? dtInicio = '', + String? dtFim = '', + String? unica = '', + int? idMotivo, + int? idNAC, + String? obs = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'debugCall', + apiUrl: '$baseUrl/jonh.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'DevDesc': devDesc, + 'idVisitante': idVisitante, + 'dtInicio': dtInicio, + 'dtFim': dtFim, + 'unica': unica, + 'idMotivo': idMotivo, + 'idNAC': idNAC, + 'obs': obs, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? errorMsg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); +} + +class GetScheduleVisitCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliUUID = '', + String? atividade = '', + int? pageSize, + int? pageNumber, + String? chaveBusca = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getScheduleVisit', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliUUID, + 'atividade': atividade, + 'pageSize': pageSize, + 'pageNumber': pageNumber, + 'chaveBusca': chaveBusca, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? errorMsg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); + int? totalRows(dynamic response) => castToType(getJsonField( + response, + r'''$.total_rows''', + )); + List? visitas(dynamic response) => getJsonField( + response, + r'''$.visitas''', + true, + ) as List?; + List? visitaDesNome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].DES_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaMotDescricao(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaMotDia(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_DIA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaMotHorafixa(dynamic response) => getJsonField( + response, + r'''$.visitas[:].MOT_HORAFIXA''', + true, + ) as List?; + List? visitaMotHoras(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_HORAS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaMotMinutos(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_MINUTOS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaMotTipo(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_TIPO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaNacDescricao(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].NAC_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawChave(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_CHAVE''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVarDestino(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DESTINO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawDtCriacao(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTCRIACAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawDtFIm(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTFIM''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawDtInicio(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTINICIO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawId(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_ID''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawObs(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_OBS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawStatus(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_STATUS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVawUnica(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_UNICA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteDocumentos(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_DOCUMENTO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteEmail(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_EMAIL''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteEmpresa(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_EMPRESA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteNome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteTipo(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_TIPO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVteTelefone(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_TELEFONE''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? visitaVdoNome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VDO_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + int? visitaTotalPages(dynamic response) => castToType(getJsonField( + response, + r'''$.total_pages''', + )); + String? page(dynamic response) => castToType(getJsonField( + response, + r'''$.page''', + )); +} + +class GetDadosCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliUUID = '', + String? atividade = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getDados', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliUUID, + 'atividade': atividade, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? errorBolean(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? msgStr(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); + String? visitedDesNomeStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.DES_NOME''', + )); + String? visitedVDOTIdStr(dynamic response) => castToType(getJsonField( + response, + r'''$.visitado.VDO_ID''', + )); + String? visitedVDOTNomeStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_NOME''', + )); + String? visitedVDOTipoStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_TIPO''', + )); + String? visitedVDOImeiStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_IMEI''', + )); + String? visitedVDODocumentoStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_DOCUMENTO''', + )); + String? visitedVDOEmailStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_EMAIL''', + )); + String? visitedVDOStatusWebStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_STATUSWEB''', + )); + List? reasonsMotIdList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_ID''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? reasonsMotDescStrList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? reasonsMotTypeStrList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_TIPO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? reasonsMotWebStrList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_WEB''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + dynamic visitedJson(dynamic response) => getJsonField( + response, + r'''$.visitado''', + ); + String? visitedDescIdStr(dynamic response) => castToType(getJsonField( + response, + r'''$.visitado.DES_ID''', + )); + String? visitedVDoNotTerceirosStr(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitado.VDO_NOTTERCEIROS''', + )); + List? reasonsJsonList(dynamic response) => getJsonField( + response, + r'''$.motivos''', + true, + ) as List?; + List? resonsMotDiaStrList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_DIA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? reasonsMotHorasStrList(dynamic response) => (getJsonField( + response, + r'''$.motivos[:].MOT_HORAS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? reasonsMotMinutosStrList(dynamic response) => getJsonField( + response, + r'''$.motivos[:].MOT_MINUTOS''', + true, + ) as List?; + List? reasonsMotHoraFixaStrList(dynamic response) => getJsonField( + response, + r'''$.motivos[:].MOT_HORAFIXA''', + true, + ) as List?; + List? levelJsonList(dynamic response) => getJsonField( + response, + r'''$.niveis''', + true, + ) as List?; + List? levelNACIdStrList(dynamic response) => (getJsonField( + response, + r'''$.niveis[:].NAC_ID''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACDescricaoStrList(dynamic response) => (getJsonField( + response, + r'''$.niveis[:].NAC_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACHorIdStrList(dynamic response) => (getJsonField( + response, + r'''$.niveis[:].NAC_HOR_ID''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACIndPermiteReentradaStrList(dynamic response) => + (getJsonField( + response, + r'''$.niveis[:].NAC_INDPERMITEREENTRADA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACObservacaoStrList(dynamic response) => (getJsonField( + response, + r'''$.niveis[:].NAC_OBSERVACAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACTempoAntiCaronaStrList(dynamic response) => + (getJsonField( + response, + r'''$.niveis[:].NAC_TEMPOANTICARONA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? levelNACTpUserStrList(dynamic response) => (getJsonField( + response, + r'''$.niveis[:].NAC_TPUSER''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + bool? provisionalBoolean(dynamic response) => castToType(getJsonField( + response, + r'''$.provisional''', + )); + bool? whatsappBoolean(dynamic response) => castToType(getJsonField( + response, + r'''$.whatsapp''', + )); +} + +class GetVisitorByDocCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? documento = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getVisitorByDoc', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'Documento': documento, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? errorMsg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); + dynamic visitante(dynamic response) => getJsonField( + response, + r'''$.visitante''', + ); + String? vistanteId(dynamic response) => castToType(getJsonField( + response, + r'''$.visitante.VTE_ID''', + )); + String? visitanteNome(dynamic response) => castToType(getJsonField( + response, + r'''$.visitante.VTE_NOME''', + )); + String? visitanteRG(dynamic response) => castToType(getJsonField( + response, + r'''$.visitante.VTE_RG''', + )); + String? visitanteDocumento(dynamic response) => + castToType(getJsonField( + response, + r'''$.visitante.VTE_DOCUMENTO''', + )); + String? visitanteTipo(dynamic response) => castToType(getJsonField( + response, + r'''$.visitante.VTE_TIPO''', + )); +} + +class GetFotoVisitanteCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? documento = '', + String? tipo = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getFotoVisitante', + apiUrl: '$baseUrl/getImage.php', + callType: ApiCallType.GET, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'Documento': documento, + 'tipo': tipo, + }, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } +} + +class PostProvVisitSchedulingCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? data = '', + String? motivo = '', + String? nome = '', + String? proID = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'postProvVisitScheduling', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'data': data, + 'motivo': motivo, + 'nome': nome, + 'proID': proID, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + String? msg(dynamic response) => castToType(getJsonField( + response, + r'''$.mensagem''', + )); + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); +} + +class GetVisitsCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'getVisits', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + int? totalRows(dynamic response) => castToType(getJsonField( + response, + r'''$.total_rows''', + )); + List? visitasList(dynamic response) => getJsonField( + response, + r'''$.visitas''', + true, + ) as List?; + List? desNome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].DES_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? motDesc(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? motDia(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_DIA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? motHorafixa(dynamic response) => getJsonField( + response, + r'''$.visitas[:].MOT_HORAFIXA''', + true, + ) as List?; + List? motHoras(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_HORAS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? motMinutos(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_MINUTOS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? motTipo(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].MOT_TIPO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? nACDesc(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].NAC_DESCRICAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWChave(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_CHAVE''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWDestino(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DESTINO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWDTCriacao(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTCRIACAO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWDTFim(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTFIM''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vawdtinicio(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_DTINICIO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWId(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_ID''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWObs(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_OBS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWStatus(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_STATUS''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vAWUnica(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VAW_UNICA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTEDocumento(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_DOCUMENTO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTEEmail(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_EMAIL''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTEEmpresa(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_EMPRESA''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTENome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTETIpo(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_TIPO''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vTETelefone(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VTE_TELEFONE''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); + List? vDONome(dynamic response) => (getJsonField( + response, + r'''$.visitas[:].VDO_NOME''', + true, + ) as List?) + ?.withoutNulls + .map((x) => castToType(x)) + .withoutNulls + .toList(); +} + +class DeleteVisitCall { + Future call({ + String? devUUID = '', + String? userUUID = '', + String? cliID = '', + String? atividade = '', + String? idVisita = '', + }) async { + final baseUrl = PhpGroup.getBaseUrl(); + + return ApiManager.instance.makeApiCall( + callName: 'deleteVisit', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'idVisita': idVisita, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } + + bool? error(dynamic response) => castToType(getJsonField( + response, + r'''$.error''', + )); + String? msg(dynamic response) => castToType(getJsonField( + response, + r'''$.error_msg''', + )); +} + +/// End PHP Group Code + +class ApiPagingParams { + int nextPageNumber = 0; + int numItems = 0; + dynamic lastResponse; + + ApiPagingParams({ + required this.nextPageNumber, + required this.numItems, + required this.lastResponse, + }); + + @override + String toString() => + 'PagingParams(nextPageNumber: $nextPageNumber, numItems: $numItems, lastResponse: $lastResponse,)'; +} + +String _toEncodable(dynamic item) { + return item; +} + +String _serializeList(List? list) { + list ??= []; + try { + return json.encode(list, toEncodable: _toEncodable); + } catch (_) { + if (kDebugMode) { + print("List serialization failed. Returning empty list."); + } + return '[]'; + } +} + +String _serializeJson(dynamic jsonVar, [bool isList = false]) { + jsonVar ??= (isList ? [] : {}); + try { + return json.encode(jsonVar, toEncodable: _toEncodable); + } catch (_) { + if (kDebugMode) { + print("Json serialization failed. Returning empty json."); + } + return isList ? '[]' : '{}'; + } +} diff --git a/lib/backend/api_requests/api_manager.dart b/lib/backend/api_requests/api_manager.dart new file mode 100644 index 00000000..6c3a6d7c --- /dev/null +++ b/lib/backend/api_requests/api_manager.dart @@ -0,0 +1,471 @@ +// ignore_for_file: constant_identifier_names, depend_on_referenced_packages, prefer_final_fields + +import 'dart:convert'; +import 'dart:core'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:collection/collection.dart'; +import 'package:http/http.dart' as http; +import 'package:equatable/equatable.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:mime_type/mime_type.dart'; + +import '/flutter_flow/uploaded_file.dart'; + +enum ApiCallType { + GET, + POST, + DELETE, + PUT, + PATCH, +} + +enum BodyType { + NONE, + JSON, + TEXT, + X_WWW_FORM_URL_ENCODED, + MULTIPART, +} + +class ApiCallOptions extends Equatable { + const ApiCallOptions({ + this.callName = '', + required this.callType, + required this.apiUrl, + required this.headers, + required this.params, + this.bodyType, + this.body, + this.returnBody = true, + this.encodeBodyUtf8 = false, + this.decodeUtf8 = false, + this.alwaysAllowBody = false, + this.cache = false, + }); + + final String callName; + final ApiCallType callType; + final String apiUrl; + final Map headers; + final Map params; + final BodyType? bodyType; + final String? body; + final bool returnBody; + final bool encodeBodyUtf8; + final bool decodeUtf8; + final bool alwaysAllowBody; + final bool cache; + + ApiCallOptions clone() => ApiCallOptions( + callName: callName, + callType: callType, + apiUrl: apiUrl, + headers: _cloneMap(headers), + params: _cloneMap(params), + bodyType: bodyType, + body: body, + returnBody: returnBody, + encodeBodyUtf8: encodeBodyUtf8, + decodeUtf8: decodeUtf8, + alwaysAllowBody: alwaysAllowBody, + cache: cache, + ); + + @override + List get props => [ + callName, + callType.name, + apiUrl, + headers, + params, + bodyType, + body, + returnBody, + encodeBodyUtf8, + decodeUtf8, + alwaysAllowBody, + cache, + ]; + + static Map _cloneMap(Map map) { + try { + return json.decode(json.encode(map)) as Map; + } catch (_) { + return Map.from(map); + } + } +} + +class ApiCallResponse { + const ApiCallResponse( + this.jsonBody, + this.headers, + this.statusCode, { + this.response, + this.exception, + }); + final dynamic jsonBody; + final Map headers; + final int statusCode; + final http.Response? response; + final Object? exception; + // Whether we received a 2xx status (which generally marks success). + bool get succeeded => statusCode >= 200 && statusCode < 300; + String getHeader(String headerName) => headers[headerName] ?? ''; + // Return the raw body from the response, or if this came from a cloud call + // and the body is not a string, then the json encoded body. + String get bodyText => + response?.body ?? + (jsonBody is String ? jsonBody as String : jsonEncode(jsonBody)); + String get exceptionMessage => exception.toString(); + + static ApiCallResponse fromHttpResponse( + http.Response response, + bool returnBody, + bool decodeUtf8, + ) { + dynamic jsonBody; + try { + final responseBody = decodeUtf8 && returnBody + ? const Utf8Decoder().convert(response.bodyBytes) + : response.body; + jsonBody = returnBody ? json.decode(responseBody) : null; + } catch (_) {} + return ApiCallResponse( + jsonBody, + response.headers, + response.statusCode, + response: response, + ); + } + + static ApiCallResponse fromCloudCallResponse(Map response) => + ApiCallResponse( + response['body'], + ApiManager.toStringMap(response['headers'] ?? {}), + response['statusCode'] ?? 400, + ); +} + +class ApiManager { + ApiManager._(); + + // Cache that will ensure identical calls are not repeatedly made. + static Map _apiCache = {}; + + static ApiManager? _instance; + static ApiManager get instance => _instance ??= ApiManager._(); + + // If your API calls need authentication, populate this field once + // the user has authenticated. Alter this as needed. + static String? _accessToken; + + // You may want to call this if, for example, you make a change to the + // database and no longer want the cached result of a call that may + // have changed. + static void clearCache(String callName) => _apiCache.keys + .toSet() + .forEach((k) => k.callName == callName ? _apiCache.remove(k) : null); + + static Map toStringMap(Map map) => + map.map((key, value) => MapEntry(key.toString(), value.toString())); + + static String asQueryParams(Map map) => map.entries + .map((e) => + "${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value.toString())}") + .join('&'); + + static Future urlRequest( + ApiCallType callType, + String apiUrl, + Map headers, + Map params, + bool returnBody, + bool decodeUtf8, { + http.Client? client, + }) async { + if (params.isNotEmpty) { + final specifier = + Uri.parse(apiUrl).queryParameters.isNotEmpty ? '&' : '?'; + apiUrl = '$apiUrl$specifier${asQueryParams(params)}'; + } + final makeRequest = callType == ApiCallType.GET + ? (client != null ? client.get : http.get) + : (client != null ? client.delete : http.delete); + final response = + await makeRequest(Uri.parse(apiUrl), headers: toStringMap(headers)); + return ApiCallResponse.fromHttpResponse(response, returnBody, decodeUtf8); + } + + static Future requestWithBody( + ApiCallType type, + String apiUrl, + Map headers, + Map params, + String? body, + BodyType? bodyType, + bool returnBody, + bool encodeBodyUtf8, + bool decodeUtf8, + bool alwaysAllowBody, { + http.Client? client, + }) async { + assert( + {ApiCallType.POST, ApiCallType.PUT, ApiCallType.PATCH}.contains(type) || + (alwaysAllowBody && type == ApiCallType.DELETE), + 'Invalid ApiCallType $type for request with body', + ); + final postBody = + createBody(headers, params, body, bodyType, encodeBodyUtf8); + + if (bodyType == BodyType.MULTIPART) { + return multipartRequest(type, apiUrl, headers, params, returnBody, + decodeUtf8, alwaysAllowBody); + } + + final requestFn = { + ApiCallType.POST: client != null ? client.post : http.post, + ApiCallType.PUT: client != null ? client.put : http.put, + ApiCallType.PATCH: client != null ? client.patch : http.patch, + ApiCallType.DELETE: client != null ? client.delete : http.delete, + }[type]!; + final response = await requestFn(Uri.parse(apiUrl), + headers: toStringMap(headers), body: postBody); + return ApiCallResponse.fromHttpResponse(response, returnBody, decodeUtf8); + } + + static Future multipartRequest( + ApiCallType? type, + String apiUrl, + Map headers, + Map params, + bool returnBody, + bool decodeUtf8, + bool alwaysAllowBody, + ) async { + assert( + {ApiCallType.POST, ApiCallType.PUT, ApiCallType.PATCH}.contains(type) || + (alwaysAllowBody && type == ApiCallType.DELETE), + 'Invalid ApiCallType $type for request with body', + ); + + bool isFile(dynamic e) => + e is FFUploadedFile || + e is List || + (e is List && e.firstOrNull is FFUploadedFile); + + final nonFileParams = toStringMap( + Map.fromEntries(params.entries.where((e) => !isFile(e.value)))); + + List files = []; + params.entries.where((e) => isFile(e.value)).forEach((e) { + final param = e.value; + final uploadedFiles = param is List + ? param as List + : [param as FFUploadedFile]; + for (var uploadedFile in uploadedFiles) { + files.add( + http.MultipartFile.fromBytes( + e.key, + uploadedFile.bytes ?? Uint8List.fromList([]), + filename: uploadedFile.name, + contentType: _getMediaType(uploadedFile.name), + ), + ); + } + }); + + final request = http.MultipartRequest( + type.toString().split('.').last, Uri.parse(apiUrl)) + ..headers.addAll(toStringMap(headers)) + ..files.addAll(files); + nonFileParams.forEach((key, value) => request.fields[key] = value); + + final response = await http.Response.fromStream(await request.send()); + return ApiCallResponse.fromHttpResponse(response, returnBody, decodeUtf8); + } + + static MediaType? _getMediaType(String? filename) { + final contentType = mime(filename); + if (contentType == null) { + return null; + } + final parts = contentType.split('/'); + if (parts.length != 2) { + return null; + } + return MediaType(parts.first, parts.last); + } + + static dynamic createBody( + Map headers, + Map? params, + String? body, + BodyType? bodyType, + bool encodeBodyUtf8, + ) { + String? contentType; + dynamic postBody; + switch (bodyType) { + case BodyType.JSON: + contentType = 'application/json'; + postBody = body ?? json.encode(params ?? {}); + break; + case BodyType.TEXT: + contentType = 'text/plain'; + postBody = body ?? json.encode(params ?? {}); + break; + case BodyType.X_WWW_FORM_URL_ENCODED: + contentType = 'application/x-www-form-urlencoded'; + postBody = toStringMap(params ?? {}); + break; + case BodyType.MULTIPART: + contentType = 'multipart/form-data'; + postBody = params; + break; + case BodyType.NONE: + case null: + break; + } + // Set "Content-Type" header if it was previously unset. + if (contentType != null && + !headers.keys.any((h) => h.toLowerCase() == 'content-type')) { + headers['Content-Type'] = contentType; + } + return encodeBodyUtf8 && postBody is String + ? utf8.encode(postBody) + : postBody; + } + + Future call(ApiCallOptions options) => makeApiCall( + callName: options.callName, + apiUrl: options.apiUrl, + callType: options.callType, + headers: options.headers, + params: options.params, + body: options.body, + bodyType: options.bodyType, + returnBody: options.returnBody, + encodeBodyUtf8: options.encodeBodyUtf8, + decodeUtf8: options.decodeUtf8, + alwaysAllowBody: options.alwaysAllowBody, + cache: options.cache, + options: options, + ); + + Future makeApiCall({ + required String callName, + required String apiUrl, + required ApiCallType callType, + Map headers = const {}, + Map params = const {}, + String? body, + BodyType? bodyType, + bool returnBody = true, + bool encodeBodyUtf8 = false, + bool decodeUtf8 = false, + bool alwaysAllowBody = false, + bool cache = false, + ApiCallOptions? options, + http.Client? client, + }) async { + final callOptions = options ?? + ApiCallOptions( + callName: callName, + callType: callType, + apiUrl: apiUrl, + headers: headers, + params: params, + bodyType: bodyType, + body: body, + returnBody: returnBody, + encodeBodyUtf8: encodeBodyUtf8, + decodeUtf8: decodeUtf8, + alwaysAllowBody: alwaysAllowBody, + cache: cache, + ); + // Modify for your specific needs if this differs from your API. + if (_accessToken != null) { + headers[HttpHeaders.authorizationHeader] = 'Bearer $_accessToken'; + } + if (!apiUrl.startsWith('http')) { + apiUrl = 'https://$apiUrl'; + } + + // If we've already made this exact call before and caching is on, + // return the cached result. + if (cache && _apiCache.containsKey(callOptions)) { + return _apiCache[callOptions]!; + } + + ApiCallResponse result; + try { + switch (callType) { + case ApiCallType.GET: + result = await urlRequest( + callType, + apiUrl, + headers, + params, + returnBody, + decodeUtf8, + client: client, + ); + break; + case ApiCallType.DELETE: + result = alwaysAllowBody + ? await requestWithBody( + callType, + apiUrl, + headers, + params, + body, + bodyType, + returnBody, + encodeBodyUtf8, + decodeUtf8, + alwaysAllowBody, + client: client, + ) + : await urlRequest( + callType, + apiUrl, + headers, + params, + returnBody, + decodeUtf8, + client: client, + ); + break; + case ApiCallType.POST: + case ApiCallType.PUT: + case ApiCallType.PATCH: + result = await requestWithBody( + callType, + apiUrl, + headers, + params, + body, + bodyType, + returnBody, + encodeBodyUtf8, + decodeUtf8, + alwaysAllowBody, + client: client, + ); + break; + } + + // If caching is on, cache the result (if present). + if (cache) { + _apiCache[callOptions] = result; + } + } catch (e) { + result = ApiCallResponse(null, {}, -1, exception: e); + } + + return result; + } +} diff --git a/lib/backend/schema/enums/enums.dart b/lib/backend/schema/enums/enums.dart new file mode 100644 index 00000000..cfef83fe --- /dev/null +++ b/lib/backend/schema/enums/enums.dart @@ -0,0 +1,24 @@ +import 'package:collection/collection.dart'; + +enum AppHeaderComponent { + menu, + home, +} + +extension FFEnumExtensions on T { + String serialize() => name; +} + +extension FFEnumListExtensions on Iterable { + T? deserialize(String? value) => + firstWhereOrNull((e) => e.serialize() == value); +} + +T? deserializeEnum(String? value) { + switch (T) { + case (AppHeaderComponent): + return AppHeaderComponent.values.deserialize(value) as T?; + default: + return null; + } +} diff --git a/lib/backend/schema/structs/action_struct.dart b/lib/backend/schema/structs/action_struct.dart new file mode 100644 index 00000000..8bdb04c8 --- /dev/null +++ b/lib/backend/schema/structs/action_struct.dart @@ -0,0 +1,85 @@ +// ignore_for_file: unnecessary_getters_setters + +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class ActionStruct extends BaseStruct { + ActionStruct({ + String? title, + String? icon, + }) : _title = title, + _icon = icon; + + // "title" field. + String? _title; + String get title => _title ?? ''; + set title(String? val) => _title = val; + bool hasTitle() => _title != null; + + // "icon" field. + String? _icon; + String get icon => _icon ?? ''; + set icon(String? val) => _icon = val; + bool hasIcon() => _icon != null; + + static ActionStruct fromMap(Map data) => ActionStruct( + title: data['title'] as String?, + icon: data['icon'] as String?, + ); + + static ActionStruct? maybeFromMap(dynamic data) => + data is Map ? ActionStruct.fromMap(data.cast()) : null; + + Map toMap() => { + 'title': _title, + 'icon': _icon, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'title': serializeParam( + _title, + ParamType.String, + ), + 'icon': serializeParam( + _icon, + ParamType.String, + ), + }.withoutNulls; + + static ActionStruct fromSerializableMap(Map data) => + ActionStruct( + title: deserializeParam( + data['title'], + ParamType.String, + false, + ), + icon: deserializeParam( + data['icon'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'ActionStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is ActionStruct && title == other.title && icon == other.icon; + } + + @override + int get hashCode => const ListEquality().hash([title, icon]); +} + +ActionStruct createActionStruct({ + String? title, + String? icon, +}) => + ActionStruct( + title: title, + icon: icon, + ); diff --git a/lib/backend/schema/structs/device_struct.dart b/lib/backend/schema/structs/device_struct.dart new file mode 100644 index 00000000..03db22f3 --- /dev/null +++ b/lib/backend/schema/structs/device_struct.dart @@ -0,0 +1,110 @@ +// ignore_for_file: unnecessary_getters_setters + +import '/backend/schema/util/schema_util.dart'; + +import 'index.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +class DeviceStruct extends BaseStruct { + DeviceStruct({ + String? devUUID, + String? version, + String? description, + }) : _devUUID = devUUID, + _version = version, + _description = description; + + // "devUUID" field. + String? _devUUID; + String get devUUID => _devUUID ?? ''; + set devUUID(String? val) => _devUUID = val; + bool hasDevUUID() => _devUUID != null; + + // "version" field. + String? _version; + String get version => _version ?? ''; + set version(String? val) => _version = val; + bool hasVersion() => _version != null; + + // "description" field. + String? _description; + String get description => _description ?? ''; + set description(String? val) => _description = val; + bool hasDescription() => _description != null; + + static DeviceStruct fromMap(Map data) => DeviceStruct( + devUUID: data['devUUID'] as String?, + version: data['version'] as String?, + description: data['description'] as String?, + ); + + static DeviceStruct? maybeFromMap(dynamic data) => + data is Map ? DeviceStruct.fromMap(data.cast()) : null; + + Map toMap() => { + 'devUUID': _devUUID, + 'version': _version, + 'description': _description, + }.withoutNulls; + + @override + Map toSerializableMap() => { + 'devUUID': serializeParam( + _devUUID, + ParamType.String, + ), + 'version': serializeParam( + _version, + ParamType.String, + ), + 'description': serializeParam( + _description, + ParamType.String, + ), + }.withoutNulls; + + static DeviceStruct fromSerializableMap(Map data) => + DeviceStruct( + devUUID: deserializeParam( + data['devUUID'], + ParamType.String, + false, + ), + version: deserializeParam( + data['version'], + ParamType.String, + false, + ), + description: deserializeParam( + data['description'], + ParamType.String, + false, + ), + ); + + @override + String toString() => 'DeviceStruct(${toMap()})'; + + @override + bool operator ==(Object other) { + return other is DeviceStruct && + devUUID == other.devUUID && + version == other.version && + description == other.description; + } + + @override + int get hashCode => + const ListEquality().hash([devUUID, version, description]); +} + +DeviceStruct createDeviceStruct({ + String? devUUID, + String? version, + String? description, +}) => + DeviceStruct( + devUUID: devUUID, + version: version, + description: description, + ); diff --git a/lib/backend/schema/structs/index.dart b/lib/backend/schema/structs/index.dart new file mode 100644 index 00000000..0c01c05d --- /dev/null +++ b/lib/backend/schema/structs/index.dart @@ -0,0 +1,4 @@ +export '/backend/schema/util/schema_util.dart'; + +export 'action_struct.dart'; +export 'device_struct.dart'; diff --git a/lib/backend/schema/util/schema_util.dart b/lib/backend/schema/util/schema_util.dart new file mode 100644 index 00000000..a074ea89 --- /dev/null +++ b/lib/backend/schema/util/schema_util.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:from_css_color/from_css_color.dart'; + +import '/backend/schema/enums/enums.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +export 'package:collection/collection.dart' show ListEquality; +export 'package:flutter/material.dart' show Color, Colors; +export 'package:from_css_color/from_css_color.dart'; + +typedef StructBuilder = T Function(Map data); + +abstract class BaseStruct { + Map toSerializableMap(); + String serialize() => json.encode(toSerializableMap()); +} + +dynamic deserializeStructParam( + dynamic param, + ParamType paramType, + bool isList, { + required StructBuilder structBuilder, +}) { + if (param == null) { + return null; + } else if (isList) { + final paramValues; + try { + paramValues = param is Iterable ? param : json.decode(param); + } catch (e) { + return null; + } + if (paramValues is! Iterable) { + return null; + } + return paramValues + .map((e) => deserializeStructParam(e, paramType, false, + structBuilder: structBuilder)) + .toList(); + } else if (param is Map) { + return structBuilder(param); + } else { + return deserializeParam( + param, + paramType, + isList, + structBuilder: structBuilder, + ); + } +} + +List? getStructList( + dynamic value, + StructBuilder structBuilder, +) => + value is! List + ? null + : value + .whereType>() + .map((e) => structBuilder(e)) + .toList(); + +List? getEnumList(dynamic value) => value is! List + ? null + : value.map((e) => deserializeEnum(e)).withoutNulls; + +Color? getSchemaColor(dynamic value) => value is String + ? fromCssColor(value) + : value is Color + ? value + : null; + +List? getColorsList(dynamic value) => + value is! List ? null : value.map(getSchemaColor).withoutNulls; + +List? getDataList(dynamic value) => + value is! List ? null : value.map((e) => castToType(e)!).toList(); + +extension MapDataExtensions on Map { + Map get withoutNulls => Map.fromEntries( + entries + .where((e) => e.value != null) + .map((e) => MapEntry(e.key, e.value!)), + ); +} diff --git a/lib/components/image_cropper_model.dart b/lib/components/image_cropper_model.dart new file mode 100644 index 00000000..3d5fedec --- /dev/null +++ b/lib/components/image_cropper_model.dart @@ -0,0 +1,11 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'image_cropper_widget.dart' show ImageCropperWidget; +import 'package:flutter/material.dart'; + +class ImageCropperModel extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/components/image_cropper_widget.dart b/lib/components/image_cropper_widget.dart new file mode 100644 index 00000000..90467078 --- /dev/null +++ b/lib/components/image_cropper_widget.dart @@ -0,0 +1,64 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/widgets/index.dart' as custom_widgets; +import 'package:flutter/material.dart'; +import 'image_cropper_model.dart'; +export 'image_cropper_model.dart'; + +class ImageCropperWidget extends StatefulWidget { + const ImageCropperWidget({ + super.key, + required this.uploadImageFile, + }); + + final FFUploadedFile? uploadImageFile; + + @override + State createState() => _ImageCropperWidgetState(); +} + +class _ImageCropperWidgetState extends State { + late ImageCropperModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ImageCropperModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: 500.0, + height: 500.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + ), + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: custom_widgets.ImageCropper( + width: double.infinity, + height: double.infinity, + imageFile: widget.uploadImageFile, + callBackAction: (url) async { + Navigator.pop(context, url); + }, + ), + ), + ); + } +} diff --git a/lib/components/legacy_local_component_model.dart b/lib/components/legacy_local_component_model.dart new file mode 100644 index 00000000..65087833 --- /dev/null +++ b/lib/components/legacy_local_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'legacy_local_component_widget.dart' show LegacyLocalComponentWidget; +import 'package:flutter/material.dart'; + +class LegacyLocalComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/components/legacy_local_component_widget.dart b/lib/components/legacy_local_component_widget.dart new file mode 100644 index 00000000..54c3610d --- /dev/null +++ b/lib/components/legacy_local_component_widget.dart @@ -0,0 +1,167 @@ +import '/application_components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/custom_functions.dart' as functions; +import '/flutter_flow/random_data_util.dart' as random_data; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'legacy_local_component_model.dart'; +export 'legacy_local_component_model.dart'; + +class LegacyLocalComponentWidget extends StatefulWidget { + const LegacyLocalComponentWidget({super.key}); + + @override + State createState() => + _LegacyLocalComponentWidgetState(); +} + +class _LegacyLocalComponentWidgetState + extends State { + late LegacyLocalComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => LegacyLocalComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Visibility( + visible: random_data.randomInteger(0, 10) != null, + child: Container( + height: 284.0, + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Material( + color: Colors.transparent, + elevation: 0.0, + child: Container( + width: double.infinity, + height: 119.0, + decoration: BoxDecoration( + color: const Color(0xFF1AAB5F), + border: Border.all( + color: const Color(0xFF1AAB5F), + ), + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Container( + width: 200.0, + height: 200.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + shape: BoxShape.circle, + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(2.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + showModalBottomSheet( + isScrollControlled: true, + backgroundColor: const Color(0x00FFFFFF), + context: context, + builder: (context) { + return Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const SizedBox( + height: double.infinity, + child: + BottomArrowLinkedLocalsComponentWidget(), + ), + ); + }, + ).then((value) => safeSetState(() {})); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(200.0), + child: Image.network( + valueOrDefault( + 'https://freaccess.com.br/freaccess/Images/Clients/${FFAppState().cliUUID}.png', + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', + ), + width: 300.0, + height: 200.0, + fit: BoxFit.cover, + alignment: const Alignment(0.0, 0.0), + errorBuilder: (context, error, stackTrace) => + Image.asset( + 'assets/images/error_image.svg', + width: 300.0, + height: 200.0, + fit: BoxFit.cover, + alignment: const Alignment(0.0, 0.0), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + valueOrDefault( + functions.convertToUppercase(FFAppState().local), + 'NOME DO LOCAL', + ), + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 20.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/components/select_header_component_model.dart b/lib/components/select_header_component_model.dart new file mode 100644 index 00000000..4c60514f --- /dev/null +++ b/lib/components/select_header_component_model.dart @@ -0,0 +1,12 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'select_header_component_widget.dart' show SelectHeaderComponentWidget; +import 'package:flutter/material.dart'; + +class SelectHeaderComponentModel + extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/components/select_header_component_widget.dart b/lib/components/select_header_component_widget.dart new file mode 100644 index 00000000..8f4f9339 --- /dev/null +++ b/lib/components/select_header_component_widget.dart @@ -0,0 +1,185 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'select_header_component_model.dart'; +export 'select_header_component_model.dart'; + +class SelectHeaderComponentWidget extends StatefulWidget { + const SelectHeaderComponentWidget({ + super.key, + required this.selectToggle, + bool? toggleIndexValue, + }) : toggleIndexValue = toggleIndexValue ?? true; + + final Future Function(bool toggleIndex)? selectToggle; + final bool toggleIndexValue; + + @override + State createState() => + _SelectHeaderComponentWidgetState(); +} + +class _SelectHeaderComponentWidgetState + extends State { + late SelectHeaderComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => SelectHeaderComponentModel()); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + height: 55.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.selectToggle?.call( + true, + ); + }, + child: Container( + width: double.infinity, + height: 50.0, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + '1gr8ztd5' /* Criar Agendamento */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + if (widget.toggleIndexValue == true) + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 2.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: 2.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: BorderRadius.circular(100.0), + ), + ), + ), + ], + ), + ), + ), + Expanded( + child: Container( + height: 55.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget.selectToggle?.call( + false, + ); + }, + child: Container( + width: double.infinity, + height: 50.0, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(0.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(0.0), + topRight: Radius.circular(0.0), + ), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'xjahsbjw' /* Histórico de Visitas */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + if (widget.toggleIndexValue == false) + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 2.0, 0.0, 0.0), + child: Container( + width: double.infinity, + height: 2.0, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primary, + borderRadius: BorderRadius.circular(100.0), + ), + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/custom_code/actions/convert_image_file_to_base64.dart b/lib/custom_code/actions/convert_image_file_to_base64.dart new file mode 100644 index 00000000..595a0468 --- /dev/null +++ b/lib/custom_code/actions/convert_image_file_to_base64.dart @@ -0,0 +1,22 @@ +// Automatic FlutterFlow imports +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; +import '/actions/actions.dart' as action_blocks; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom actions +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom action code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'dart:convert'; +import 'dart:typed_data'; + +Future convertImageFileToBase64(FFUploadedFile imageFile) async { + List? imageBytes = imageFile.bytes; + if (imageBytes != null) { + String base64Image = base64Encode(imageBytes); + return base64Image; + } +} diff --git a/lib/custom_code/actions/convert_to_upload_file.dart b/lib/custom_code/actions/convert_to_upload_file.dart new file mode 100644 index 00000000..da9e3dae --- /dev/null +++ b/lib/custom_code/actions/convert_to_upload_file.dart @@ -0,0 +1,32 @@ +// Automatic FlutterFlow imports +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; +import '/actions/actions.dart' as action_blocks; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom actions +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom action code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'dart:convert'; // Import for base64 decoding +import 'dart:io'; // Import for file operations +import 'package:path_provider/path_provider.dart'; // Import for temporary directory + +Future convertToUploadFile(String img) async { + // Decode the base64 string into bytes + Uint8List bytes = base64.decode(img); + + // Create a temporary file to store the image + final tempDir = await getTemporaryDirectory(); + final tempPath = tempDir.path; + final tempFile = await File('$tempPath/image.jpg').create(); + await tempFile.writeAsBytes(bytes); + + // Create an FFUploadedFile object using the temporary file + return FFUploadedFile( + bytes: bytes, + name: 'image.jpg', + ); +} diff --git a/lib/custom_code/actions/get_dev_u_u_i_d.dart b/lib/custom_code/actions/get_dev_u_u_i_d.dart new file mode 100644 index 00000000..6d4843e7 --- /dev/null +++ b/lib/custom_code/actions/get_dev_u_u_i_d.dart @@ -0,0 +1,28 @@ +// Automatic FlutterFlow imports +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; +import '/actions/actions.dart' as action_blocks; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom actions +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom action code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; + +Future getDevUUID() async { + var deviceInfo = DeviceInfoPlugin(); + if (Platform.isIOS) { + // import 'dart:io' + var iosDeviceInfo = await deviceInfo.iosInfo; + return iosDeviceInfo.identifierForVendor; // unique ID on iOS + } else if (Platform.isAndroid) { + var androidDeviceInfo = await deviceInfo.androidInfo; + print(AndroidDeviceInfo); + return androidDeviceInfo.serialNumber; // unique ID on Android + } +} diff --git a/lib/custom_code/actions/index.dart b/lib/custom_code/actions/index.dart new file mode 100644 index 00000000..2110f043 --- /dev/null +++ b/lib/custom_code/actions/index.dart @@ -0,0 +1,3 @@ +export 'convert_image_file_to_base64.dart' show convertImageFileToBase64; +export 'convert_to_upload_file.dart' show convertToUploadFile; +export 'get_dev_u_u_i_d.dart' show getDevUUID; diff --git a/lib/custom_code/widgets/image_cropper.dart b/lib/custom_code/widgets/image_cropper.dart new file mode 100644 index 00000000..459c718b --- /dev/null +++ b/lib/custom_code/widgets/image_cropper.dart @@ -0,0 +1,179 @@ +// Automatic FlutterFlow imports +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; +import '/actions/actions.dart' as action_blocks; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'index.dart'; // Imports other custom widgets +import '/custom_code/actions/index.dart'; // Imports custom actions +import '/flutter_flow/custom_functions.dart'; // Imports custom functions +import 'package:flutter/material.dart'; +// Begin custom widget code +// DO NOT REMOVE OR MODIFY THE CODE ABOVE! + +import 'package:crop_your_image/crop_your_image.dart'; +import 'package:google_fonts/google_fonts.dart'; +import '/backend/firebase_storage/storage.dart'; + +class ImageCropper extends StatefulWidget { + const ImageCropper({ + super.key, + this.width, + this.height, + this.imageFile, + this.callBackAction, + this.currentUserId, + }); + + final double? width; + final double? height; + final FFUploadedFile? imageFile; + final Future Function(String? url)? callBackAction; + final String? currentUserId; + + @override + State createState() => _ImageCropperState(); +} + +class _ImageCropperState extends State { + bool loading = false; + final _crop_controller = CropController(); + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: widget.width ?? double.infinity, + height: (widget.height ?? 555) - 80, + child: Center( + child: Crop( + image: Uint8List.fromList(widget.imageFile!.bytes!), + controller: _crop_controller, + onCropped: (image) async { + final path = _getStoragePath(_firebasePathPrefix(), + widget.imageFile!.name!, false, 0); + uploadData(path, image).then((value) { + print('image cropped'); + widget.callBackAction!.call(value!); + loading = false; + }); + // add error handling here + }, + + aspectRatio: 1 / 1, + initialSize: 0.5, + // initialArea: Rect.fromLTWH(240, 212, 800, 600),\ + //initialAreaBuilder: (rect) => Rect.fromLTRB(rect.left + 80, rect.top + 80, rect.right - 80, rect.bottom - 80), + withCircleUi: true, + baseColor: Color.fromARGB(255, 0, 3, 22), + maskColor: Colors.white.withAlpha(100), + radius: 20, + + onMoved: (newRect) { + // do something with current cropping area. + }, + onStatusChanged: (status) { + // do something with current CropStatus + }, + cornerDotBuilder: (size, edgeAlignment) => + const DotControl(color: Colors.white), + interactive: true, + // fixArea: true, + ))), + Padding( + padding: EdgeInsetsDirectional.fromSTEB(8, 5, 8, 5), + child: ElevatedButton( + onPressed: () async { + if (!loading) { + setState(() { + loading = true; + }); + print('Button pressed ...'); + _crop_controller.crop(); + + //widget.loading = true; + } + }, + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + FlutterFlowTheme.of(context).primaryColor, + ), + padding: MaterialStateProperty.all( + EdgeInsets.zero, + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), + side: BorderSide.none, + ), + ), + ), + child: Container( + width: 250, + height: 50, + alignment: Alignment.center, + child: loading + ? CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation(Colors.white), + ) + : Text( + 'Crop', + style: FlutterFlowTheme.of(context) + .subtitle2 + .override( + fontFamily: 'Lexend', + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.normal, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .subtitle2Family), + ), + ), + ), + )), + ]), + Positioned( + top: 4, + right: 4, + child: IconButton( + icon: Icon(Icons.close), + onPressed: () => Navigator.pop(context), + )) + ], + ); + } + + String _getStoragePath( + String? pathPrefix, + String filePath, + bool isVideo, [ + int? index, + ]) { + pathPrefix ??= _firebasePathPrefix(); + pathPrefix = _removeTrailingSlash(pathPrefix); + final timestamp = DateTime.now().microsecondsSinceEpoch; + final prefix = 'cropped-'; + // Workaround fixed by https://github.com/flutter/plugins/pull/3685 + // (not yet in stable). + final ext = isVideo ? 'mp4' : filePath.split('.').last; + final indexStr = index != null ? '_$index' : ''; + return '$pathPrefix/$prefix$timestamp$indexStr.$ext'; + } + + String? _removeTrailingSlash(String? path) => + path != null && path.endsWith('/') + ? path.substring(0, path.length - 1) + : path; + + String _firebasePathPrefix() => 'users/${widget.currentUserId}/uploads'; +} +// Set your widget name, define your parameter, and then add the +// boilerplate code using the green button on the right! diff --git a/lib/custom_code/widgets/index.dart b/lib/custom_code/widgets/index.dart new file mode 100644 index 00000000..ec35fd3e --- /dev/null +++ b/lib/custom_code/widgets/index.dart @@ -0,0 +1 @@ +export 'image_cropper.dart' show ImageCropper; diff --git a/lib/flutter_flow/custom_functions.dart b/lib/flutter_flow/custom_functions.dart new file mode 100644 index 00000000..2aaa5566 --- /dev/null +++ b/lib/flutter_flow/custom_functions.dart @@ -0,0 +1,107 @@ +import 'dart:convert'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:timeago/timeago.dart' as timeago; +import 'lat_lng.dart'; +import 'place.dart'; +import 'uploaded_file.dart'; +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; + +String? isOneAcliID(String jsonString) { + // Converte o JSON em um Map + final Map data = jsonDecode(jsonString); + + // Extrai a lista de locais + final List locais = data['locais']; + + // Filtra os locais onde CLU_STATUS é igual a "A" + final List locaisAtivos = + locais.where((local) => local['CLU_STATUS'] == 'A').toList(); + + // Verifica se existe somente um local ativo + if (locaisAtivos.length == 1) { + return locaisAtivos.first['CLI_ID']; + } else { + return null; + } +} + +String? convertToUppercase(String input) { + // recebe uuma string qualquer e retorna ela em uppercase + return input.toUpperCase(); +} + +String? uploadFileToBase64(String? uploadFile) { + // takes an UploadFile of an image as an argument and returns a base64 string of that image + if (uploadFile == null) { + return null; + } + + // Converte a string em uma lista de inteiros + final List bytes = uploadFile.codeUnits; + + // Converte os bytes em uma string base64 + final String base64String = base64.encode(bytes); + + return base64String; +} + +String jsonListToStr(List visitorList) { + // rece um json list e retorna uma string de $.visitante.VTE_DOCUMENTO separado por virgula + String result = ''; + for (var visitor in visitorList) { + result += '${visitor['VTE_DOCUMENTO']},'; + } + return result.substring(0, result.length - 1); +} + +List listStrJsonToJsonList( + dynamic jsonList, + List strList, +) { + // Recebe um jsonList e uma stringList como argumento e retorna uma nova jsonList associando cada item + List result = []; + + for (int i = 0; i < jsonList.length; i++) { + Map item = jsonList[i]; + if (i < strList.length) { + item['newField'] = strList[i]; + } else { + item['newField'] = ''; + } + result.add(item); + } + + return result; +} + +String strListToStr(List strList) { + // recebe uma stringList como argumento e retorna uma str com cada item da strList separado por virgula + + return strList.join(','); +} + +int extractIdToStr(String str) { + // recebe um uma string e retorna um inteiro com o valor entre '_ID:' e a próxima vírgula ',' + final idStart = str.indexOf('_ID:') + 4; + final idEnd = str.indexOf(',', idStart); + final idStr = str.substring(idStart, idEnd); + return int.parse(idStr); +} + +String extractDescToStr(String str) { + // recebe um uma string e retorna uma string com o valor entre '_DESCRICAO' e a próxima vírgula ',' + final startIndex = str.indexOf('_DESCRICAO:') + '_DESCRICAO:'.length; + final endIndex = str.indexOf(',', startIndex); + return str.substring(startIndex, endIndex); +} + +String jsonToStr(dynamic json) { + // recebe um json como parametro, converte-o em string e retorna essa string + String jsonString = jsonEncode(json); + return jsonString; +} diff --git a/lib/flutter_flow/custom_icons.dart b/lib/flutter_flow/custom_icons.dart new file mode 100644 index 00000000..52991086 --- /dev/null +++ b/lib/flutter_flow/custom_icons.dart @@ -0,0 +1,21 @@ +import 'package:flutter/widgets.dart'; + +class FFIcons { + FFIcons._(); + + static const String _iconsFamily = 'Icons'; + static const String _menuFamily = 'Menu'; + + // icons + static const IconData kvector = IconData(0xe900, fontFamily: _iconsFamily); + static const IconData kfast = IconData(0xe903, fontFamily: _iconsFamily); + static const IconData khome = IconData(0xe904, fontFamily: _iconsFamily); + static const IconData kpets = IconData(0xe901, fontFamily: _iconsFamily); + static const IconData kvector1 = IconData(0xe902, fontFamily: _iconsFamily); + + // menu + static const IconData kiconFastPass = + IconData(0xe900, fontFamily: _menuFamily); + static const IconData kvector2 = IconData(0xe905, fontFamily: _menuFamily); + static const IconData kvector3 = IconData(0xe906, fontFamily: _menuFamily); +} diff --git a/lib/flutter_flow/flutter_flow_animations.dart b/lib/flutter_flow/flutter_flow_animations.dart new file mode 100644 index 00000000..486179ca --- /dev/null +++ b/lib/flutter_flow/flutter_flow_animations.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; + +enum AnimationTrigger { + onPageLoad, + onActionTrigger, +} + +class AnimationInfo { + AnimationInfo({ + required this.trigger, + required this.effectsBuilder, + this.loop = false, + this.reverse = false, + this.applyInitialState = true, + }); + final AnimationTrigger trigger; + final List Function()? effectsBuilder; + final bool applyInitialState; + final bool loop; + final bool reverse; + late AnimationController controller; + + List? _effects; + List get effects => _effects ??= effectsBuilder!(); + + void maybeUpdateEffects(List? updatedEffects) { + if (updatedEffects != null) { + _effects = updatedEffects; + } + } +} + +void createAnimation(AnimationInfo animation, TickerProvider vsync) { + final newController = AnimationController(vsync: vsync); + animation.controller = newController; +} + +void setupAnimations(Iterable animations, TickerProvider vsync) { + for (var animation in animations) { + createAnimation(animation, vsync); + } +} + +extension AnimatedWidgetExtension on Widget { + Widget animateOnPageLoad( + AnimationInfo animationInfo, { + List? effects, + }) { + animationInfo.maybeUpdateEffects(effects); + return Animate( + effects: animationInfo.effects, + child: this, + onPlay: (controller) => animationInfo.loop + ? controller.repeat(reverse: animationInfo.reverse) + : null, + onComplete: (controller) => !animationInfo.loop && animationInfo.reverse + ? controller.reverse() + : null, + ); + } + + Widget animateOnActionTrigger( + AnimationInfo animationInfo, { + List? effects, + bool hasBeenTriggered = false, + }) { + animationInfo.maybeUpdateEffects(effects); + return hasBeenTriggered || animationInfo.applyInitialState + ? Animate( + controller: animationInfo.controller, + autoPlay: false, + effects: animationInfo.effects, + child: this) + : this; + } +} + +class TiltEffect extends Effect { + const TiltEffect({ + super.delay, + super.duration, + super.curve, + Offset? begin, + Offset? end, + }) : super( + begin: begin ?? const Offset(0.0, 0.0), + end: end ?? const Offset(0.0, 0.0), + ); + + @override + Widget build( + BuildContext context, + Widget child, + AnimationController controller, + EffectEntry entry, + ) { + Animation animation = buildAnimation(controller, entry); + return getOptimizedBuilder( + animation: animation, + builder: (_, __) => Transform( + transform: Matrix4.identity() + ..setEntry(3, 2, 0.001) + ..rotateX(animation.value.dx) + ..rotateY(animation.value.dy), + alignment: Alignment.center, + child: child, + ), + ); + } +} diff --git a/lib/flutter_flow/flutter_flow_drop_down.dart b/lib/flutter_flow/flutter_flow_drop_down.dart new file mode 100644 index 00000000..edaba01f --- /dev/null +++ b/lib/flutter_flow/flutter_flow_drop_down.dart @@ -0,0 +1,373 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; + +import 'form_field_controller.dart'; +import 'package:flutter/material.dart'; + +class FlutterFlowDropDown extends StatefulWidget { + const FlutterFlowDropDown({ + super.key, + this.controller, + this.multiSelectController, + this.hintText, + this.searchHintText, + required this.options, + this.optionLabels, + this.onChanged, + this.onMultiSelectChanged, + this.icon, + this.width, + this.height, + this.maxHeight, + this.fillColor, + this.searchHintTextStyle, + this.searchTextStyle, + this.searchCursorColor, + required this.textStyle, + required this.elevation, + required this.borderWidth, + required this.borderRadius, + required this.borderColor, + required this.margin, + this.hidesUnderline = false, + this.disabled = false, + this.isOverButton = false, + this.menuOffset, + this.isSearchable = false, + this.isMultiSelect = false, + this.labelText, + this.labelTextStyle, + }) : assert( + isMultiSelect + ? (controller == null && + onChanged == null && + multiSelectController != null && + onMultiSelectChanged != null) + : (controller != null && + onChanged != null && + multiSelectController == null && + onMultiSelectChanged == null), + ); + + final FormFieldController? controller; + final FormFieldController?>? multiSelectController; + final String? hintText; + final String? searchHintText; + final List options; + final List? optionLabels; + final Function(T?)? onChanged; + final Function(List?)? onMultiSelectChanged; + final Widget? icon; + final double? width; + final double? height; + final double? maxHeight; + final Color? fillColor; + final TextStyle? searchHintTextStyle; + final TextStyle? searchTextStyle; + final Color? searchCursorColor; + final TextStyle textStyle; + final double elevation; + final double borderWidth; + final double borderRadius; + final Color borderColor; + final EdgeInsetsGeometry margin; + final bool hidesUnderline; + final bool disabled; + final bool isOverButton; + final Offset? menuOffset; + final bool isSearchable; + final bool isMultiSelect; + final String? labelText; + final TextStyle? labelTextStyle; + + @override + State> createState() => _FlutterFlowDropDownState(); +} + +class _FlutterFlowDropDownState extends State> { + bool get isMultiSelect => widget.isMultiSelect; + FormFieldController get controller => widget.controller!; + FormFieldController?> get multiSelectController => + widget.multiSelectController!; + + T? get currentValue { + final value = isMultiSelect + ? multiSelectController.value?.firstOrNull + : controller.value; + return widget.options.contains(value) ? value : null; + } + + Set get currentValues { + if (!isMultiSelect || multiSelectController.value == null) { + return {}; + } + return widget.options + .toSet() + .intersection(multiSelectController.value!.toSet()); + } + + Map get optionLabels => Map.fromEntries( + widget.options.asMap().entries.map( + (option) => MapEntry( + option.value, + widget.optionLabels == null || + widget.optionLabels!.length < option.key + 1 + ? option.value.toString() + : widget.optionLabels![option.key], + ), + ), + ); + + EdgeInsetsGeometry get horizontalMargin => widget.margin.clamp( + EdgeInsetsDirectional.zero, + const EdgeInsetsDirectional.symmetric(horizontal: double.infinity), + ); + + late void Function() _listener; + final TextEditingController _textEditingController = TextEditingController(); + + @override + void initState() { + super.initState(); + if (isMultiSelect) { + _listener = + () => widget.onMultiSelectChanged!(multiSelectController.value); + multiSelectController.addListener(_listener); + } else { + _listener = () => widget.onChanged!(controller.value); + controller.addListener(_listener); + } + } + + @override + void dispose() { + if (isMultiSelect) { + multiSelectController.removeListener(_listener); + } else { + controller.removeListener(_listener); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final dropdownWidget = _buildDropdownWidget(); + return SizedBox( + width: widget.width, + height: widget.height, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(widget.borderRadius), + border: Border.all( + color: widget.borderColor, + width: widget.borderWidth, + ), + color: widget.fillColor, + ), + child: Padding( + padding: _useDropdown2() ? EdgeInsets.zero : widget.margin, + child: widget.hidesUnderline + ? DropdownButtonHideUnderline(child: dropdownWidget) + : dropdownWidget, + ), + ), + ); + } + + bool _useDropdown2() => + widget.isMultiSelect || + widget.isSearchable || + !widget.isOverButton || + widget.maxHeight != null; + + Widget _buildDropdownWidget() => + _useDropdown2() ? _buildDropdown() : _buildLegacyDropdown(); + + Widget _buildLegacyDropdown() { + return DropdownButtonFormField( + value: currentValue, + hint: _createHintText(), + items: _createMenuItems(), + elevation: widget.elevation.toInt(), + onChanged: widget.disabled ? null : (value) => controller.value = value, + icon: widget.icon, + isExpanded: true, + dropdownColor: widget.fillColor, + focusColor: Colors.transparent, + decoration: InputDecoration( + labelText: widget.labelText == null || widget.labelText!.isEmpty + ? null + : widget.labelText, + labelStyle: widget.labelTextStyle, + border: widget.hidesUnderline + ? InputBorder.none + : const UnderlineInputBorder(), + ), + ); + } + + Text? _createHintText() => widget.hintText != null + ? Text(widget.hintText!, style: widget.textStyle) + : null; + + List> _createMenuItems() => widget.options + .map( + (option) => DropdownMenuItem( + value: option, + child: Padding( + padding: _useDropdown2() ? horizontalMargin : EdgeInsets.zero, + child: Text(optionLabels[option] ?? '', style: widget.textStyle), + ), + ), + ) + .toList(); + + List> _createMultiselectMenuItems() => widget.options + .map( + (item) => DropdownMenuItem( + value: item, + // Disable default onTap to avoid closing menu when selecting an item + enabled: false, + child: StatefulBuilder( + builder: (context, menuSetState) { + final isSelected = + multiSelectController.value?.contains(item) ?? false; + return InkWell( + onTap: () { + multiSelectController.value ??= []; + isSelected + ? multiSelectController.value!.remove(item) + : multiSelectController.value!.add(item); + multiSelectController.update(); + // This rebuilds the StatefulWidget to update the button's text. + setState(() {}); + // This rebuilds the dropdownMenu Widget to update the check mark. + menuSetState(() {}); + }, + child: Container( + height: double.infinity, + padding: horizontalMargin, + child: Row( + children: [ + if (isSelected) + const Icon(Icons.check_box_outlined) + else + const Icon(Icons.check_box_outline_blank), + const SizedBox(width: 16), + Expanded( + child: Text( + optionLabels[item]!, + style: widget.textStyle, + ), + ), + ], + ), + ), + ); + }, + ), + ), + ) + .toList(); + + Widget _buildDropdown() { + final overlayColor = MaterialStateProperty.resolveWith((states) => + states.contains(MaterialState.focused) ? Colors.transparent : null); + final iconStyleData = widget.icon != null + ? IconStyleData(icon: widget.icon!) + : const IconStyleData(); + return DropdownButton2( + value: currentValue, + hint: _createHintText(), + items: isMultiSelect ? _createMultiselectMenuItems() : _createMenuItems(), + iconStyleData: iconStyleData, + buttonStyleData: ButtonStyleData( + elevation: widget.elevation.toInt(), + overlayColor: overlayColor, + padding: widget.margin, + ), + menuItemStyleData: MenuItemStyleData( + overlayColor: overlayColor, + padding: EdgeInsets.zero, + ), + dropdownStyleData: DropdownStyleData( + elevation: widget.elevation.toInt(), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4.0), + color: widget.fillColor, + ), + isOverButton: widget.isOverButton, + offset: widget.menuOffset ?? Offset.zero, + maxHeight: widget.maxHeight, + padding: EdgeInsets.zero, + ), + onChanged: widget.disabled + ? null + : (isMultiSelect ? (_) {} : (val) => widget.controller!.value = val), + isExpanded: true, + selectedItemBuilder: (context) => widget.options + .map( + (item) => Align( + alignment: AlignmentDirectional.centerStart, + child: Text( + isMultiSelect + ? currentValues + .where((v) => optionLabels.containsKey(v)) + .map((v) => optionLabels[v]) + .join(', ') + : optionLabels[item]!, + style: widget.textStyle, + maxLines: 1, + ), + ), + ) + .toList(), + dropdownSearchData: widget.isSearchable + ? DropdownSearchData( + searchController: _textEditingController, + searchInnerWidgetHeight: 50, + searchInnerWidget: Container( + height: 50, + padding: const EdgeInsets.only( + top: 8, + bottom: 4, + right: 8, + left: 8, + ), + child: TextFormField( + expands: true, + maxLines: null, + controller: _textEditingController, + cursorColor: widget.searchCursorColor, + style: widget.searchTextStyle, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + hintText: widget.searchHintText, + hintStyle: widget.searchHintTextStyle, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + searchMatchFn: (item, searchValue) { + return (optionLabels[item.value] ?? '') + .toLowerCase() + .contains(searchValue.toLowerCase()); + }, + ) + : null, + // This is to clear the search value when you close the menu + onMenuStateChange: widget.isSearchable + ? (isOpen) { + if (!isOpen) { + _textEditingController.clear(); + } + } + : null, + ); + } +} diff --git a/lib/flutter_flow/flutter_flow_icon_button.dart b/lib/flutter_flow/flutter_flow_icon_button.dart new file mode 100644 index 00000000..cabfa4e9 --- /dev/null +++ b/lib/flutter_flow/flutter_flow_icon_button.dart @@ -0,0 +1,170 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class FlutterFlowIconButton extends StatefulWidget { + const FlutterFlowIconButton({ + super.key, + required this.icon, + this.borderColor, + this.borderRadius, + this.borderWidth, + this.buttonSize, + this.fillColor, + this.disabledColor, + this.disabledIconColor, + this.hoverColor, + this.hoverIconColor, + this.onPressed, + this.showLoadingIndicator = false, + }); + + final Widget icon; + final double? borderRadius; + final double? buttonSize; + final Color? fillColor; + final Color? disabledColor; + final Color? disabledIconColor; + final Color? hoverColor; + final Color? hoverIconColor; + final Color? borderColor; + final double? borderWidth; + final bool showLoadingIndicator; + final Function()? onPressed; + + @override + State createState() => _FlutterFlowIconButtonState(); +} + +class _FlutterFlowIconButtonState extends State { + bool loading = false; + late double? iconSize; + late Color? iconColor; + late Widget effectiveIcon; + + @override + void initState() { + super.initState(); + _updateIcon(); + } + + @override + void didUpdateWidget(FlutterFlowIconButton oldWidget) { + super.didUpdateWidget(oldWidget); + _updateIcon(); + } + + void _updateIcon() { + final isFontAwesome = widget.icon is FaIcon; + if (isFontAwesome) { + FaIcon icon = widget.icon as FaIcon; + effectiveIcon = FaIcon( + icon.icon, + size: icon.size, + ); + iconSize = icon.size; + iconColor = icon.color; + } else { + Icon icon = widget.icon as Icon; + effectiveIcon = Icon( + icon.icon, + size: icon.size, + ); + iconSize = icon.size; + iconColor = icon.color; + } + } + + @override + Widget build(BuildContext context) { + ButtonStyle style = ButtonStyle( + shape: MaterialStateProperty.resolveWith( + (states) { + return RoundedRectangleBorder( + borderRadius: BorderRadius.circular(widget.borderRadius ?? 0), + side: BorderSide( + color: widget.borderColor ?? Colors.transparent, + width: widget.borderWidth ?? 0, + ), + ); + }, + ), + iconColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled) && + widget.disabledIconColor != null) { + return widget.disabledIconColor; + } + if (states.contains(MaterialState.hovered) && + widget.hoverIconColor != null) { + return widget.hoverIconColor; + } + return iconColor; + }, + ), + backgroundColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled) && + widget.disabledColor != null) { + return widget.disabledColor; + } + if (states.contains(MaterialState.hovered) && + widget.hoverColor != null) { + return widget.hoverColor; + } + + return widget.fillColor; + }, + ), + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.pressed)) { + return null; + } + return widget.hoverColor == null ? null : Colors.transparent; + }), + ); + + return SizedBox( + width: widget.buttonSize, + height: widget.buttonSize, + child: Theme( + data: ThemeData.from( + colorScheme: Theme.of(context).colorScheme, + useMaterial3: true, + ), + child: IgnorePointer( + ignoring: (widget.showLoadingIndicator && loading), + child: IconButton( + icon: (widget.showLoadingIndicator && loading) + ? SizedBox( + width: iconSize, + height: iconSize, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + iconColor ?? Colors.white, + ), + ), + ) + : effectiveIcon, + onPressed: widget.onPressed == null + ? null + : () async { + if (loading) { + return; + } + setState(() => loading = true); + try { + await widget.onPressed!(); + } finally { + if (mounted) { + setState(() => loading = false); + } + } + }, + splashRadius: widget.buttonSize, + style: style, + ), + ), + ), + ); + } +} diff --git a/lib/flutter_flow/flutter_flow_model.dart b/lib/flutter_flow/flutter_flow_model.dart new file mode 100644 index 00000000..4606ba84 --- /dev/null +++ b/lib/flutter_flow/flutter_flow_model.dart @@ -0,0 +1,169 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:provider/provider.dart'; + +Widget wrapWithModel({ + required T model, + required Widget child, + required VoidCallback updateCallback, + bool updateOnChange = false, +}) { + // Set the component to optionally update the page on updates. + model.setOnUpdate( + onUpdate: updateCallback, + updateOnChange: updateOnChange, + ); + // Models for components within a page will be disposed by the page's model, + // so we don't want the component widget to dispose them until the page is + // itself disposed. + model.disposeOnWidgetDisposal = false; + // Wrap in a Provider so that the model can be accessed by the component. + return Provider.value( + value: model, + child: child, + ); +} + +T createModel( + BuildContext context, + T Function() defaultBuilder, +) { + final model = context.read() ?? defaultBuilder(); + model._init(context); + return model; +} + +abstract class FlutterFlowModel { + // Initialization methods + bool _isInitialized = false; + void initState(BuildContext context); + void _init(BuildContext context) { + if (!_isInitialized) { + initState(context); + _isInitialized = true; + } + if (context.widget is W) _widget = context.widget as W; + } + + // The widget associated with this model. This is useful for accessing the + // parameters of the widget, for example. + W? _widget; + // This will always be non-null when used, but is nullable to allow us to + // dispose of the widget in the [dispose] method (for garbage collection). + W get widget => _widget!; + + // Dispose methods + // Whether to dispose this model when the corresponding widget is + // disposed. By default this is true for pages and false for components, + // as page/component models handle the disposal of their children. + bool disposeOnWidgetDisposal = true; + void dispose(); + void maybeDispose() { + if (disposeOnWidgetDisposal) { + dispose(); + } + // Remove reference to widget for garbage collection purposes. + _widget = null; + } + + // Whether to update the containing page / component on updates. + bool updateOnChange = false; + // Function to call when the model receives an update. + VoidCallback _updateCallback = () {}; + void onUpdate() => updateOnChange ? _updateCallback() : () {}; + FlutterFlowModel setOnUpdate({ + bool updateOnChange = false, + required VoidCallback onUpdate, + }) => + this + .._updateCallback = onUpdate + ..updateOnChange = updateOnChange; + // Update the containing page when this model received an update. + void updatePage(VoidCallback callback) { + callback(); + _updateCallback(); + } +} + +class FlutterFlowDynamicModels { + FlutterFlowDynamicModels(this.defaultBuilder); + + final T Function() defaultBuilder; + final Map _childrenModels = {}; + final Map _childrenIndexes = {}; + Set? _activeKeys; + + T getModel(String uniqueKey, int index) { + _updateActiveKeys(uniqueKey); + _childrenIndexes[uniqueKey] = index; + return _childrenModels[uniqueKey] ??= defaultBuilder(); + } + + List getValues(S? Function(T) getValue) { + return _childrenIndexes.entries + // Sort keys by index. + .sorted((a, b) => a.value.compareTo(b.value)) + .where((e) => _childrenModels[e.key] != null) + // Map each model to the desired value and return as list. In order + // to preserve index order, rather than removing null values we provide + // default values (for types with reasonable defaults). + .map((e) => getValue(_childrenModels[e.key]!) ?? _getDefaultValue()!) + .toList(); + } + + S? getValueAtIndex(int index, S? Function(T) getValue) { + final uniqueKey = + _childrenIndexes.entries.firstWhereOrNull((e) => e.value == index)?.key; + return getValueForKey(uniqueKey, getValue); + } + + S? getValueForKey(String? uniqueKey, S? Function(T) getValue) { + final model = _childrenModels[uniqueKey]; + return model != null ? getValue(model) : null; + } + + void dispose() => _childrenModels.values.forEach((model) => model.dispose()); + + void _updateActiveKeys(String uniqueKey) { + final shouldResetActiveKeys = _activeKeys == null; + _activeKeys ??= {}; + _activeKeys!.add(uniqueKey); + + if (shouldResetActiveKeys) { + // Add a post-frame callback to remove and dispose of unused models after + // we're done building, then reset `_activeKeys` to null so we know to do + // this again next build. + SchedulerBinding.instance.addPostFrameCallback((_) { + _childrenIndexes.removeWhere((k, _) => !_activeKeys!.contains(k)); + _childrenModels.keys + .toSet() + .difference(_activeKeys!) + // Remove and dispose of unused models since they are not being used + // elsewhere and would not otherwise be disposed. + .forEach((k) => _childrenModels.remove(k)?.maybeDispose()); + _activeKeys = null; + }); + } + } +} + +T? _getDefaultValue() { + switch (T) { + case int: + return 0 as T; + case double: + return 0.0 as T; + case String: + return '' as T; + case bool: + return false as T; + default: + return null as T; + } +} + +extension TextValidationExtensions on String? Function(BuildContext, String?)? { + String? Function(String?)? asValidator(BuildContext context) => + this != null ? (val) => this!(context, val) : null; +} diff --git a/lib/flutter_flow/flutter_flow_theme.dart b/lib/flutter_flow/flutter_flow_theme.dart new file mode 100644 index 00000000..7429aca2 --- /dev/null +++ b/lib/flutter_flow/flutter_flow_theme.dart @@ -0,0 +1,613 @@ +// ignore_for_file: overridden_fields, annotate_overrides + +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import 'package:shared_preferences/shared_preferences.dart'; + +const kThemeModeKey = '__theme_mode__'; +SharedPreferences? _prefs; + +enum DeviceSize { + mobile, + tablet, + desktop, +} + +abstract class FlutterFlowTheme { + static DeviceSize deviceSize = DeviceSize.mobile; + + static Future initialize() async => + _prefs = await SharedPreferences.getInstance(); + static ThemeMode get themeMode { + final darkMode = _prefs?.getBool(kThemeModeKey); + return darkMode == null + ? ThemeMode.system + : darkMode + ? ThemeMode.dark + : ThemeMode.light; + } + + static void saveThemeMode(ThemeMode mode) => mode == ThemeMode.system + ? _prefs?.remove(kThemeModeKey) + : _prefs?.setBool(kThemeModeKey, mode == ThemeMode.dark); + + static FlutterFlowTheme of(BuildContext context) { + deviceSize = getDeviceSize(context); + return Theme.of(context).brightness == Brightness.dark + ? DarkModeTheme() + : LightModeTheme(); + } + + @Deprecated('Use primary instead') + Color get primaryColor => primary; + @Deprecated('Use secondary instead') + Color get secondaryColor => secondary; + @Deprecated('Use tertiary instead') + Color get tertiaryColor => tertiary; + + late Color primary; + late Color secondary; + late Color tertiary; + late Color alternate; + late Color primaryText; + late Color secondaryText; + late Color primaryBackground; + late Color secondaryBackground; + late Color accent1; + late Color accent2; + late Color accent3; + late Color accent4; + late Color success; + late Color warning; + late Color error; + late Color info; + + late Color customColor1; + late Color customColor2; + late Color customColor3; + late Color customColor4; + late Color customColor5; + + @Deprecated('Use displaySmallFamily instead') + String get title1Family => displaySmallFamily; + @Deprecated('Use displaySmall instead') + TextStyle get title1 => typography.displaySmall; + @Deprecated('Use headlineMediumFamily instead') + String get title2Family => typography.headlineMediumFamily; + @Deprecated('Use headlineMedium instead') + TextStyle get title2 => typography.headlineMedium; + @Deprecated('Use headlineSmallFamily instead') + String get title3Family => typography.headlineSmallFamily; + @Deprecated('Use headlineSmall instead') + TextStyle get title3 => typography.headlineSmall; + @Deprecated('Use titleMediumFamily instead') + String get subtitle1Family => typography.titleMediumFamily; + @Deprecated('Use titleMedium instead') + TextStyle get subtitle1 => typography.titleMedium; + @Deprecated('Use titleSmallFamily instead') + String get subtitle2Family => typography.titleSmallFamily; + @Deprecated('Use titleSmall instead') + TextStyle get subtitle2 => typography.titleSmall; + @Deprecated('Use bodyMediumFamily instead') + String get bodyText1Family => typography.bodyMediumFamily; + @Deprecated('Use bodyMedium instead') + TextStyle get bodyText1 => typography.bodyMedium; + @Deprecated('Use bodySmallFamily instead') + String get bodyText2Family => typography.bodySmallFamily; + @Deprecated('Use bodySmall instead') + TextStyle get bodyText2 => typography.bodySmall; + + String get displayLargeFamily => typography.displayLargeFamily; + TextStyle get displayLarge => typography.displayLarge; + String get displayMediumFamily => typography.displayMediumFamily; + TextStyle get displayMedium => typography.displayMedium; + String get displaySmallFamily => typography.displaySmallFamily; + TextStyle get displaySmall => typography.displaySmall; + String get headlineLargeFamily => typography.headlineLargeFamily; + TextStyle get headlineLarge => typography.headlineLarge; + String get headlineMediumFamily => typography.headlineMediumFamily; + TextStyle get headlineMedium => typography.headlineMedium; + String get headlineSmallFamily => typography.headlineSmallFamily; + TextStyle get headlineSmall => typography.headlineSmall; + String get titleLargeFamily => typography.titleLargeFamily; + TextStyle get titleLarge => typography.titleLarge; + String get titleMediumFamily => typography.titleMediumFamily; + TextStyle get titleMedium => typography.titleMedium; + String get titleSmallFamily => typography.titleSmallFamily; + TextStyle get titleSmall => typography.titleSmall; + String get labelLargeFamily => typography.labelLargeFamily; + TextStyle get labelLarge => typography.labelLarge; + String get labelMediumFamily => typography.labelMediumFamily; + TextStyle get labelMedium => typography.labelMedium; + String get labelSmallFamily => typography.labelSmallFamily; + TextStyle get labelSmall => typography.labelSmall; + String get bodyLargeFamily => typography.bodyLargeFamily; + TextStyle get bodyLarge => typography.bodyLarge; + String get bodyMediumFamily => typography.bodyMediumFamily; + TextStyle get bodyMedium => typography.bodyMedium; + String get bodySmallFamily => typography.bodySmallFamily; + TextStyle get bodySmall => typography.bodySmall; + + Typography get typography => { + DeviceSize.mobile: MobileTypography(this), + DeviceSize.tablet: TabletTypography(this), + DeviceSize.desktop: DesktopTypography(this), + }[deviceSize]!; +} + +DeviceSize getDeviceSize(BuildContext context) { + final width = MediaQuery.sizeOf(context).width; + if (width < 479) { + return DeviceSize.mobile; + } else if (width < 991) { + return DeviceSize.tablet; + } else { + return DeviceSize.desktop; + } +} + +class LightModeTheme extends FlutterFlowTheme { + @Deprecated('Use primary instead') + Color get primaryColor => primary; + @Deprecated('Use secondary instead') + Color get secondaryColor => secondary; + @Deprecated('Use tertiary instead') + Color get tertiaryColor => tertiary; + + late Color primary = const Color(0xFF1AAB5F); + late Color secondary = const Color(0xFFB59E9E); + late Color tertiary = const Color(0xFF984BB6); + late Color alternate = const Color(0xFFF2F2F2); + late Color primaryText = const Color(0xFF000000); + late Color secondaryText = const Color(0xFFFFFFFF); + late Color primaryBackground = const Color(0xFFFFFFFF); + late Color secondaryBackground = const Color(0xFFFFFFFF); + late Color accent1 = const Color(0xFF1AAB5F); + late Color accent2 = const Color(0x4D000000); + late Color accent3 = const Color(0xFFFFFFFF); + late Color accent4 = const Color(0xFF1AAB5F); + late Color success = const Color(0xFF1AAB5F); + late Color warning = const Color(0xFFF3C344); + late Color error = const Color(0xFFD70000); + late Color info = const Color(0xFFFFFFFF); + + late Color customColor1 = const Color(0xFF000000); + late Color customColor2 = const Color(0xFF1AAB5F); + late Color customColor3 = const Color(0xFFFFFFFF); + late Color customColor4 = const Color(0xFFCFCFCF); + late Color customColor5 = const Color(0xFF979595); +} + +abstract class Typography { + String get displayLargeFamily; + TextStyle get displayLarge; + String get displayMediumFamily; + TextStyle get displayMedium; + String get displaySmallFamily; + TextStyle get displaySmall; + String get headlineLargeFamily; + TextStyle get headlineLarge; + String get headlineMediumFamily; + TextStyle get headlineMedium; + String get headlineSmallFamily; + TextStyle get headlineSmall; + String get titleLargeFamily; + TextStyle get titleLarge; + String get titleMediumFamily; + TextStyle get titleMedium; + String get titleSmallFamily; + TextStyle get titleSmall; + String get labelLargeFamily; + TextStyle get labelLarge; + String get labelMediumFamily; + TextStyle get labelMedium; + String get labelSmallFamily; + TextStyle get labelSmall; + String get bodyLargeFamily; + TextStyle get bodyLarge; + String get bodyMediumFamily; + TextStyle get bodyMedium; + String get bodySmallFamily; + TextStyle get bodySmall; +} + +class MobileTypography extends Typography { + MobileTypography(this.theme); + + final FlutterFlowTheme theme; + + String get displayLargeFamily => 'Nunito Sans'; + TextStyle get displayLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w300, + fontSize: 52.0, + ); + String get displayMediumFamily => 'Nunito Sans'; + TextStyle get displayMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 44.0, + ); + String get displaySmallFamily => 'Nunito Sans'; + TextStyle get displaySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 36.0, + ); + String get headlineLargeFamily => 'Nunito Sans'; + TextStyle get headlineLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineMediumFamily => 'Nunito Sans'; + TextStyle get headlineMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 28.0, + ); + String get headlineSmallFamily => 'Nunito Sans'; + TextStyle get headlineSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 24.0, + ); + String get titleLargeFamily => 'Nunito Sans'; + TextStyle get titleLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleMediumFamily => 'Nunito Sans'; + TextStyle get titleMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 18.0, + ); + String get titleSmallFamily => 'Nunito Sans'; + TextStyle get titleSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelLargeFamily => 'Nunito Sans'; + TextStyle get labelLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelMediumFamily => 'Nunito Sans'; + TextStyle get labelMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 14.0, + ); + String get labelSmallFamily => 'Nunito Sans'; + TextStyle get labelSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 12.0, + ); + String get bodyLargeFamily => 'Nunito Sans'; + TextStyle get bodyLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontSize: 16.0, + ); + String get bodyMediumFamily => 'Nunito Sans'; + TextStyle get bodyMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 14.0, + ); + String get bodySmallFamily => 'Nunito Sans'; + TextStyle get bodySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 12.0, + ); +} + +class TabletTypography extends Typography { + TabletTypography(this.theme); + + final FlutterFlowTheme theme; + + String get displayLargeFamily => 'Nunito Sans'; + TextStyle get displayLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w300, + fontSize: 52.0, + ); + String get displayMediumFamily => 'Nunito Sans'; + TextStyle get displayMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 44.0, + ); + String get displaySmallFamily => 'Nunito Sans'; + TextStyle get displaySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 36.0, + ); + String get headlineLargeFamily => 'Nunito Sans'; + TextStyle get headlineLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineMediumFamily => 'Nunito Sans'; + TextStyle get headlineMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 28.0, + ); + String get headlineSmallFamily => 'Nunito Sans'; + TextStyle get headlineSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 24.0, + ); + String get titleLargeFamily => 'Nunito Sans'; + TextStyle get titleLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleMediumFamily => 'Nunito Sans'; + TextStyle get titleMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 18.0, + ); + String get titleSmallFamily => 'Nunito Sans'; + TextStyle get titleSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelLargeFamily => 'Nunito Sans'; + TextStyle get labelLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelMediumFamily => 'Nunito Sans'; + TextStyle get labelMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 14.0, + ); + String get labelSmallFamily => 'Nunito Sans'; + TextStyle get labelSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 12.0, + ); + String get bodyLargeFamily => 'Nunito Sans'; + TextStyle get bodyLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontSize: 16.0, + ); + String get bodyMediumFamily => 'Nunito Sans'; + TextStyle get bodyMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 14.0, + ); + String get bodySmallFamily => 'Nunito Sans'; + TextStyle get bodySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 12.0, + ); +} + +class DesktopTypography extends Typography { + DesktopTypography(this.theme); + + final FlutterFlowTheme theme; + + String get displayLargeFamily => 'Nunito Sans'; + TextStyle get displayLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w300, + fontSize: 52.0, + ); + String get displayMediumFamily => 'Nunito Sans'; + TextStyle get displayMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 44.0, + ); + String get displaySmallFamily => 'Nunito Sans'; + TextStyle get displaySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 36.0, + ); + String get headlineLargeFamily => 'Nunito Sans'; + TextStyle get headlineLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 32.0, + ); + String get headlineMediumFamily => 'Nunito Sans'; + TextStyle get headlineMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 28.0, + ); + String get headlineSmallFamily => 'Nunito Sans'; + TextStyle get headlineSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 24.0, + ); + String get titleLargeFamily => 'Nunito Sans'; + TextStyle get titleLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.w500, + fontSize: 22.0, + ); + String get titleMediumFamily => 'Nunito Sans'; + TextStyle get titleMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 18.0, + ); + String get titleSmallFamily => 'Nunito Sans'; + TextStyle get titleSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.info, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelLargeFamily => 'Nunito Sans'; + TextStyle get labelLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 16.0, + ); + String get labelMediumFamily => 'Nunito Sans'; + TextStyle get labelMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 14.0, + ); + String get labelSmallFamily => 'Nunito Sans'; + TextStyle get labelSmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.secondaryText, + fontWeight: FontWeight.w500, + fontSize: 12.0, + ); + String get bodyLargeFamily => 'Nunito Sans'; + TextStyle get bodyLarge => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontSize: 16.0, + ); + String get bodyMediumFamily => 'Nunito Sans'; + TextStyle get bodyMedium => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 14.0, + ); + String get bodySmallFamily => 'Nunito Sans'; + TextStyle get bodySmall => GoogleFonts.getFont( + 'Nunito Sans', + color: theme.primaryText, + fontWeight: FontWeight.normal, + fontSize: 12.0, + ); +} + +class DarkModeTheme extends FlutterFlowTheme { + @Deprecated('Use primary instead') + Color get primaryColor => primary; + @Deprecated('Use secondary instead') + Color get secondaryColor => secondary; + @Deprecated('Use tertiary instead') + Color get tertiaryColor => tertiary; + + late Color primary = const Color(0xFF1AAB5F); + late Color secondary = const Color(0xFF18AA99); + late Color tertiary = const Color(0xFF984BB6); + late Color alternate = const Color(0xFF232323); + late Color primaryText = const Color(0xFFFFFFFF); + late Color secondaryText = const Color(0xFF000000); + late Color primaryBackground = const Color(0xFF171717); + late Color secondaryBackground = const Color(0xFF101818); + late Color accent1 = const Color(0xFFFFFFFF); + late Color accent2 = const Color(0x4D000000); + late Color accent3 = const Color(0xFFFFFFFF); + late Color accent4 = const Color(0xFF4A4A4A); + late Color success = const Color(0xFF1AAB5F); + late Color warning = const Color(0xFFF3C344); + late Color error = const Color(0xFFD70000); + late Color info = const Color(0xFFFFFFFF); + + late Color customColor1 = const Color(0xFFFFFFFF); + late Color customColor2 = const Color(0xFFFFFFFF); + late Color customColor3 = const Color(0xFF1AAB5F); + late Color customColor4 = const Color(0xFF232323); + late Color customColor5 = const Color(0xFF232323); +} + +extension TextStyleHelper on TextStyle { + TextStyle override({ + String? fontFamily, + Color? color, + double? fontSize, + FontWeight? fontWeight, + double? letterSpacing, + FontStyle? fontStyle, + bool useGoogleFonts = true, + TextDecoration? decoration, + double? lineHeight, + }) => + useGoogleFonts + ? GoogleFonts.getFont( + fontFamily!, + color: color ?? this.color, + fontSize: fontSize ?? this.fontSize, + letterSpacing: letterSpacing ?? this.letterSpacing, + fontWeight: fontWeight ?? this.fontWeight, + fontStyle: fontStyle ?? this.fontStyle, + decoration: decoration, + height: lineHeight, + ) + : copyWith( + fontFamily: fontFamily, + color: color, + fontSize: fontSize, + letterSpacing: letterSpacing, + fontWeight: fontWeight, + fontStyle: fontStyle, + decoration: decoration, + height: lineHeight, + ); +} diff --git a/lib/flutter_flow/flutter_flow_util.dart b/lib/flutter_flow/flutter_flow_util.dart new file mode 100644 index 00000000..f48a21ef --- /dev/null +++ b/lib/flutter_flow/flutter_flow_util.dart @@ -0,0 +1,562 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:collection/collection.dart'; +import 'package:from_css_color/from_css_color.dart'; +import 'dart:math' show pow, pi, sin; +import 'package:intl/intl.dart'; +import 'package:json_path/json_path.dart'; +import 'package:timeago/timeago.dart' as timeago; +import 'package:url_launcher/url_launcher.dart'; + +import '../main.dart'; + + +export 'lat_lng.dart'; +export 'place.dart'; +export 'uploaded_file.dart'; +export '../app_state.dart'; +export 'flutter_flow_model.dart'; +export 'dart:math' show min, max; +export 'dart:typed_data' show Uint8List; +export 'dart:convert' show jsonEncode, jsonDecode; +export 'package:intl/intl.dart'; +export 'package:page_transition/page_transition.dart'; +export 'custom_icons.dart' show FFIcons; +export 'internationalization.dart' show FFLocalizations; +export 'nav/nav.dart'; + +T valueOrDefault(T? value, T defaultValue) => + (value is String && value.isEmpty) || value == null ? defaultValue : value; + +void _setTimeagoLocales() { + timeago.setLocaleMessages('pt', timeago.PtBrMessages()); + timeago.setLocaleMessages('pt_short', timeago.PtBrShortMessages()); + timeago.setLocaleMessages('en', timeago.EnMessages()); + timeago.setLocaleMessages('en_short', timeago.EnShortMessages()); +} + +String dateTimeFormat(String format, DateTime? dateTime, {String? locale}) { + if (dateTime == null) { + return ''; + } + if (format == 'relative') { + _setTimeagoLocales(); + return timeago.format(dateTime, locale: locale, allowFromNow: true); + } + return DateFormat(format, locale).format(dateTime); +} + +Theme wrapInMaterialDatePickerTheme( + BuildContext context, + Widget child, { + required Color headerBackgroundColor, + required Color headerForegroundColor, + required TextStyle headerTextStyle, + required Color pickerBackgroundColor, + required Color pickerForegroundColor, + required Color selectedDateTimeBackgroundColor, + required Color selectedDateTimeForegroundColor, + required Color actionButtonForegroundColor, + required double iconSize, +}) { + final baseTheme = Theme.of(context); + final dateTimeMaterialStateForegroundColor = + MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.disabled)) { + return pickerForegroundColor.withOpacity(0.60); + } + if (states.contains(MaterialState.selected)) { + return selectedDateTimeForegroundColor; + } + if (states.isEmpty) { + return pickerForegroundColor; + } + return null; + }); + + final dateTimeMaterialStateBackgroundColor = + MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return selectedDateTimeBackgroundColor; + } + return null; + }); + + return Theme( + data: baseTheme.copyWith( + colorScheme: baseTheme.colorScheme.copyWith( + onSurface: pickerForegroundColor, + ), + disabledColor: pickerForegroundColor.withOpacity(0.3), + textTheme: baseTheme.textTheme.copyWith( + headlineSmall: headerTextStyle, + headlineMedium: headerTextStyle, + ), + iconTheme: baseTheme.iconTheme.copyWith( + size: iconSize, + ), + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + foregroundColor: MaterialStatePropertyAll( + actionButtonForegroundColor, + ), + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.hovered)) { + return actionButtonForegroundColor.withOpacity(0.04); + } + if (states.contains(MaterialState.focused) || + states.contains(MaterialState.pressed)) { + return actionButtonForegroundColor.withOpacity(0.12); + } + return null; + })), + ), + datePickerTheme: DatePickerThemeData( + backgroundColor: pickerBackgroundColor, + headerBackgroundColor: headerBackgroundColor, + headerForegroundColor: headerForegroundColor, + weekdayStyle: baseTheme.textTheme.labelMedium!.copyWith( + color: pickerForegroundColor, + ), + dayBackgroundColor: dateTimeMaterialStateBackgroundColor, + todayBackgroundColor: dateTimeMaterialStateBackgroundColor, + yearBackgroundColor: dateTimeMaterialStateBackgroundColor, + dayForegroundColor: dateTimeMaterialStateForegroundColor, + todayForegroundColor: dateTimeMaterialStateForegroundColor, + yearForegroundColor: dateTimeMaterialStateForegroundColor, + ), + ), + child: child, + ); +} + +Theme wrapInMaterialTimePickerTheme( + BuildContext context, + Widget child, { + required Color headerBackgroundColor, + required Color headerForegroundColor, + required TextStyle headerTextStyle, + required Color pickerBackgroundColor, + required Color pickerForegroundColor, + required Color selectedDateTimeBackgroundColor, + required Color selectedDateTimeForegroundColor, + required Color actionButtonForegroundColor, + required double iconSize, +}) { + final baseTheme = Theme.of(context); + return Theme( + data: baseTheme.copyWith( + iconTheme: baseTheme.iconTheme.copyWith( + size: iconSize, + ), + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + foregroundColor: MaterialStatePropertyAll( + actionButtonForegroundColor, + ), + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.hovered)) { + return actionButtonForegroundColor.withOpacity(0.04); + } + if (states.contains(MaterialState.focused) || + states.contains(MaterialState.pressed)) { + return actionButtonForegroundColor.withOpacity(0.12); + } + return null; + })), + ), + timePickerTheme: baseTheme.timePickerTheme.copyWith( + backgroundColor: pickerBackgroundColor, + hourMinuteTextColor: pickerForegroundColor, + dialHandColor: selectedDateTimeBackgroundColor, + dialTextColor: MaterialStateColor.resolveWith((states) => + states.contains(MaterialState.selected) + ? selectedDateTimeForegroundColor + : pickerForegroundColor), + dayPeriodBorderSide: BorderSide( + color: pickerForegroundColor, + ), + dayPeriodTextColor: MaterialStateColor.resolveWith((states) => + states.contains(MaterialState.selected) + ? selectedDateTimeForegroundColor + : pickerForegroundColor), + dayPeriodColor: MaterialStateColor.resolveWith((states) => + states.contains(MaterialState.selected) + ? selectedDateTimeBackgroundColor + : Colors.transparent), + entryModeIconColor: pickerForegroundColor, + ), + ), + child: child, + ); +} + +Future launchURL(String url) async { + var uri = Uri.parse(url); + try { + await launchUrl(uri); + } catch (e) { + throw 'Could not launch $uri: $e'; + } +} + +Color colorFromCssString(String color, {Color? defaultColor}) { + try { + return fromCssColor(color); + } catch (_) {} + return defaultColor ?? Colors.black; +} + +enum FormatType { + decimal, + percent, + scientific, + compact, + compactLong, + custom, +} + +enum DecimalType { + automatic, + periodDecimal, + commaDecimal, +} + +String formatNumber( + num? value, { + required FormatType formatType, + DecimalType? decimalType, + String? currency, + bool toLowerCase = false, + String? format, + String? locale, +}) { + if (value == null) { + return ''; + } + var formattedValue = ''; + switch (formatType) { + case FormatType.decimal: + switch (decimalType!) { + case DecimalType.automatic: + formattedValue = NumberFormat.decimalPattern().format(value); + break; + case DecimalType.periodDecimal: + formattedValue = NumberFormat.decimalPattern('en_US').format(value); + break; + case DecimalType.commaDecimal: + formattedValue = NumberFormat.decimalPattern('es_PA').format(value); + break; + } + break; + case FormatType.percent: + formattedValue = NumberFormat.percentPattern().format(value); + break; + case FormatType.scientific: + formattedValue = NumberFormat.scientificPattern().format(value); + if (toLowerCase) { + formattedValue = formattedValue.toLowerCase(); + } + break; + case FormatType.compact: + formattedValue = NumberFormat.compact().format(value); + break; + case FormatType.compactLong: + formattedValue = NumberFormat.compactLong().format(value); + break; + case FormatType.custom: + final hasLocale = locale != null && locale.isNotEmpty; + formattedValue = + NumberFormat(format, hasLocale ? locale : null).format(value); + } + + if (formattedValue.isEmpty) { + return value.toString(); + } + + if (currency != null) { + final currencySymbol = currency.isNotEmpty + ? currency + : NumberFormat.simpleCurrency().format(0.0).substring(0, 1); + formattedValue = '$currencySymbol$formattedValue'; + } + + return formattedValue; +} + +DateTime get getCurrentTimestamp => DateTime.now(); +DateTime dateTimeFromSecondsSinceEpoch(int seconds) { + return DateTime.fromMillisecondsSinceEpoch(seconds * 1000); +} + +extension DateTimeConversionExtension on DateTime { + int get secondsSinceEpoch => (millisecondsSinceEpoch / 1000).round(); +} + +extension DateTimeComparisonOperators on DateTime { + bool operator <(DateTime other) => isBefore(other); + bool operator >(DateTime other) => isAfter(other); + bool operator <=(DateTime other) => this < other || isAtSameMomentAs(other); + bool operator >=(DateTime other) => this > other || isAtSameMomentAs(other); +} + +T? castToType(dynamic value) { + if (value == null) { + return null; + } + switch (T) { + case double: + // Doubles may be stored as ints in some cases. + return value.toDouble() as T; + case int: + // Likewise, ints may be stored as doubles. If this is the case + // (i.e. no decimal value), return the value as an int. + if (value is num && value.toInt() == value) { + return value.toInt() as T; + } + break; + default: + break; + } + return value as T; +} + +dynamic getJsonField( + dynamic response, + String jsonPath, [ + bool isForList = false, +]) { + final field = JsonPath(jsonPath).read(response); + if (field.isEmpty) { + return null; + } + if (field.length > 1) { + return field.map((f) => f.value).toList(); + } + final value = field.first.value; + if (isForList) { + return value is! Iterable + ? [value] + : (value is List ? value : value.toList()); + } + return value; +} + +Rect? getWidgetBoundingBox(BuildContext context) { + try { + final renderBox = context.findRenderObject() as RenderBox?; + return renderBox!.localToGlobal(Offset.zero) & renderBox.size; + } catch (_) { + return null; + } +} + +bool get isAndroid => !kIsWeb && Platform.isAndroid; +bool get isiOS => !kIsWeb && Platform.isIOS; +bool get isWeb => kIsWeb; + +const kBreakpointSmall = 479.0; +const kBreakpointMedium = 767.0; +const kBreakpointLarge = 991.0; +bool isMobileWidth(BuildContext context) => + MediaQuery.sizeOf(context).width < kBreakpointSmall; +bool responsiveVisibility({ + required BuildContext context, + bool phone = true, + bool tablet = true, + bool tabletLandscape = true, + bool desktop = true, +}) { + final width = MediaQuery.sizeOf(context).width; + if (width < kBreakpointSmall) { + return phone; + } else if (width < kBreakpointMedium) { + return tablet; + } else if (width < kBreakpointLarge) { + return tabletLandscape; + } else { + return desktop; + } +} + +const kTextValidatorUsernameRegex = r'^[a-zA-Z][a-zA-Z0-9_-]{2,16}$'; +// https://stackoverflow.com/a/201378 +const kTextValidatorEmailRegex = + "^(?:[a-zA-Z0-9!#\$%&\'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#\$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])\$"; +const kTextValidatorWebsiteRegex = + r'(https?:\/\/)?(www\.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,10}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)|(https?:\/\/)?(www\.)?(?!ww)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,10}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)'; + +extension FFTextEditingControllerExt on TextEditingController? { + String get text => this == null ? '' : this!.text; + set text(String newText) => this?.text = newText; +} + +extension IterableExt on Iterable { + List sortedList([S Function(T)? keyOf]) => toList() + ..sort(keyOf == null ? null : ((a, b) => keyOf(a).compareTo(keyOf(b)))); + + List mapIndexed(S Function(int, T) func) => toList() + .asMap() + .map((index, value) => MapEntry(index, func(index, value))) + .values + .toList(); +} + +void setAppLanguage(BuildContext context, String language) => + MyApp.of(context).setLocale(language); + +void setDarkModeSetting(BuildContext context, ThemeMode themeMode) => + MyApp.of(context).setThemeMode(themeMode); + +void showSnackbar( + BuildContext context, + String message, { + bool loading = false, + int duration = 4, +}) { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Row( + children: [ + if (loading) + const Padding( + padding: EdgeInsetsDirectional.only(end: 10.0), + child: SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + color: Colors.white, + ), + ), + ), + Text(message), + ], + ), + duration: Duration(seconds: duration), + ), + ); +} + +extension FFStringExt on String { + String maybeHandleOverflow({int? maxChars, String replacement = ''}) => + maxChars != null && length > maxChars + ? replaceRange(maxChars, null, replacement) + : this; +} + +extension ListFilterExt on Iterable { + List get withoutNulls => where((s) => s != null).map((e) => e!).toList(); +} + +extension MapListContainsExt on List { + bool containsMap(dynamic map) => map is Map + ? any((e) => e is Map && const DeepCollectionEquality().equals(e, map)) + : contains(map); +} + +extension ListDivideExt on Iterable { + Iterable> get enumerate => toList().asMap().entries; + + List divide(Widget t, {bool Function(int)? filterFn}) => isEmpty + ? [] + : (enumerate + .map((e) => [e.value, if (filterFn == null || filterFn(e.key)) t]) + .expand((i) => i) + .toList() + ..removeLast()); + + List around(Widget t) => addToStart(t).addToEnd(t); + + List addToStart(Widget t) => + enumerate.map((e) => e.value).toList()..insert(0, t); + + List addToEnd(Widget t) => + enumerate.map((e) => e.value).toList()..add(t); + + List paddingTopEach(double val) => + map((w) => Padding(padding: EdgeInsets.only(top: val), child: w)) + .toList(); +} + +extension StatefulWidgetExtensions on State { + /// Check if the widget exist before safely setting state. + void safeSetState(VoidCallback fn) { + if (mounted) { + // ignore: invalid_use_of_protected_member + setState(fn); + } + } +} + +// For iOS 16 and below, set the status bar color to match the app's theme. +// https://github.com/flutter/flutter/issues/41067 +Brightness? _lastBrightness; +void fixStatusBarOniOS16AndBelow(BuildContext context) { + if (!isiOS) { + return; + } + final brightness = Theme.of(context).brightness; + if (_lastBrightness != brightness) { + _lastBrightness = brightness; + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle( + statusBarBrightness: brightness, + systemStatusBarContrastEnforced: true, + ), + ); + } +} + +extension ListUniqueExt on Iterable { + List unique(dynamic Function(T) getKey) { + var distinctSet = {}; + var distinctList = []; + for (var item in this) { + if (distinctSet.add(getKey(item))) { + distinctList.add(item); + } + } + return distinctList; + } +} + +String roundTo(double value, int decimalPoints) { + final power = pow(10, decimalPoints); + return ((value * power).round() / power).toString(); +} + +double computeGradientAlignmentX(double evaluatedAngle) { + evaluatedAngle %= 360; + final rads = evaluatedAngle * pi / 180; + double x; + if (evaluatedAngle < 45 || evaluatedAngle > 315) { + x = sin(2 * rads); + } else if (45 <= evaluatedAngle && evaluatedAngle <= 135) { + x = 1; + } else if (135 <= evaluatedAngle && evaluatedAngle <= 225) { + x = sin(-2 * rads); + } else { + x = -1; + } + return double.parse(roundTo(x, 2)); +} + +double computeGradientAlignmentY(double evaluatedAngle) { + evaluatedAngle %= 360; + final rads = evaluatedAngle * pi / 180; + double y; + if (evaluatedAngle < 45 || evaluatedAngle > 315) { + y = -1; + } else if (45 <= evaluatedAngle && evaluatedAngle <= 135) { + y = sin(-2 * rads); + } else if (135 <= evaluatedAngle && evaluatedAngle <= 225) { + y = 1; + } else { + y = sin(2 * rads); + } + return double.parse(roundTo(y, 2)); +} diff --git a/lib/flutter_flow/flutter_flow_widgets.dart b/lib/flutter_flow/flutter_flow_widgets.dart new file mode 100644 index 00000000..6cfe3d67 --- /dev/null +++ b/lib/flutter_flow/flutter_flow_widgets.dart @@ -0,0 +1,285 @@ +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:flutter/material.dart'; +import 'package:auto_size_text/auto_size_text.dart'; + +class FFButtonOptions { + const FFButtonOptions({ + this.textStyle, + this.elevation, + this.height, + this.width, + this.padding, + this.color, + this.disabledColor, + this.disabledTextColor, + this.splashColor, + this.iconSize, + this.iconColor, + this.iconPadding, + this.borderRadius, + this.borderSide, + this.hoverColor, + this.hoverBorderSide, + this.hoverTextColor, + this.hoverElevation, + this.maxLines, + }); + + final TextStyle? textStyle; + final double? elevation; + final double? height; + final double? width; + final EdgeInsetsGeometry? padding; + final Color? color; + final Color? disabledColor; + final Color? disabledTextColor; + final int? maxLines; + final Color? splashColor; + final double? iconSize; + final Color? iconColor; + final EdgeInsetsGeometry? iconPadding; + final BorderRadius? borderRadius; + final BorderSide? borderSide; + final Color? hoverColor; + final BorderSide? hoverBorderSide; + final Color? hoverTextColor; + final double? hoverElevation; +} + +class FFButtonWidget extends StatefulWidget { + const FFButtonWidget({ + super.key, + required this.text, + required this.onPressed, + this.icon, + this.iconData, + required this.options, + this.showLoadingIndicator = true, + }); + + final String text; + final Widget? icon; + final IconData? iconData; + final Function()? onPressed; + final FFButtonOptions options; + final bool showLoadingIndicator; + + @override + State createState() => _FFButtonWidgetState(); +} + +class _FFButtonWidgetState extends State { + bool loading = false; + + int get maxLines => widget.options.maxLines ?? 1; + String? get text => + widget.options.textStyle?.fontSize == 0 ? null : widget.text; + + @override + Widget build(BuildContext context) { + Widget textWidget = loading + ? SizedBox( + width: widget.options.width == null + ? _getTextWidth(text, widget.options.textStyle, maxLines) + : null, + child: Center( + child: SizedBox( + width: 23, + height: 23, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + widget.options.textStyle?.color ?? Colors.white, + ), + ), + ), + ), + ) + : AutoSizeText( + text ?? '', + style: + text == null ? null : widget.options.textStyle?.withoutColor(), + maxLines: maxLines, + overflow: TextOverflow.ellipsis, + ); + + final onPressed = widget.onPressed != null + ? (widget.showLoadingIndicator + ? () async { + if (loading) { + return; + } + setState(() => loading = true); + try { + await widget.onPressed!(); + } finally { + if (mounted) { + setState(() => loading = false); + } + } + } + : () => widget.onPressed!()) + : null; + + ButtonStyle style = ButtonStyle( + shape: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.hovered) && + widget.options.hoverBorderSide != null) { + return RoundedRectangleBorder( + borderRadius: + widget.options.borderRadius ?? BorderRadius.circular(8), + side: widget.options.hoverBorderSide!, + ); + } + return RoundedRectangleBorder( + borderRadius: + widget.options.borderRadius ?? BorderRadius.circular(8), + side: widget.options.borderSide ?? BorderSide.none, + ); + }, + ), + foregroundColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled) && + widget.options.disabledTextColor != null) { + return widget.options.disabledTextColor; + } + if (states.contains(MaterialState.hovered) && + widget.options.hoverTextColor != null) { + return widget.options.hoverTextColor; + } + return widget.options.textStyle?.color ?? Colors.white; + }, + ), + backgroundColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled) && + widget.options.disabledColor != null) { + return widget.options.disabledColor; + } + if (states.contains(MaterialState.hovered) && + widget.options.hoverColor != null) { + return widget.options.hoverColor; + } + return widget.options.color; + }, + ), + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.pressed)) { + return widget.options.splashColor; + } + return widget.options.hoverColor == null ? null : Colors.transparent; + }), + padding: MaterialStateProperty.all(widget.options.padding ?? + const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4.0)), + elevation: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.hovered) && + widget.options.hoverElevation != null) { + return widget.options.hoverElevation!; + } + return widget.options.elevation ?? 2.0; + }, + ), + ); + + if ((widget.icon != null || widget.iconData != null) && !loading) { + Widget icon = widget.icon ?? + FaIcon( + widget.iconData!, + size: widget.options.iconSize, + color: widget.options.iconColor, + ); + + if (text == null) { + return Container( + height: widget.options.height, + width: widget.options.width, + decoration: BoxDecoration( + border: Border.fromBorderSide( + widget.options.borderSide ?? BorderSide.none, + ), + borderRadius: + widget.options.borderRadius ?? BorderRadius.circular(8), + ), + child: IconButton( + splashRadius: 1.0, + icon: Padding( + padding: widget.options.iconPadding ?? EdgeInsets.zero, + child: icon, + ), + onPressed: onPressed, + style: style, + ), + ); + } + return SizedBox( + height: widget.options.height, + width: widget.options.width, + child: ElevatedButton.icon( + icon: Padding( + padding: widget.options.iconPadding ?? EdgeInsets.zero, + child: icon, + ), + label: textWidget, + onPressed: onPressed, + style: style, + ), + ); + } + + return SizedBox( + height: widget.options.height, + width: widget.options.width, + child: ElevatedButton( + onPressed: onPressed, + style: style, + child: textWidget, + ), + ); + } +} + +extension _WithoutColorExtension on TextStyle { + TextStyle withoutColor() => TextStyle( + inherit: inherit, + color: null, + backgroundColor: backgroundColor, + fontSize: fontSize, + fontWeight: fontWeight, + fontStyle: fontStyle, + letterSpacing: letterSpacing, + wordSpacing: wordSpacing, + textBaseline: textBaseline, + height: height, + leadingDistribution: leadingDistribution, + locale: locale, + foreground: foreground, + background: background, + shadows: shadows, + fontFeatures: fontFeatures, + decoration: decoration, + decorationColor: decorationColor, + decorationStyle: decorationStyle, + decorationThickness: decorationThickness, + debugLabel: debugLabel, + fontFamily: fontFamily, + fontFamilyFallback: fontFamilyFallback, + // The _package field is private so unfortunately we can't set it here, + // but it's almost always unset anyway. + // package: _package, + overflow: overflow, + ); +} + +// Slightly hacky method of getting the layout width of the provided text. +double? _getTextWidth(String? text, TextStyle? style, int maxLines) => + text != null + ? (TextPainter( + text: TextSpan(text: text, style: style), + textDirection: TextDirection.ltr, + maxLines: maxLines, + )..layout()) + .size + .width + : null; diff --git a/lib/flutter_flow/form_field_controller.dart b/lib/flutter_flow/form_field_controller.dart new file mode 100644 index 00000000..adcd778e --- /dev/null +++ b/lib/flutter_flow/form_field_controller.dart @@ -0,0 +1,10 @@ +import 'package:flutter/foundation.dart'; + +class FormFieldController extends ValueNotifier { + FormFieldController(this.initialValue) : super(initialValue); + + final T? initialValue; + + void reset() => value = initialValue; + void update() => notifyListeners(); +} diff --git a/lib/flutter_flow/internationalization.dart b/lib/flutter_flow/internationalization.dart new file mode 100644 index 00000000..b4a5794a --- /dev/null +++ b/lib/flutter_flow/internationalization.dart @@ -0,0 +1,1127 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +const _kLocaleStorageKey = '__locale_key__'; + +class FFLocalizations { + FFLocalizations(this.locale); + + final Locale locale; + + static FFLocalizations of(BuildContext context) => + Localizations.of(context, FFLocalizations)!; + + static List languages() => ['pt', 'en']; + + static late SharedPreferences _prefs; + static Future initialize() async => + _prefs = await SharedPreferences.getInstance(); + static Future storeLocale(String locale) => + _prefs.setString(_kLocaleStorageKey, locale); + static Locale? getStoredLocale() { + final locale = _prefs.getString(_kLocaleStorageKey); + return locale != null && locale.isNotEmpty ? createLocale(locale) : null; + } + + String get languageCode => locale.toString(); + String? get languageShortCode => + _languagesWithShortCode.contains(locale.toString()) + ? '${locale.toString()}_short' + : null; + int get languageIndex => languages().contains(languageCode) + ? languages().indexOf(languageCode) + : 0; + + String getText(String key) => + (kTranslationsMap[key] ?? {})[locale.toString()] ?? ''; + + String getVariableText({ + String? ptText = '', + String? enText = '', + }) => + [ptText, enText][languageIndex] ?? ''; + + static const Set _languagesWithShortCode = { + 'ar', + 'az', + 'ca', + 'cs', + 'da', + 'de', + 'dv', + 'en', + 'es', + 'et', + 'fi', + 'fr', + 'gr', + 'he', + 'hi', + 'hu', + 'it', + 'km', + 'ku', + 'mn', + 'ms', + 'no', + 'pt', + 'ro', + 'ru', + 'rw', + 'sv', + 'th', + 'uk', + 'vi', + }; +} + +class FFLocalizationsDelegate extends LocalizationsDelegate { + const FFLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) { + final language = locale.toString(); + return FFLocalizations.languages().contains( + language.endsWith('_') + ? language.substring(0, language.length - 1) + : language, + ); + } + + @override + Future load(Locale locale) => + SynchronousFuture(FFLocalizations(locale)); + + @override + bool shouldReload(FFLocalizationsDelegate old) => false; +} + +Locale createLocale(String language) => language.contains('_') + ? Locale.fromSubtags( + languageCode: language.split('_').first, + scriptCode: language.split('_').last, + ) + : Locale(language); + +final kTranslationsMap = >>[ + // LoginPage + { + '0113wf5c': { + 'pt': 'VAMOS LA! ENTRE COM A SUA CONTA', + 'en': 'LET\'S GO! SIGN IN WITH YOUR ACCOUNT', + }, + 'f2go5a71': { + 'pt': 'Email', + 'en': 'Email', + }, + 'paon3y0v': { + 'pt': 'Senha', + 'en': 'Password', + }, + 'wmbzwstw': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'j8567afe': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + 'y3wd9q18': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'j6ufb6sq': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + 'h85112qs': { + 'pt': 'Você esqueceu a sua senha?', + 'en': 'Have you forgotten your password?', + }, + 'di48hdaj': { + 'pt': ' Recupere aqui', + 'en': 'recover here', + }, + 'gx2fp6zq': { + 'pt': 'Termo de Uso', + 'en': 'Terms of use', + }, + 'ef5lm94r': { + 'pt': 'Home', + 'en': '', + }, + }, + // ForgotPasswordPage + { + 'gfvplb0h': { + 'pt': 'ESQUECEU SUA SENHA?', + 'en': 'FORGOT YOUR PASSWORD?', + }, + 'azssgpdi': { + 'pt': + 'Não se preucupe nós vamos te ajudar, digite o email cadastrado no aplicativo e clique em enviar.', + 'en': + 'Don\'t worry, we will help you, enter the email registered in the application and click send.', + }, + '0o139961': { + 'pt': 'Email', + 'en': 'Email', + }, + 'aanw1fp3': { + 'pt': 'digite o seu email.....', + 'en': 'enter your email.....', + }, + 'e7hdgc4q': { + 'pt': 'Enviar', + 'en': 'To send', + }, + '3xnxor0t': { + 'pt': 'Home', + 'en': '', + }, + }, + // homePage + { + 'lyiat6s2': { + 'pt': 'NOME DO MORADOR', + 'en': 'RESIDENT\'S NAME', + }, + '3jgvv75o': { + 'pt': '', + 'en': '', + }, + 'dlaeicxd': { + 'pt': 'Auto-Visita', + 'en': 'Self-Visit', + }, + '53jd930v': { + 'pt': 'Condominio', + 'en': 'Condominium', + }, + 'ptsx0rln': { + 'pt': 'Cadastrar Pet', + 'en': 'Register Pet', + }, + 'rgxgw626': { + 'pt': 'Cadastrar Visitante', + 'en': 'Register Visitor', + }, + 'j2tn9lpw': { + 'pt': 'QR Code de Acesso', + 'en': 'Access QR Code', + }, + '9weuwgs1': { + 'pt': 'Histórico de Acesso', + 'en': 'Access History', + }, + 'vuk5bjau': { + 'pt': 'Agendar Visita', + 'en': 'Schedule Visit', + }, + 'xx0db4wi': { + 'pt': 'Sair', + 'en': 'Logout', + }, + 'rg9pzkpz': { + 'pt': 'FRE ACCESS', + 'en': 'FREE ACCESS', + }, + 'mp6igsok': { + 'pt': 'Home', + 'en': '', + }, + }, + // RegisterPage + { + '2d8uulm3': { + 'pt': 'INSIRA SEU EMAIL E SENHA, VAMOS TE CADASTRAR!', + 'en': 'ENTER YOUR EMAIL AND PASSWORD, LET\'S REGISTER YOU!', + }, + '8kjhi406': { + 'pt': 'Nome', + 'en': 'Name', + }, + 'ro4zkkxp': { + 'pt': 'Email', + 'en': 'Email', + }, + 'j5yny8ee': { + 'pt': '', + 'en': '', + }, + 'lzgobioa': { + 'pt': 'Senha', + 'en': 'Password', + }, + 'c7sfyeh8': { + 'pt': 'Cadastrar-se', + 'en': 'Sign-Up', + }, + 'jglpa1tr': { + 'pt': 'Você já tem uma conta? ', + 'en': 'You already have an account?', + }, + 'hfcm0td9': { + 'pt': 'Clique aqui', + 'en': 'Click here', + }, + 'c3kno4t9': { + 'pt': 'Termo de Uso', + 'en': '', + }, + 'tzy6n0n4': { + 'pt': 'Home', + 'en': '', + }, + }, + // WelcomePage + { + 'xflxvs9y': { + 'pt': 'UMA EXPERIÊCIA COMPLETA', + 'en': 'A COMPLETE EXPERIENCE', + }, + '5a86wzd1': { + 'pt': 'COM CONFORTO ONDE VOCÊ ESTIVER.', + 'en': 'WITH COMFORT WHEREVER YOU ARE.', + }, + '65nuva6j': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + '9u6oaw01': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + 'd1qem43w': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'bhowzv2u': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + 'qls72pio': { + 'pt': 'Home', + 'en': '', + }, + }, + // registerVisitorPage + { + 'q8cct5lk': { + 'pt': 'Cadastrar Visitante', + 'en': 'Register Visitor', + }, + 'p4ftwxcy': { + 'pt': 'Clique para adicionar a foto para o visitante', + 'en': 'Click to add photo for visitor', + }, + 'zazj5d8b': { + 'pt': 'Preencha o formulário com os dados do visitante', + 'en': 'Fill in the form with the visitor\'s data', + }, + 'v7g73yik': { + 'pt': 'Nome', + 'en': 'Name', + }, + 'yp23q90m': { + 'pt': 'Selecione o tipo:', + 'en': 'Select type:', + }, + 'n8vddmcq': { + 'pt': 'Visitante ', + 'en': 'Visitor', + }, + '9luaa09e': { + 'pt': 'Prestador de Serviço', + 'en': 'Service provider', + }, + 'pmezihb4': { + 'pt': 'Selecione...', + 'en': 'Please select...', + }, + 'yza6i4t7': { + 'pt': 'Search for an item...', + 'en': '', + }, + 'rl8tvwnr': { + 'pt': 'Documento', + 'en': 'Document', + }, + 'bqpucwh0': { + 'pt': 'Contatos', + 'en': 'Contacts', + }, + 'h84ls2r6': { + 'pt': 'Telefone', + 'en': 'Telephone', + }, + 'fqp7qmka': { + 'pt': 'Email', + 'en': 'Email', + }, + 'okbw0aiu': { + 'pt': 'Cadastrar', + 'en': 'Register', + }, + 'xtcz66ar': { + 'pt': 'registerVisitor', + 'en': '', + }, + }, + // scheduleCompleteVisitPage + { + 'qo0pg2at': { + 'pt': 'Quais visitantes você deseja cadastrar?', + 'en': 'Which visitors do you want to register?', + }, + 'i0jhuu3e': { + 'pt': 'Clique para adicionar um visitante', + 'en': 'Click to add a visitor', + }, + 'z4ry3tge': { + 'pt': 'Qual o período de validade da visita?', + 'en': 'Visit Validity Period', + }, + 'hjp5mzbd': { + 'pt': 'Inicio da Visita', + 'en': 'Start of Visit', + }, + '2in5sljf': { + 'pt': '', + 'en': 'End of Visit', + }, + 'ce6xryf4': { + 'pt': 'Quando você inicia a visita?', + 'en': 'When do you start the visit?', + }, + 'jwsbk0xu': { + 'pt': 'Fim da Visita', + 'en': 'End of Visit', + }, + '87rlxmbk': { + 'pt': '', + 'en': 'End of Visit', + }, + 'lyfe46f6': { + 'pt': 'Quando a visita terminá?', + 'en': 'When will the visit end?', + }, + 'p81uol2v': { + 'pt': 'Quais são os motivos da visita?', + 'en': 'What are the reasons for the visit?', + }, + 'bbauep0b': { + 'pt': 'Motivo da Visita', + 'en': 'End of Visit', + }, + 'x1ij847i': { + 'pt': 'Escolha um motivo aqui', + 'en': 'Choose a reason here', + }, + 'ejyyypuz': { + 'pt': 'Search for an item...', + 'en': '', + }, + 'etzbm8l5': { + 'pt': 'Nível de Acesso', + 'en': 'End of Visit', + }, + 'kmgv5j7x': { + 'pt': 'Escolha um nível de acesso aqui', + 'en': 'Choose an access level here', + }, + 'izwi0ya7': { + 'pt': 'Search for an item...', + 'en': '', + }, + 'mddp33o0': { + 'pt': 'Visita se encerra após o primeiro acesso?', + 'en': 'Does the visit end after the first access?', + }, + '68j9gw4h': { + 'pt': 'Visita única', + 'en': 'Single visit', + }, + '9rudpkq7': { + 'pt': 'Você tem alguma observação sobre está visita?', + 'en': 'Do you have any observations about this visit?', + }, + '4rgpxrfe': { + 'pt': 'Observações da Visita', + 'en': 'Visit Observations', + }, + '7knytis2': { + 'pt': 'Escreva as suas observações aqui', + 'en': 'Write your observations here', + }, + 'bvioevav': { + 'pt': 'Ativo', + 'en': 'Active', + }, + '295oz5is': { + 'pt': '16/10/2024', + 'en': '16/10/2024', + }, + '07h0w8ki': { + 'pt': '16/10/2024', + 'en': '16/10/2024', + }, + 'd34nuw4w': { + 'pt': 'Visitante:', + 'en': 'Visitor:', + }, + 'y8geteyc': { + 'pt': ' Lucas Martin Mota', + 'en': 'Lucas Martin Mota', + }, + 'gxdykms1': { + 'pt': 'Morador:', + 'en': 'Resident:', + }, + 'ue7wkm9r': { + 'pt': ' Lucas Martin Mota', + 'en': 'Lucas Martin Mota', + }, + 'zs8s0wd3': { + 'pt': 'Validade:', + 'en': 'Validity:', + }, + 'z7fset9r': { + 'pt': ' 16/10/2024 a 16/10/2024', + 'en': ' 16/10/2024 a 16/10/2024', + }, + 'fcb5avae': { + 'pt': 'Agendamento Ativo', + 'en': 'Active Scheduling', + }, + '61lcxdgm': { + 'pt': 'Agendar Visita', + 'en': 'Schedule Visit', + }, + 'v3mpyspm': { + 'pt': 'scheduleVisit', + 'en': '', + }, + }, + // scheduleProvisionalVisitPage + { + 'n7bbd202': { + 'pt': 'Agendamento Provisório', + 'en': 'Provisional Scheduling', + }, + 'i4xujgbn': { + 'pt': 'Visita Provisória', + 'en': 'Provisional Visit', + }, + 'x7at46ur': { + 'pt': 'Quais visitantes você deseja cadastrar?', + 'en': 'Which visitors do you want to register?', + }, + 'shj19b2o': { + 'pt': 'Qual o período de validade da visita?', + 'en': 'Visit Validity Period', + }, + '8zgsw5so': { + 'pt': 'Ínicio da Visita', + 'en': 'Start of the Visit', + }, + 'p16wm7kp': { + 'pt': 'Quando a visitas se inicia?', + 'en': 'When does the visit start?', + }, + '3zfd7uf9': { + 'pt': 'Qual o nome do visitante?', + 'en': 'What is the visitor\'s name?', + }, + 'wehvxbz4': { + 'pt': 'Nome do Visitante', + 'en': 'Visitor Name', + }, + 'juh7f24w': { + 'pt': 'Escreva o nome do visitante aqui', + 'en': 'Write the visitor\'s name here', + }, + 'jhss056s': { + 'pt': 'Você tem alguma observação sobre está visita?', + 'en': 'Do you have any observations about this visit?', + }, + 'cw8b3tbb': { + 'pt': 'Observações da Visita', + 'en': 'Visit Observations', + }, + 'k4qkbv1f': { + 'pt': 'Escreva as suas observações aqui', + 'en': 'Write your observations here', + }, + 'lhzhh2jb': { + 'pt': 'scheduleVisit', + 'en': '', + }, + }, + // onBoardingPage + { + '6exl3e75': { + 'pt': 'Home', + 'en': '', + }, + }, + // fastPassPage + { + 'koh6s96f': { + 'pt': 'Home', + 'en': '', + }, + }, + // visitorDetailsModal + { + 'kqzf7nx2': { + 'pt': 'Nome do Visitante', + 'en': 'Visitor Name', + }, + 'hz7ivuqn': { + 'pt': 'Tipo de Visitante', + 'en': 'Visitor Type', + }, + 'rwqn0det': { + 'pt': '(00) 0 0000-0000', + 'en': 'Telephone', + }, + '0wqbiekp': { + 'pt': 'email@provider.etc', + 'en': 'Email', + }, + }, + // throwException + { + 'e58xxxiq': { + 'pt': 'ERRO', + 'en': 'ERROR', + }, + }, + // regisiterVistorComponent + { + 'wnhkedzt': { + 'pt': 'Cadastrar Visitante', + 'en': 'Register Visitor', + }, + 'kpd31z4d': { + 'pt': 'Clique para adicionar a foto para o visitante', + 'en': 'Click to add photo for visitor', + }, + 'q986vs4m': { + 'pt': 'Preencha o formulário com os dados do visitante', + 'en': 'Fill in the form with the visitor\'s data', + }, + 'llcw2tei': { + 'pt': 'Nome', + 'en': 'Name', + }, + '67ykbznt': { + 'pt': 'Selecione o tipo:', + 'en': 'Select type:', + }, + 'ugjkeiz7': { + 'pt': 'Visitante ', + 'en': 'Visitor', + }, + '8nlk5xlk': { + 'pt': 'Prestador de Serviço', + 'en': 'Service provider', + }, + 'kw07i43y': { + 'pt': 'Selecione...', + 'en': 'Please select...', + }, + 'e887o707': { + 'pt': 'Search for an item...', + 'en': '', + }, + '96ayre48': { + 'pt': 'Documento', + 'en': 'Document', + }, + 'j0g7ggs2': { + 'pt': 'Contatos', + 'en': 'Contacts', + }, + 'ybdjabnd': { + 'pt': 'Telefone', + 'en': 'Telephone', + }, + 'tlr6uxo4': { + 'pt': 'Email', + 'en': 'Email', + }, + '65puvap9': { + 'pt': 'Cadastrar', + 'en': 'Register', + }, + }, + // visitorSearchComponent + { + 'cjlpru1m': { + 'pt': 'Procure pelo documento do visitante ', + 'en': 'Search for the visitor\'s document', + }, + '8i1qszba': { + 'pt': 'test', + 'en': '', + }, + 'oj12tamm': { + 'pt': 'test', + 'en': '', + }, + '9coywebh': { + 'pt': 'Visitantes encontrados', + 'en': 'Visitors Found', + }, + '6f5p0fv6': { + 'pt': '24', + 'en': '24', + }, + 'ug6qzyla': { + 'pt': 'Adicionar', + 'en': 'To add', + }, + }, + // visitorNotFoundComponent + { + '1p9mykbj': { + 'pt': 'Usuário não encontrado', + 'en': 'User not found', + }, + 'kt937sp6': { + 'pt': + 'O documento inserido não corresponde a nenhum usuário cadastrado no sistema. Verifique o documento inserido ou adicione um novo visitante ao sistema.', + 'en': + 'The document inserted does not correspond to any user registered in the system. Check the inserted document or add a new visitor to the system.', + }, + 'y2x4nfcn': { + 'pt': 'Adicionar ', + 'en': 'To add', + }, + }, + // viewVisitDetail + { + '9yu35pzg': { + 'pt': 'Encerramento da Visita', + 'en': 'Closing of the Visit', + }, + 'aj6scczp': { + 'pt': 'Início', + 'en': 'Start', + }, + 'ub084nhy': { + 'pt': 'dd/mm/yyyy', + 'en': 'dd/mm/yyyy', + }, + 'rvi5z7wg': { + 'pt': 'Término', + 'en': 'Termination', + }, + 'ixs67mrz': { + 'pt': 'dd/mm/yyyy', + 'en': 'dd/mm/yyyy', + }, + 'yxilg7ek': { + 'pt': 'Motivo da Visita', + 'en': 'Start of the Visit', + }, + 'ypeydbem': { + 'pt': 'Motivo', + 'en': 'Reason', + }, + 'dgr3pk3a': { + 'pt': 'Nível de Acesso', + 'en': 'Access Level', + }, + 'rs3d4gb8': { + 'pt': 'Nível de Acesso', + 'en': '', + }, + 'lppn9rxa': { + 'pt': 'Observações da Visita', + 'en': 'Visit Observations', + }, + }, + // scheduleVisitDetail + { + '7w4fohoa': { + 'pt': 'Encerramento da Visita', + 'en': 'Closing of the Visit', + }, + 'snah4iet': { + 'pt': 'Início', + 'en': 'Start', + }, + '0cp1e31d': { + 'pt': 'dd/mm/yyyy', + 'en': 'dd/mm/yyyy', + }, + 'abppdgz3': { + 'pt': 'Término', + 'en': 'Termination', + }, + 'kqralft4': { + 'pt': 'dd/mm/yyyy', + 'en': 'dd/mm/yyyy', + }, + 'xjxhzqqm': { + 'pt': 'Motivo da Visita', + 'en': 'Start of the Visit', + }, + '47oezdm6': { + 'pt': 'Motivo', + 'en': 'Reason', + }, + '2ujg7u18': { + 'pt': 'Nível de Acesso', + 'en': 'Access Level', + }, + '3emmbbfv': { + 'pt': 'Nível de Acesso', + 'en': '', + }, + 'ritce5uw': { + 'pt': 'Observações da Visita', + 'en': 'Visit Observations', + }, + }, + // optionSelectionModal + { + 'omxabblt': { + 'pt': 'Agenda \nRápida', + 'en': 'Schedule \nQuick', + }, + 'vpy51li0': { + 'pt': 'Agenda\nProvisória', + 'en': 'Schedule\nProvisional', + }, + '8ad3hms9': { + 'pt': 'Agenda\nCompleta', + 'en': 'Schedule\nComplete', + }, + }, + // menuListViewComponent + { + 'utgue9a5': { + 'pt': 'Agendar \nVisita', + 'en': 'Schedule \nVisit', + }, + '82b5f8yz': { + 'pt': 'Cadastrar\nVisitante', + 'en': 'Register\nVisitor', + }, + 't4ie13ut': { + 'pt': 'Vincular \nCondomínio', + 'en': 'Link\nCondominium', + }, + 'n3n76pha': { + 'pt': 'Cadastrar \nPet', + 'en': 'Register\npet', + }, + 'l6b9o7yn': { + 'pt': 'QR Code \nde Acesso', + 'en': 'QR Code\nAccess', + }, + }, + // menuStaggeredViewComponent + { + 'ee33l0ms': { + 'pt': 'Agendar \nVisita', + 'en': 'Schedule \nVisit', + }, + 'ya37l3jt': { + 'pt': 'Cadastrar\n Visitante', + 'en': 'Register\n Visitor', + }, + 'h8s3adu8': { + 'pt': 'Vincular\nCondomínio', + 'en': 'Link\nCondominium', + }, + 'j6tfixen': { + 'pt': 'Cadastrar\nPet', + 'en': 'Register\npet', + }, + '9tli4i2x': { + 'pt': 'QR Code\nde Acesso', + 'en': 'QR Code\nAccess', + }, + }, + // messageWellComponent + { + '8fworxmb': { + 'pt': 'Mural de Mensagens', + 'en': 'Message Wall', + }, + 'yikill36': { + 'pt': 'Todos', + 'en': 'All', + }, + }, + // signInComponent + { + '9hbdjxrz': { + 'pt': 'VAMOS LA! ENTRE COM A SUA CONTA', + 'en': 'LET\'S GO! SIGN IN WITH YOUR ACCOUNT', + }, + '1ltg0ylb': { + 'pt': 'Email', + 'en': 'Email', + }, + '2x19ce8k': { + 'pt': 'Senha', + 'en': 'Password', + }, + 'k44tm7wo': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + '14u7ipws': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + '1x926nsn': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'jwvd4ai1': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + '05dx91ku': { + 'pt': 'Você esqueceu a sua senha?', + 'en': 'Have you forgotten your password?', + }, + 'p5c6d54y': { + 'pt': ' Recupere aqui', + 'en': 'recover here', + }, + 'olf967cj': { + 'pt': 'Termo de Uso', + 'en': 'Terms of use', + }, + }, + // signUpComponent + { + '49609olv': { + 'pt': 'INSIRA SEU EMAIL E SENHA, VAMOS TE CADASTRAR!', + 'en': 'ENTER YOUR EMAIL AND PASSWORD, LET\'S REGISTER YOU!', + }, + '3corpwhd': { + 'pt': 'Nome', + 'en': 'Name', + }, + '80wonb69': { + 'pt': 'Email', + 'en': 'Email', + }, + 'ws143wf4': { + 'pt': '', + 'en': '', + }, + '0firji8l': { + 'pt': 'Senha', + 'en': 'Password', + }, + 'rnvdwzei': { + 'pt': 'Cadastrar-se', + 'en': 'Sign-Up', + }, + 'a9smhn5b': { + 'pt': 'Você já tem uma conta? ', + 'en': 'You already have an account?', + }, + '09xv5ctc': { + 'pt': 'Clique aqui', + 'en': 'Click here', + }, + 'huygnka2': { + 'pt': 'Termo de Uso', + 'en': '', + }, + }, + // welcomeComponent + { + 'dsc9tuc8': { + 'pt': 'UMA EXPERIÊCIA COMPLETA', + 'en': 'A COMPLETE EXPERIENCE', + }, + '5bgqn16z': { + 'pt': 'COM CONFORTO ONDE VOCÊ ESTIVER.', + 'en': 'WITH COMFORT WHEREVER YOU ARE.', + }, + 'dynet730': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'hha60cg7': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + 'zvtay8ee': { + 'pt': 'Entrar', + 'en': 'Sign-In', + }, + 'o6zob50a': { + 'pt': 'Cadastrar', + 'en': 'Sign-Up', + }, + }, + // forgotPasswordComponent + { + 'xxm3ajsy': { + 'pt': 'ESQUECEU SUA SENHA?', + 'en': 'FORGOT YOUR PASSWORD?', + }, + 'wu2f7yzo': { + 'pt': + 'Não se preucupe nós vamos te ajudar, digite o email cadastrado no aplicativo e clique em enviar.', + 'en': + 'Don\'t worry, we will help you, enter the email registered in the application and click send.', + }, + 'mtz8l7ft': { + 'pt': 'Email', + 'en': 'Email', + }, + 'w7y5wlnv': { + 'pt': 'digite o seu email.....', + 'en': 'enter your email.....', + }, + '74rnd5bu': { + 'pt': 'Enviar', + 'en': 'To send', + }, + }, + // selectHeaderComponent + { + '1gr8ztd5': { + 'pt': 'Criar Agendamento', + 'en': 'Create Schedule', + }, + 'xjahsbjw': { + 'pt': 'Histórico de Visitas', + 'en': 'Visit History', + }, + }, + // Miscellaneous + { + 'i5smty81': { + 'pt': '', + 'en': 'dd/mm/yyyy', + }, + 'kw89v4f5': { + 'pt': '', + 'en': '', + }, + '7zjyxhuq': { + 'pt': '', + 'en': '', + }, + 'd86ioepz': { + 'pt': '', + 'en': '', + }, + 'lt3ssl76': { + 'pt': '', + 'en': '', + }, + 'fng3jimx': { + 'pt': '', + 'en': '', + }, + 'fl5g3od1': { + 'pt': '', + 'en': '', + }, + 'ypvz2z2w': { + 'pt': '', + 'en': '', + }, + '8qc8ukp7': { + 'pt': '', + 'en': '', + }, + '2e7jypoo': { + 'pt': '', + 'en': '', + }, + '3ns1uuql': { + 'pt': '', + 'en': '', + }, + '6wpbd6qf': { + 'pt': '', + 'en': '', + }, + '8lujanjg': { + 'pt': '', + 'en': '', + }, + 'uteo7q4l': { + 'pt': '', + 'en': '', + }, + 'fddqwa3t': { + 'pt': '', + 'en': '', + }, + 'qt1hznnl': { + 'pt': '', + 'en': '', + }, + 'ifdxkz4h': { + 'pt': '', + 'en': '', + }, + 'mrvjp805': { + 'pt': '', + 'en': '', + }, + '9n5qf96i': { + 'pt': '', + 'en': '', + }, + 'lmtedmcu': { + 'pt': '', + 'en': '', + }, + 'a8q9pni2': { + 'pt': '', + 'en': '', + }, + 'awm7dfw0': { + 'pt': '', + 'en': '', + }, + 'lradbjb6': { + 'pt': '', + 'en': '', + }, + 'j9igyop7': { + 'pt': '', + 'en': '', + }, + '7wsvuydm': { + 'pt': '', + 'en': '', + }, + 'vm22i4rf': { + 'pt': '', + 'en': '', + }, + 'uirsdmbi': { + 'pt': '', + 'en': '', + }, + 'm6r7vsdc': { + 'pt': '', + 'en': '', + }, + 'mqw2z9f3': { + 'pt': '', + 'en': '', + }, + }, +].reduce((a, b) => a..addAll(b)); diff --git a/lib/flutter_flow/lat_lng.dart b/lib/flutter_flow/lat_lng.dart new file mode 100644 index 00000000..9e7b8ea8 --- /dev/null +++ b/lib/flutter_flow/lat_lng.dart @@ -0,0 +1,19 @@ +class LatLng { + const LatLng(this.latitude, this.longitude); + final double latitude; + final double longitude; + + @override + String toString() => 'LatLng(lat: $latitude, lng: $longitude)'; + + String serialize() => '$latitude,$longitude'; + + @override + int get hashCode => latitude.hashCode + longitude.hashCode; + + @override + bool operator ==(other) => + other is LatLng && + latitude == other.latitude && + longitude == other.longitude; +} diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart new file mode 100644 index 00000000..e3a792e2 --- /dev/null +++ b/lib/flutter_flow/nav/nav.dart @@ -0,0 +1,346 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '/backend/schema/structs/index.dart'; + +import '/index.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; + +export 'package:go_router/go_router.dart'; +export 'serialization_util.dart'; + +const kTransitionInfoKey = '__transition_info__'; + +class AppStateNotifier extends ChangeNotifier { + AppStateNotifier._(); + + static AppStateNotifier? _instance; + static AppStateNotifier get instance => _instance ??= AppStateNotifier._(); + + bool showSplashImage = true; + + void stopShowingSplashImage() { + showSplashImage = false; + notifyListeners(); + } +} + +GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( + initialLocation: '/', + debugLogDiagnostics: true, + refreshListenable: appStateNotifier, + errorBuilder: (context, state) => appStateNotifier.showSplashImage + ? Builder( + builder: (context) => Container( + color: FlutterFlowTheme.of(context).primary, + child: Image.asset( + 'assets/images/logo.svg', + fit: BoxFit.cover, + ), + ), + ) + : const OnBoardingPageWidget(), + routes: [ + FFRoute( + name: '_initialize', + path: '/', + builder: (context, _) => appStateNotifier.showSplashImage + ? Builder( + builder: (context) => Container( + color: FlutterFlowTheme.of(context).primary, + child: Image.asset( + 'assets/images/logo.svg', + fit: BoxFit.cover, + ), + ), + ) + : const OnBoardingPageWidget(), + ), + FFRoute( + name: 'LoginPage', + path: '/loginPage', + builder: (context, params) => LoginPageWidget( + device: params.getParam( + 'device', + ParamType.String, + ), + ), + ), + FFRoute( + name: 'ForgotPasswordPage', + path: '/forgotPasswordPage', + builder: (context, params) => const ForgotPasswordPageWidget(), + ), + FFRoute( + name: 'homePage', + path: '/homePage', + builder: (context, params) => const HomePageWidget(), + ), + FFRoute( + name: 'RegisterPage', + path: '/registerPage', + builder: (context, params) => const RegisterPageWidget(), + ), + FFRoute( + name: 'WelcomePage', + path: '/welcomePage', + builder: (context, params) => const WelcomePageWidget(), + ), + FFRoute( + name: 'registerVisitorPage', + path: '/registerVisitorPage', + builder: (context, params) => const RegisterVisitorPageWidget(), + ), + FFRoute( + name: 'scheduleCompleteVisitPage', + path: '/scheduleCompleteVisitPage', + builder: (context, params) => ScheduleCompleteVisitPageWidget( + visitorStrList: params.getParam( + 'visitorStrList', + ParamType.String, + ), + visitStartDateStr: params.getParam( + 'visitStartDateStr', + ParamType.String, + ), + visitEndDateStr: params.getParam( + 'visitEndDateStr', + ParamType.String, + ), + visitReasonStr: params.getParam( + 'visitReasonStr', + ParamType.String, + ), + visitLevelStr: params.getParam( + 'visitLevelStr', + ParamType.String, + ), + visitTempBol: params.getParam( + 'visitTempBol', + ParamType.bool, + ), + visitObsStr: params.getParam( + 'visitObsStr', + ParamType.String, + ), + visitorJsonList: params.getParam( + 'visitorJsonList', + ParamType.JSON, + isList: true, + ), + ), + ), + FFRoute( + name: 'scheduleProvisionalVisitPage', + path: '/scheduleProvisionalVisitPage', + builder: (context, params) => const ScheduleProvisionalVisitPageWidget(), + ), + FFRoute( + name: 'onBoardingPage', + path: '/onBoardingPage', + builder: (context, params) => const OnBoardingPageWidget(), + ), + FFRoute( + name: 'fastPassPage', + path: '/fastPassPage', + builder: (context, params) => const FastPassPageWidget(), + ) + ].map((r) => r.toRoute(appStateNotifier)).toList(), + ); + +extension NavParamExtensions on Map { + Map get withoutNulls => Map.fromEntries( + entries + .where((e) => e.value != null) + .map((e) => MapEntry(e.key, e.value!)), + ); +} + +extension NavigationExtensions on BuildContext { + void safePop() { + // If there is only one route on the stack, navigate to the initial + // page instead of popping. + if (canPop()) { + pop(); + } else { + go('/'); + } + } +} + +extension _GoRouterStateExtensions on GoRouterState { + Map get extraMap => + extra != null ? extra as Map : {}; + Map get allParams => {} + ..addAll(pathParameters) + ..addAll(uri.queryParameters) + ..addAll(extraMap); + TransitionInfo get transitionInfo => extraMap.containsKey(kTransitionInfoKey) + ? extraMap[kTransitionInfoKey] as TransitionInfo + : TransitionInfo.appDefault(); +} + +class FFParameters { + FFParameters(this.state, [this.asyncParams = const {}]); + + final GoRouterState state; + final Map Function(String)> asyncParams; + + Map futureParamValues = {}; + + // Parameters are empty if the params map is empty or if the only parameter + // present is the special extra parameter reserved for the transition info. + bool get isEmpty => + state.allParams.isEmpty || + (state.allParams.length == 1 && + state.extraMap.containsKey(kTransitionInfoKey)); + bool isAsyncParam(MapEntry param) => + asyncParams.containsKey(param.key) && param.value is String; + bool get hasFutures => state.allParams.entries.any(isAsyncParam); + Future completeFutures() => Future.wait( + state.allParams.entries.where(isAsyncParam).map( + (param) async { + final doc = await asyncParams[param.key]!(param.value) + .onError((_, __) => null); + if (doc != null) { + futureParamValues[param.key] = doc; + return true; + } + return false; + }, + ), + ).onError((_, __) => [false]).then((v) => v.every((e) => e)); + + dynamic getParam( + String paramName, + ParamType type, { + bool isList = false, + StructBuilder? structBuilder, + }) { + if (futureParamValues.containsKey(paramName)) { + return futureParamValues[paramName]; + } + if (!state.allParams.containsKey(paramName)) { + return null; + } + final param = state.allParams[paramName]; + // Got parameter from `extras`, so just directly return it. + if (param is! String) { + return param; + } + // Return serialized value. + return deserializeParam( + param, + type, + isList, + structBuilder: structBuilder, + ); + } +} + +class FFRoute { + const FFRoute({ + required this.name, + required this.path, + required this.builder, + this.requireAuth = false, + this.asyncParams = const {}, + this.routes = const [], + }); + + final String name; + final String path; + final bool requireAuth; + final Map Function(String)> asyncParams; + final Widget Function(BuildContext, FFParameters) builder; + final List routes; + + GoRoute toRoute(AppStateNotifier appStateNotifier) => GoRoute( + name: name, + path: path, + pageBuilder: (context, state) { + fixStatusBarOniOS16AndBelow(context); + final ffParams = FFParameters(state, asyncParams); + final page = ffParams.hasFutures + ? FutureBuilder( + future: ffParams.completeFutures(), + builder: (context, _) => builder(context, ffParams), + ) + : builder(context, ffParams); + final child = page; + + final transitionInfo = state.transitionInfo; + return transitionInfo.hasTransition + ? CustomTransitionPage( + key: state.pageKey, + child: child, + transitionDuration: transitionInfo.duration, + transitionsBuilder: + (context, animation, secondaryAnimation, child) => + PageTransition( + type: transitionInfo.transitionType, + duration: transitionInfo.duration, + reverseDuration: transitionInfo.duration, + alignment: transitionInfo.alignment, + child: child, + ).buildTransitions( + context, + animation, + secondaryAnimation, + child, + ), + ) + : MaterialPage(key: state.pageKey, child: child); + }, + routes: routes, + ); +} + +class TransitionInfo { + const TransitionInfo({ + required this.hasTransition, + this.transitionType = PageTransitionType.fade, + this.duration = const Duration(milliseconds: 300), + this.alignment, + }); + + final bool hasTransition; + final PageTransitionType transitionType; + final Duration duration; + final Alignment? alignment; + + static TransitionInfo appDefault() => const TransitionInfo(hasTransition: false); +} + +class RootPageContext { + const RootPageContext(this.isRootPage, [this.errorRoute]); + final bool isRootPage; + final String? errorRoute; + + static bool isInactiveRootPage(BuildContext context) { + final rootPageContext = context.read(); + final isRootPage = rootPageContext?.isRootPage ?? false; + final location = GoRouterState.of(context).uri.toString(); + return isRootPage && + location != '/' && + location != rootPageContext?.errorRoute; + } + + static Widget wrap(Widget child, {String? errorRoute}) => Provider.value( + value: RootPageContext(true, errorRoute), + child: child, + ); +} + +extension GoRouterLocationExtension on GoRouter { + String getCurrentLocation() { + final RouteMatch lastMatch = routerDelegate.currentConfiguration.last; + final RouteMatchList matchList = lastMatch is ImperativeRouteMatch + ? lastMatch.matches + : routerDelegate.currentConfiguration; + return matchList.uri.toString(); + } +} diff --git a/lib/flutter_flow/nav/serialization_util.dart b/lib/flutter_flow/nav/serialization_util.dart new file mode 100644 index 00000000..1de6e7b5 --- /dev/null +++ b/lib/flutter_flow/nav/serialization_util.dart @@ -0,0 +1,227 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; + +import '/backend/schema/structs/index.dart'; +import '/backend/schema/enums/enums.dart'; + +import '../../flutter_flow/lat_lng.dart'; +import '../../flutter_flow/place.dart'; +import '../../flutter_flow/uploaded_file.dart'; + +/// SERIALIZATION HELPERS + +String dateTimeRangeToString(DateTimeRange dateTimeRange) { + final startStr = dateTimeRange.start.millisecondsSinceEpoch.toString(); + final endStr = dateTimeRange.end.millisecondsSinceEpoch.toString(); + return '$startStr|$endStr'; +} + +String placeToString(FFPlace place) => jsonEncode({ + 'latLng': place.latLng.serialize(), + 'name': place.name, + 'address': place.address, + 'city': place.city, + 'state': place.state, + 'country': place.country, + 'zipCode': place.zipCode, + }); + +String uploadedFileToString(FFUploadedFile uploadedFile) => + uploadedFile.serialize(); + +String? serializeParam( + dynamic param, + ParamType paramType, [ + bool isList = false, +]) { + try { + if (param == null) { + return null; + } + if (isList) { + final serializedValues = (param as Iterable) + .map((p) => serializeParam(p, paramType, false)) + .where((p) => p != null) + .map((p) => p!) + .toList(); + return json.encode(serializedValues); + } + switch (paramType) { + case ParamType.int: + return param.toString(); + case ParamType.double: + return param.toString(); + case ParamType.String: + return param; + case ParamType.bool: + return param ? 'true' : 'false'; + case ParamType.DateTime: + return (param as DateTime).millisecondsSinceEpoch.toString(); + case ParamType.DateTimeRange: + return dateTimeRangeToString(param as DateTimeRange); + case ParamType.LatLng: + return (param as LatLng).serialize(); + case ParamType.Color: + return (param as Color).toCssString(); + case ParamType.FFPlace: + return placeToString(param as FFPlace); + case ParamType.FFUploadedFile: + return uploadedFileToString(param as FFUploadedFile); + case ParamType.JSON: + return json.encode(param); + + case ParamType.DataStruct: + return param is BaseStruct ? param.serialize() : null; + + case ParamType.Enum: + return (param is Enum) ? param.serialize() : null; + + default: + return null; + } + } catch (e) { + print('Error serializing parameter: $e'); + return null; + } +} + +/// END SERIALIZATION HELPERS + +/// DESERIALIZATION HELPERS + +DateTimeRange? dateTimeRangeFromString(String dateTimeRangeStr) { + final pieces = dateTimeRangeStr.split('|'); + if (pieces.length != 2) { + return null; + } + return DateTimeRange( + start: DateTime.fromMillisecondsSinceEpoch(int.parse(pieces.first)), + end: DateTime.fromMillisecondsSinceEpoch(int.parse(pieces.last)), + ); +} + +LatLng? latLngFromString(String? latLngStr) { + final pieces = latLngStr?.split(','); + if (pieces == null || pieces.length != 2) { + return null; + } + return LatLng( + double.parse(pieces.first.trim()), + double.parse(pieces.last.trim()), + ); +} + +FFPlace placeFromString(String placeStr) { + final serializedData = jsonDecode(placeStr) as Map; + final data = { + 'latLng': serializedData.containsKey('latLng') + ? latLngFromString(serializedData['latLng'] as String) + : const LatLng(0.0, 0.0), + 'name': serializedData['name'] ?? '', + 'address': serializedData['address'] ?? '', + 'city': serializedData['city'] ?? '', + 'state': serializedData['state'] ?? '', + 'country': serializedData['country'] ?? '', + 'zipCode': serializedData['zipCode'] ?? '', + }; + return FFPlace( + latLng: data['latLng'] as LatLng, + name: data['name'] as String, + address: data['address'] as String, + city: data['city'] as String, + state: data['state'] as String, + country: data['country'] as String, + zipCode: data['zipCode'] as String, + ); +} + +FFUploadedFile uploadedFileFromString(String uploadedFileStr) => + FFUploadedFile.deserialize(uploadedFileStr); + +enum ParamType { + int, + double, + String, + bool, + DateTime, + DateTimeRange, + LatLng, + Color, + FFPlace, + FFUploadedFile, + JSON, + DataStruct, + Enum, +} + +dynamic deserializeParam( + String? param, + ParamType paramType, + bool isList, { + StructBuilder? structBuilder, +}) { + try { + if (param == null) { + return null; + } + if (isList) { + final paramValues = json.decode(param); + if (paramValues is! Iterable || paramValues.isEmpty) { + return null; + } + return paramValues + .whereType() + .map((p) => p) + .map((p) => deserializeParam( + p, + paramType, + false, + structBuilder: structBuilder, + )) + .where((p) => p != null) + .map((p) => p! as T) + .toList(); + } + switch (paramType) { + case ParamType.int: + return int.tryParse(param); + case ParamType.double: + return double.tryParse(param); + case ParamType.String: + return param; + case ParamType.bool: + return param == 'true'; + case ParamType.DateTime: + final milliseconds = int.tryParse(param); + return milliseconds != null + ? DateTime.fromMillisecondsSinceEpoch(milliseconds) + : null; + case ParamType.DateTimeRange: + return dateTimeRangeFromString(param); + case ParamType.LatLng: + return latLngFromString(param); + case ParamType.Color: + return fromCssColor(param); + case ParamType.FFPlace: + return placeFromString(param); + case ParamType.FFUploadedFile: + return uploadedFileFromString(param); + case ParamType.JSON: + return json.decode(param); + + case ParamType.DataStruct: + final data = json.decode(param) as Map? ?? {}; + return structBuilder != null ? structBuilder(data) : null; + + case ParamType.Enum: + return deserializeEnum(param); + + default: + return null; + } + } catch (e) { + print('Error deserializing parameter: $e'); + return null; + } +} diff --git a/lib/flutter_flow/place.dart b/lib/flutter_flow/place.dart new file mode 100644 index 00000000..e3589b3b --- /dev/null +++ b/lib/flutter_flow/place.dart @@ -0,0 +1,46 @@ +import 'lat_lng.dart'; + +class FFPlace { + const FFPlace({ + this.latLng = const LatLng(0.0, 0.0), + this.name = '', + this.address = '', + this.city = '', + this.state = '', + this.country = '', + this.zipCode = '', + }); + + final LatLng latLng; + final String name; + final String address; + final String city; + final String state; + final String country; + final String zipCode; + + @override + String toString() => '''FFPlace( + latLng: $latLng, + name: $name, + address: $address, + city: $city, + state: $state, + country: $country, + zipCode: $zipCode, + )'''; + + @override + int get hashCode => latLng.hashCode; + + @override + bool operator ==(other) => + other is FFPlace && + latLng == other.latLng && + name == other.name && + address == other.address && + city == other.city && + state == other.state && + country == other.country && + zipCode == other.zipCode; +} diff --git a/lib/flutter_flow/random_data_util.dart b/lib/flutter_flow/random_data_util.dart new file mode 100644 index 00000000..6599e5a6 --- /dev/null +++ b/lib/flutter_flow/random_data_util.dart @@ -0,0 +1,51 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +final _random = Random(); + +int randomInteger(int min, int max) { + return _random.nextInt(max - min + 1) + min; +} + +double randomDouble(double min, double max) { + return _random.nextDouble() * (max - min) + min; +} + +String randomString( + int minLength, + int maxLength, + bool lowercaseAz, + bool uppercaseAz, + bool digits, +) { + var chars = ''; + if (lowercaseAz) { + chars += 'abcdefghijklmnopqrstuvwxyz'; + } + if (uppercaseAz) { + chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + } + if (digits) { + chars += '0123456789'; + } + return List.generate(randomInteger(minLength, maxLength), + (index) => chars[_random.nextInt(chars.length)]).join(); +} + +// Random date between 1970 and 2025. +DateTime randomDate() { + // Random max must be in range 0 < max <= 2^32. + // So we have to generate the time in seconds and then convert to milliseconds. + return DateTime.fromMillisecondsSinceEpoch( + randomInteger(0, 1735689600) * 1000); +} + +String randomImageUrl(int width, int height) { + return 'https://picsum.photos/seed/${_random.nextInt(1000)}/$width/$height'; +} + +Color randomColor() { + return Color.fromARGB( + 255, _random.nextInt(255), _random.nextInt(255), _random.nextInt(255)); +} diff --git a/lib/flutter_flow/upload_data.dart b/lib/flutter_flow/upload_data.dart new file mode 100644 index 00000000..11219e59 --- /dev/null +++ b/lib/flutter_flow/upload_data.dart @@ -0,0 +1,377 @@ +import 'dart:async'; + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:mime_type/mime_type.dart'; +import 'package:video_player/video_player.dart'; + +import 'flutter_flow_theme.dart'; +import 'flutter_flow_util.dart'; + +const allowedFormats = {'image/png', 'image/jpeg', 'video/mp4', 'image/gif'}; + +class SelectedFile { + const SelectedFile({ + this.storagePath = '', + this.filePath, + required this.bytes, + this.dimensions, + this.blurHash, + }); + final String storagePath; + final String? filePath; + final Uint8List bytes; + final MediaDimensions? dimensions; + final String? blurHash; +} + +class MediaDimensions { + const MediaDimensions({ + this.height, + this.width, + }); + final double? height; + final double? width; +} + +enum MediaSource { + photoGallery, + videoGallery, + camera, +} + +Future?> selectMediaWithSourceBottomSheet({ + required BuildContext context, + String? storageFolderPath, + double? maxWidth, + double? maxHeight, + int? imageQuality, + required bool allowPhoto, + bool allowVideo = false, + String pickerFontFamily = 'Roboto', + Color textColor = const Color(0xFF111417), + Color backgroundColor = const Color(0xFFF5F5F5), + bool includeDimensions = false, + bool includeBlurHash = false, +}) async { + createUploadMediaListTile(String label, MediaSource mediaSource) => ListTile( + title: Text( + label, + textAlign: TextAlign.center, + style: GoogleFonts.getFont( + pickerFontFamily, + color: textColor, + fontWeight: FontWeight.w600, + fontSize: 20, + ), + ), + tileColor: backgroundColor, + dense: false, + onTap: () => Navigator.pop( + context, + mediaSource, + ), + ); + final mediaSource = await showModalBottomSheet( + context: context, + backgroundColor: backgroundColor, + builder: (context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (!kIsWeb) ...[ + Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), + child: ListTile( + title: Text( + 'Choose Source', + textAlign: TextAlign.center, + style: GoogleFonts.getFont( + pickerFontFamily, + color: textColor.withOpacity(0.65), + fontWeight: FontWeight.w500, + fontSize: 20, + ), + ), + tileColor: backgroundColor, + dense: false, + ), + ), + const Divider(), + ], + if (allowPhoto && allowVideo) ...[ + createUploadMediaListTile( + 'Gallery (Photo)', + MediaSource.photoGallery, + ), + const Divider(), + createUploadMediaListTile( + 'Gallery (Video)', + MediaSource.videoGallery, + ), + ] else if (allowPhoto) + createUploadMediaListTile( + 'Gallery', + MediaSource.photoGallery, + ) + else + createUploadMediaListTile( + 'Gallery', + MediaSource.videoGallery, + ), + if (!kIsWeb) ...[ + const Divider(), + createUploadMediaListTile('Camera', MediaSource.camera), + const Divider(), + ], + const SizedBox(height: 10), + ], + ); + }); + if (mediaSource == null) { + return null; + } + return selectMedia( + storageFolderPath: storageFolderPath, + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + isVideo: mediaSource == MediaSource.videoGallery || + (mediaSource == MediaSource.camera && allowVideo && !allowPhoto), + mediaSource: mediaSource, + includeDimensions: includeDimensions, + includeBlurHash: includeBlurHash, + ); +} + +Future?> selectMedia({ + String? storageFolderPath, + double? maxWidth, + double? maxHeight, + int? imageQuality, + bool isVideo = false, + MediaSource mediaSource = MediaSource.camera, + bool multiImage = false, + bool includeDimensions = false, + bool includeBlurHash = false, +}) async { + final picker = ImagePicker(); + + if (multiImage) { + final pickedMediaFuture = picker.pickMultiImage( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + ); + final pickedMedia = await pickedMediaFuture; + if (pickedMedia.isEmpty) { + return null; + } + return Future.wait(pickedMedia.asMap().entries.map((e) async { + final index = e.key; + final media = e.value; + final mediaBytes = await media.readAsBytes(); + final path = _getStoragePath(storageFolderPath, media.name, false, index); + final dimensions = includeDimensions + ? isVideo + ? _getVideoDimensions(media.path) + : _getImageDimensions(mediaBytes) + : null; + + return SelectedFile( + storagePath: path, + filePath: media.path, + bytes: mediaBytes, + dimensions: await dimensions, + ); + })); + } + + final source = mediaSource == MediaSource.camera + ? ImageSource.camera + : ImageSource.gallery; + final pickedMediaFuture = isVideo + ? picker.pickVideo(source: source) + : picker.pickImage( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + source: source, + ); + final pickedMedia = await pickedMediaFuture; + final mediaBytes = await pickedMedia?.readAsBytes(); + if (mediaBytes == null) { + return null; + } + final path = _getStoragePath(storageFolderPath, pickedMedia!.name, isVideo); + final dimensions = includeDimensions + ? isVideo + ? _getVideoDimensions(pickedMedia.path) + : _getImageDimensions(mediaBytes) + : null; + + return [ + SelectedFile( + storagePath: path, + filePath: pickedMedia.path, + bytes: mediaBytes, + dimensions: await dimensions, + ), + ]; +} + +bool validateFileFormat(String filePath, BuildContext context) { + if (allowedFormats.contains(mime(filePath))) { + return true; + } + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(SnackBar( + content: Text('Invalid file format: ${mime(filePath)}'), + )); + return false; +} + +Future selectFile({ + String? storageFolderPath, + List? allowedExtensions, +}) => + selectFiles( + storageFolderPath: storageFolderPath, + allowedExtensions: allowedExtensions, + multiFile: false, + ).then((value) => value?.first); + +Future?> selectFiles({ + String? storageFolderPath, + List? allowedExtensions, + bool multiFile = false, +}) async { + final pickedFiles = await FilePicker.platform.pickFiles( + type: allowedExtensions != null ? FileType.custom : FileType.any, + allowedExtensions: allowedExtensions, + withData: true, + allowMultiple: multiFile, + ); + if (pickedFiles == null || pickedFiles.files.isEmpty) { + return null; + } + if (multiFile) { + return Future.wait(pickedFiles.files.asMap().entries.map((e) async { + final index = e.key; + final file = e.value; + final storagePath = + _getStoragePath(storageFolderPath, file.name, false, index); + return SelectedFile( + storagePath: storagePath, + filePath: isWeb ? null : file.path, + bytes: file.bytes!, + ); + })); + } + final file = pickedFiles.files.first; + if (file.bytes == null) { + return null; + } + final storagePath = _getStoragePath(storageFolderPath, file.name, false); + return [ + SelectedFile( + storagePath: storagePath, + filePath: isWeb ? null : file.path, + bytes: file.bytes!, + ) + ]; +} + +List selectedFilesFromUploadedFiles( + List uploadedFiles, { + String? storageFolderPath, + bool isMultiData = false, +}) => + uploadedFiles.asMap().entries.map( + (entry) { + final index = entry.key; + final file = entry.value; + return SelectedFile( + storagePath: _getStoragePath( + storageFolderPath, + file.name!, + false, + isMultiData ? index : null, + ), + bytes: file.bytes!); + }, + ).toList(); + +Future _getImageDimensions(Uint8List mediaBytes) async { + final image = await decodeImageFromList(mediaBytes); + return MediaDimensions( + width: image.width.toDouble(), + height: image.height.toDouble(), + ); +} + +Future _getVideoDimensions(String path) async { + final VideoPlayerController videoPlayerController = + VideoPlayerController.asset(path); + await videoPlayerController.initialize(); + final size = videoPlayerController.value.size; + return MediaDimensions(width: size.width, height: size.height); +} + +String _getStoragePath( + String? pathPrefix, + String filePath, + bool isVideo, [ + int? index, +]) { + pathPrefix = _removeTrailingSlash(pathPrefix); + final timestamp = DateTime.now().microsecondsSinceEpoch; + // Workaround fixed by https://github.com/flutter/plugins/pull/3685 + // (not yet in stable). + final ext = isVideo ? 'mp4' : filePath.split('.').last; + final indexStr = index != null ? '_$index' : ''; + return '$pathPrefix/$timestamp$indexStr.$ext'; +} + +String getSignatureStoragePath([String? pathPrefix]) { + pathPrefix = _removeTrailingSlash(pathPrefix); + final timestamp = DateTime.now().microsecondsSinceEpoch; + return '$pathPrefix/signature_$timestamp.png'; +} + +void showUploadMessage( + BuildContext context, + String message, { + bool showLoading = false, +}) { + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar( + content: Row( + children: [ + if (showLoading) + Padding( + padding: const EdgeInsetsDirectional.only(end: 10.0), + child: CircularProgressIndicator( + valueColor: Theme.of(context).brightness == Brightness.dark + ? AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).accent4) + : null, + ), + ), + Text(message), + ], + ), + duration: showLoading ? const Duration(days: 1) : const Duration(seconds: 4), + ), + ); +} + +String? _removeTrailingSlash(String? path) => path != null && path.endsWith('/') + ? path.substring(0, path.length - 1) + : path; diff --git a/lib/flutter_flow/uploaded_file.dart b/lib/flutter_flow/uploaded_file.dart new file mode 100644 index 00000000..2dfd2ff1 --- /dev/null +++ b/lib/flutter_flow/uploaded_file.dart @@ -0,0 +1,68 @@ +import 'dart:convert'; +import 'dart:typed_data' show Uint8List; + +class FFUploadedFile { + const FFUploadedFile({ + this.name, + this.bytes, + this.height, + this.width, + this.blurHash, + }); + + final String? name; + final Uint8List? bytes; + final double? height; + final double? width; + final String? blurHash; + + @override + String toString() => + 'FFUploadedFile(name: $name, bytes: ${bytes?.length ?? 0}, height: $height, width: $width, blurHash: $blurHash,)'; + + String serialize() => jsonEncode( + { + 'name': name, + 'bytes': bytes, + 'height': height, + 'width': width, + 'blurHash': blurHash, + }, + ); + + static FFUploadedFile deserialize(String val) { + final serializedData = jsonDecode(val) as Map; + final data = { + 'name': serializedData['name'] ?? '', + 'bytes': serializedData['bytes'] ?? Uint8List.fromList([]), + 'height': serializedData['height'], + 'width': serializedData['width'], + 'blurHash': serializedData['blurHash'], + }; + return FFUploadedFile( + name: data['name'] as String, + bytes: Uint8List.fromList(data['bytes'].cast().toList()), + height: data['height'] as double?, + width: data['width'] as double?, + blurHash: data['blurHash'] as String?, + ); + } + + @override + int get hashCode => Object.hash( + name, + bytes, + height, + width, + blurHash, + ); + + @override + bool operator ==(other) => + other is FFUploadedFile && + name == other.name && + bytes == other.bytes && + height == other.height && + width == other.width && + blurHash == other.blurHash; +} diff --git a/lib/index.dart b/lib/index.dart new file mode 100644 index 00000000..d3cc0e80 --- /dev/null +++ b/lib/index.dart @@ -0,0 +1,20 @@ +// Export pages +export '/on_boarding/on_boarding_legacy/login_page/login_page_widget.dart' + show LoginPageWidget; +export '/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_widget.dart' + show ForgotPasswordPageWidget; +export '/application_pages/home_page/home_page_widget.dart' show HomePageWidget; +export '/on_boarding/on_boarding_legacy/register_page/register_page_widget.dart' + show RegisterPageWidget; +export '/on_boarding/on_boarding_legacy/welcome_page/welcome_page_widget.dart' + show WelcomePageWidget; +export '/application_pages/register_visitor_page/register_visitor_page_widget.dart' + show RegisterVisitorPageWidget; +export '/application_pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart' + show ScheduleCompleteVisitPageWidget; +export '/application_pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart' + show ScheduleProvisionalVisitPageWidget; +export '/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_widget.dart' + show OnBoardingPageWidget; +export '/application_pages/fast_pass_page/fast_pass_page_widget.dart' + show FastPassPageWidget; diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 00000000..9431af7c --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,120 @@ +import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; + +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_web_plugins/url_strategy.dart'; +import 'flutter_flow/flutter_flow_theme.dart'; +import 'flutter_flow/flutter_flow_util.dart'; +import 'flutter_flow/internationalization.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + GoRouter.optionURLReflectsImperativeAPIs = true; + usePathUrlStrategy(); + + await FlutterFlowTheme.initialize(); + + await FFLocalizations.initialize(); + + final appState = FFAppState(); // Initialize FFAppState + await appState.initializePersistedState(); + + runApp(ChangeNotifierProvider( + create: (context) => appState, + child: const MyApp(), + )); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + State createState() => _MyAppState(); + + static _MyAppState of(BuildContext context) => + context.findAncestorStateOfType<_MyAppState>()!; +} + +class _MyAppState extends State { + Locale? _locale = FFLocalizations.getStoredLocale(); + ThemeMode _themeMode = FlutterFlowTheme.themeMode; + + late AppStateNotifier _appStateNotifier; + late GoRouter _router; + + bool displaySplashImage = true; + + @override + void initState() { + super.initState(); + + _appStateNotifier = AppStateNotifier.instance; + _router = createRouter(_appStateNotifier); + + Future.delayed(const Duration(milliseconds: 1000), + () => setState(() => _appStateNotifier.stopShowingSplashImage())); + } + + void setLocale(String language) { + setState(() => _locale = createLocale(language)); + FFLocalizations.storeLocale(language); + } + + void setThemeMode(ThemeMode mode) => setState(() { + _themeMode = mode; + FlutterFlowTheme.saveThemeMode(mode); + }); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + title: 'FREHub', + localizationsDelegates: const [ + FFLocalizationsDelegate(), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + locale: _locale, + supportedLocales: const [ + Locale('pt'), + Locale('en'), + ], + theme: ThemeData( + brightness: Brightness.light, + scrollbarTheme: ScrollbarThemeData( + thumbVisibility: MaterialStateProperty.all(false), + interactive: false, + thumbColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.dragged)) { + return const Color(0xff1aab5f); + } + if (states.contains(MaterialState.hovered)) { + return const Color(0xff1aab5f); + } + return const Color(0xff1aab5f); + }), + ), + ), + darkTheme: ThemeData( + brightness: Brightness.dark, + scrollbarTheme: ScrollbarThemeData( + thumbVisibility: MaterialStateProperty.all(false), + interactive: false, + thumbColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.dragged)) { + return const Color(0xff1aab5f); + } + if (states.contains(MaterialState.hovered)) { + return const Color(0xff1aab5f); + } + return const Color(0xff1aab5f); + }), + ), + ), + themeMode: _themeMode, + routerConfig: _router, + ); + } +} diff --git a/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_model.dart b/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_model.dart new file mode 100644 index 00000000..f82f5603 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_model.dart @@ -0,0 +1,26 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'forgot_password_component_widget.dart' + show ForgotPasswordComponentWidget; +import 'package:flutter/material.dart'; + +class ForgotPasswordComponentModel + extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for emailAddress widget. + FocusNode? emailAddressFocusNode; + TextEditingController? emailAddressTextController; + String? Function(BuildContext, String?)? emailAddressTextControllerValidator; + // Stores action output result for [Backend Call - API (forgotPassword)] action in Button-Login widget. + ApiCallResponse? req; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + emailAddressFocusNode?.dispose(); + emailAddressTextController?.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_widget.dart b/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_widget.dart new file mode 100644 index 00000000..9f889f97 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_widget.dart @@ -0,0 +1,292 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'forgot_password_component_model.dart'; +export 'forgot_password_component_model.dart'; + +class ForgotPasswordComponentWidget extends StatefulWidget { + const ForgotPasswordComponentWidget({super.key}); + + @override + State createState() => + _ForgotPasswordComponentWidgetState(); +} + +class _ForgotPasswordComponentWidgetState + extends State { + late ForgotPasswordComponentModel _model; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ForgotPasswordComponentModel()); + + _model.emailAddressTextController ??= TextEditingController(); + _model.emailAddressFocusNode ??= FocusNode(); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Container( + width: double.infinity, + height: 300.0, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // This row exists for when the "app bar" is hidden on desktop, having a way back for the user can work well. + if (responsiveVisibility( + context: context, + phone: false, + tablet: false, + )) + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 16.0, 8.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.safePop(); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + const Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: Icon( + Icons.arrow_back_rounded, + color: Color(0xFF15161E), + size: 24.0, + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(12.0, 0.0, 0.0, 0.0), + child: Text( + '', + style: + FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: const Color(0xFF15161E), + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'xxm3ajsy' /* ESQUECEU SUA SENHA? */, + ), + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Outfit', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap().containsKey('Outfit'), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 4.0, 16.0, 4.0), + child: Text( + FFLocalizations.of(context).getText( + 'wu2f7yzo' /* Não se preucupe nós vamos te a... */, + ), + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Plus Jakarta Sans'), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 16.0, 0.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model.emailAddressTextController, + focusNode: _model.emailAddressFocusNode, + autofillHints: const [AutofillHints.email], + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + 'mtz8l7ft' /* Email */, + ), + labelStyle: + FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).accent1, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + hintText: FFLocalizations.of(context).getText( + 'w7y5wlnv' /* digite o seu email..... */, + ), + hintStyle: + FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent3, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context).primaryBackground, + contentPadding: + const EdgeInsetsDirectional.fromSTEB(24.0, 24.0, 20.0, 24.0), + suffixIcon: Icon( + Icons.email, + color: FlutterFlowTheme.of(context).accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).secondaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + maxLines: null, + keyboardType: TextInputType.emailAddress, + cursorColor: const Color(0xFF6F61EF), + validator: _model.emailAddressTextControllerValidator + .asValidator(context), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 24.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + var shouldSetState = false; + _model.req = await PhpGroup.forgotPasswordCall.call( + email: _model.emailAddressTextController.text, + ); + shouldSetState = true; + if (PhpGroup.forgotPasswordCall.error( + (_model.req?.jsonBody ?? ''), + ) == + false) { + Navigator.pop(context); + } else { + if (shouldSetState) setState(() {}); + return; + } + + if (shouldSetState) setState(() {}); + }, + text: FFLocalizations.of(context).getText( + '74rnd5bu' /* Enviar */, + ), + options: FFButtonOptions( + width: 270.0, + height: 50.0, + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: const Color(0xFF1AAB5F), + textStyle: FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Plus Jakarta Sans', + color: Colors.white, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + ), + showLoadingIndicator: false, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_model.dart b/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_model.dart new file mode 100644 index 00000000..f66a1974 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_model.dart @@ -0,0 +1,45 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import '/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_widget.dart'; +import '/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_widget.dart'; +import '/on_boarding/on_boarding_beta/welcome_component/welcome_component_widget.dart'; +import 'on_boarding_page_widget.dart' show OnBoardingPageWidget; +import 'package:flutter/material.dart'; + +class OnBoardingPageModel extends FlutterFlowModel { + /// Local state fields for this page. + + String toggleIdx = 'welcome'; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // Model for signInComponent component. + late SignInComponentModel signInComponentModel; + // Model for signUpComponent component. + late SignUpComponentModel signUpComponentModel; + // Model for welcomeComponent component. + late WelcomeComponentModel welcomeComponentModel; + + @override + void initState(BuildContext context) { + signInComponentModel = createModel(context, () => SignInComponentModel()); + signUpComponentModel = createModel(context, () => SignUpComponentModel()); + welcomeComponentModel = createModel(context, () => WelcomeComponentModel()); + } + + @override + void dispose() { + unfocusNode.dispose(); + signInComponentModel.dispose(); + signUpComponentModel.dispose(); + welcomeComponentModel.dispose(); + } + + /// Action blocks. + Future toggleOnBoardingActionPage( + BuildContext context, { + required String? toggleValue, + }) async { + toggleIdx = toggleValue!; + } +} diff --git a/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_widget.dart b/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_widget.dart new file mode 100644 index 00000000..da799597 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/on_boarding_page/on_boarding_page_widget.dart @@ -0,0 +1,131 @@ +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_widget.dart'; +import '/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_widget.dart'; +import '/on_boarding/on_boarding_beta/welcome_component/welcome_component_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:provider/provider.dart'; +import 'on_boarding_page_model.dart'; +export 'on_boarding_page_model.dart'; + +class OnBoardingPageWidget extends StatefulWidget { + const OnBoardingPageWidget({super.key}); + + @override + State createState() => _OnBoardingPageWidgetState(); +} + +class _OnBoardingPageWidgetState extends State { + late OnBoardingPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => OnBoardingPageModel()); + + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + if (FFAppState().isLogged == true) { + context.pushNamed( + 'homePage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.fade, + duration: Duration(milliseconds: 0), + ), + }, + ); + } else { + if (isAndroid == true) { + FFAppState().device = 'Android'; + setState(() {}); + } else if (isiOS == true) { + FFAppState().device = 'iOS'; + setState(() {}); + } else { + FFAppState().device = 'Web'; + setState(() {}); + } + } + }); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Stack( + children: [ + if (_model.toggleIdx == 'SignIn') + wrapWithModel( + model: _model.signInComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: SignInComponentWidget( + toggleOnBoardingPageAction: (toggleValueSignInParam) async { + await _model.toggleOnBoardingActionPage( + context, + toggleValue: toggleValueSignInParam, + ); + setState(() {}); + }, + ), + ), + if (_model.toggleIdx == 'SignUp') + wrapWithModel( + model: _model.signUpComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: SignUpComponentWidget( + toggleOnBoardingPageAction: (toggleValueSignUpParam) async { + await _model.toggleOnBoardingActionPage( + context, + toggleValue: toggleValueSignUpParam, + ); + setState(() {}); + }, + ), + ), + if (_model.toggleIdx == 'welcome') + wrapWithModel( + model: _model.welcomeComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: WelcomeComponentWidget( + toggleOnboardingPageAction: + (toggleValueWelcomeParam) async { + await _model.toggleOnBoardingActionPage( + context, + toggleValue: toggleValueWelcomeParam, + ); + setState(() {}); + }, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_model.dart b/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_model.dart new file mode 100644 index 00000000..9642203c --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_model.dart @@ -0,0 +1,31 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'sign_in_component_widget.dart' show SignInComponentWidget; +import 'package:flutter/material.dart'; + +class SignInComponentModel extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for emailAddress widget. + FocusNode? emailAddressFocusNode; + TextEditingController? emailAddressTextController; + String? Function(BuildContext, String?)? emailAddressTextControllerValidator; + // State field(s) for password widget. + FocusNode? passwordFocusNode; + TextEditingController? passwordTextController; + late bool passwordVisibility; + String? Function(BuildContext, String?)? passwordTextControllerValidator; + + @override + void initState(BuildContext context) { + passwordVisibility = false; + } + + @override + void dispose() { + emailAddressFocusNode?.dispose(); + emailAddressTextController?.dispose(); + + passwordFocusNode?.dispose(); + passwordTextController?.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_widget.dart b/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_widget.dart new file mode 100644 index 00000000..b6955b01 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/sign_in_component/sign_in_component_widget.dart @@ -0,0 +1,899 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/on_boarding/on_boarding_beta/forgot_password_component/forgot_password_component_widget.dart'; +import '/actions/actions.dart' as action_blocks; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'sign_in_component_model.dart'; +export 'sign_in_component_model.dart'; + +class SignInComponentWidget extends StatefulWidget { + const SignInComponentWidget({ + super.key, + required this.toggleOnBoardingPageAction, + }); + + final Future Function(String toggleValueSignInParam)? + toggleOnBoardingPageAction; + + @override + State createState() => _SignInComponentWidgetState(); +} + +class _SignInComponentWidgetState extends State + with TickerProviderStateMixin { + late SignInComponentModel _model; + + final animationsMap = {}; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => SignInComponentModel()); + + _model.emailAddressTextController ??= TextEditingController(); + _model.emailAddressFocusNode ??= FocusNode(); + + _model.passwordTextController ??= TextEditingController(); + _model.passwordFocusNode ??= FocusNode(); + + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 6, + child: Container( + width: 100.0, + height: double.infinity, + decoration: const BoxDecoration(), + alignment: const AlignmentDirectional(0.0, -1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 35.0, 0.0, 35.0), + child: Container( + width: 548.0, + height: 112.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Text( + FFLocalizations.of(context).getText( + '9hbdjxrz' /* VAMOS LA! ENTRE COM A SUA CONT... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Container( + width: 291.0, + height: 167.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/sr43ucngg4a4/Vector.png', + width: 603.0, + height: 155.0, + fit: BoxFit.contain, + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 34.0, 0.0, 34.0, 0.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: BorderRadius.circular(12.0), + shape: BoxShape.rectangle, + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .emailAddressTextController, + focusNode: + _model.emailAddressFocusNode, + autofocus: false, + textCapitalization: + TextCapitalization.none, + textInputAction: + TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context) + .getText( + '1ltg0ylb' /* Email */, + ), + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + suffixIcon: Icon( + Icons.email, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: + TextInputType.emailAddress, + validator: _model + .emailAddressTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: + _model.passwordTextController, + focusNode: _model.passwordFocusNode, + autofocus: false, + textInputAction: + TextInputAction.send, + obscureText: + !_model.passwordVisibility, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context) + .getText( + '2x19ce8k' /* Senha */, + ), + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFF1AAB5F), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + suffixIcon: InkWell( + onTap: () => setState( + () => _model + .passwordVisibility = + !_model + .passwordVisibility, + ), + focusNode: FocusNode( + skipTraversal: true), + child: Icon( + _model.passwordVisibility + ? Icons + .visibility_outlined + : Icons + .visibility_off_outlined, + color: FlutterFlowTheme.of( + context) + .accent1, + size: 24.0, + ), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + validator: _model + .passwordTextControllerValidator + .asValidator(context), + ), + ), + ), + Builder( + builder: (context) { + if (MediaQuery.sizeOf(context).width < + kBreakpointSmall + ? true + : false) { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: ((_model.emailAddressTextController + .text == + '') && + (_model.passwordTextController + .text == + '')) + ? null + : () async { + await action_blocks + .singInActionApp( + context, + emailAdress: _model + .emailAddressTextController + .text, + password: _model + .passwordTextController + .text, + ); + setState(() {}); + }, + text: FFLocalizations.of( + context) + .getText( + 'k44tm7wo' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: + FlutterFlowTheme.of( + context) + .primary, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .info, + fontSize: 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: + Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + disabledColor: + const Color(0x951AAB5F), + ), + showLoadingIndicator: false, + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + await widget + .toggleOnBoardingPageAction + ?.call( + 'SignUp', + ); + }, + text: FFLocalizations.of( + context) + .getText( + '14u7ipws' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: + FlutterFlowTheme.of( + context) + .customColor1, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: + Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + ], + ); + } else { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 16.0), + child: FFButtonWidget( + onPressed: () { + print( + 'signInButtonLoginForm pressed ...'); + }, + text: FFLocalizations.of( + context) + .getText( + '1x926nsn' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: + FlutterFlowTheme.of( + context) + .accent1, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + showLoadingIndicator: + false, + ), + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'RegisterPage'); + }, + text: FFLocalizations.of( + context) + .getText( + 'jwvd4ai1' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: + FlutterFlowTheme.of( + context) + .customColor1, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + showLoadingIndicator: + false, + ), + ), + ), + ].divide(const SizedBox(width: 7.0)), + ); + } + }, + ), + + // You will have to add an action on this rich text to go to your login page. + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: RichText( + textScaler: + MediaQuery.of(context).textScaler, + text: TextSpan( + children: [ + TextSpan( + text: + FFLocalizations.of(context) + .getText( + '05dx91ku' /* Você esqueceu a sua senha? */, + ), + style: TextStyle( + color: FlutterFlowTheme.of( + context) + .primaryText, + ), + ), + TextSpan( + text: + FFLocalizations.of(context) + .getText( + 'p5c6d54y' /* Recupere aqui */, + ), + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primary, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.normal, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + mouseCursor: + SystemMouseCursors.click, + recognizer: + TapGestureRecognizer() + ..onTap = () async { + await showModalBottomSheet( + isScrollControlled: + true, + backgroundColor: + Colors + .transparent, + context: context, + builder: (context) { + return Padding( + padding: MediaQuery + .viewInsetsOf( + context), + child: + const ForgotPasswordComponentWidget(), + ); + }, + ).then((value) => + safeSetState( + () {})); + }, + ) + ], + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + Text( + FFLocalizations.of(context).getText( + 'olf967cj' /* Termo de Uso */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: + FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ], + ), + ), + ), + ).animateOnPageLoad( + animationsMap['containerOnPageLoadAnimation']!), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_model.dart b/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_model.dart new file mode 100644 index 00000000..48fa5cb4 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_model.dart @@ -0,0 +1,43 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'sign_up_component_widget.dart' show SignUpComponentWidget; +import 'package:flutter/material.dart'; + +class SignUpComponentModel extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for nameRegisterForm widget. + FocusNode? nameRegisterFormFocusNode; + TextEditingController? nameRegisterFormTextController; + String? Function(BuildContext, String?)? + nameRegisterFormTextControllerValidator; + // State field(s) for emailRegisterForm widget. + FocusNode? emailRegisterFormFocusNode; + TextEditingController? emailRegisterFormTextController; + String? Function(BuildContext, String?)? + emailRegisterFormTextControllerValidator; + // State field(s) for passwordRegisterForm widget. + FocusNode? passwordRegisterFormFocusNode; + TextEditingController? passwordRegisterFormTextController; + late bool passwordRegisterFormVisibility; + String? Function(BuildContext, String?)? + passwordRegisterFormTextControllerValidator; + // Stores action output result for [Action Block - signUpActionApp] action in SignUpButtonRegisterForm widget. + bool? signUp; + + @override + void initState(BuildContext context) { + passwordRegisterFormVisibility = false; + } + + @override + void dispose() { + nameRegisterFormFocusNode?.dispose(); + nameRegisterFormTextController?.dispose(); + + emailRegisterFormFocusNode?.dispose(); + emailRegisterFormTextController?.dispose(); + + passwordRegisterFormFocusNode?.dispose(); + passwordRegisterFormTextController?.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_widget.dart b/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_widget.dart new file mode 100644 index 00000000..db82a230 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/sign_up_component/sign_up_component_widget.dart @@ -0,0 +1,770 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/actions/actions.dart' as action_blocks; +import 'package:easy_debounce/easy_debounce.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'sign_up_component_model.dart'; +export 'sign_up_component_model.dart'; + +class SignUpComponentWidget extends StatefulWidget { + const SignUpComponentWidget({ + super.key, + required this.toggleOnBoardingPageAction, + }); + + final Future Function(String toggleValueSignUpParam)? + toggleOnBoardingPageAction; + + @override + State createState() => _SignUpComponentWidgetState(); +} + +class _SignUpComponentWidgetState extends State + with TickerProviderStateMixin { + late SignUpComponentModel _model; + + final animationsMap = {}; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => SignUpComponentModel()); + + _model.nameRegisterFormTextController ??= TextEditingController(); + _model.nameRegisterFormFocusNode ??= FocusNode(); + _model.nameRegisterFormFocusNode!.addListener(() => setState(() {})); + _model.emailRegisterFormTextController ??= TextEditingController(); + _model.emailRegisterFormFocusNode ??= FocusNode(); + _model.emailRegisterFormFocusNode!.addListener(() => setState(() {})); + _model.passwordRegisterFormTextController ??= TextEditingController(); + _model.passwordRegisterFormFocusNode ??= FocusNode(); + _model.passwordRegisterFormFocusNode!.addListener(() => setState(() {})); + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 6, + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + alignment: const AlignmentDirectional(0.0, -1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(4.0), + child: Container( + width: 669.0, + height: 112.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Text( + FFLocalizations.of(context).getText( + '49609olv' /* INSIRA SEU EMAIL E SENHA, VAMO... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Container( + width: 291.0, + height: 167.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: SvgPicture.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/ug2zlyhca2sh/Frame_5.svg', + width: 603.0, + height: 155.0, + fit: BoxFit.contain, + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(34.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: BorderRadius.circular(12.0), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .nameRegisterFormTextController, + focusNode: _model + .nameRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.nameRegisterFormTextController', + const Duration(milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [AutofillHints.name], + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context) + .getText( + '3corpwhd' /* Nome */, + ), + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + suffixIcon: Icon( + Icons.person, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: TextInputType.name, + validator: _model + .nameRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .emailRegisterFormTextController, + focusNode: _model + .emailRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.emailRegisterFormTextController', + const Duration(milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [ + AutofillHints.email + ], + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context) + .getText( + '80wonb69' /* Email */, + ), + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .primaryText, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + suffixIcon: Icon( + Icons.email, + color: + FlutterFlowTheme.of(context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .customColor1, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: + TextInputType.emailAddress, + validator: _model + .emailRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .passwordRegisterFormTextController, + focusNode: _model + .passwordRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.passwordRegisterFormTextController', + const Duration(milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [ + AutofillHints.password + ], + obscureText: !_model + .passwordRegisterFormVisibility, + decoration: InputDecoration( + labelText: + FFLocalizations.of(context) + .getText( + '0firji8l' /* Senha */, + ), + labelStyle: FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFF1AAB5F), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of(context) + .primaryBackground, + suffixIcon: InkWell( + onTap: () => setState( + () => _model + .passwordRegisterFormVisibility = + !_model + .passwordRegisterFormVisibility, + ), + focusNode: FocusNode( + skipTraversal: true), + child: Icon( + _model.passwordRegisterFormVisibility + ? Icons + .visibility_outlined + : Icons + .visibility_off_outlined, + color: FlutterFlowTheme.of( + context) + .accent1, + size: 24.0, + ), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + validator: _model + .passwordRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + var shouldSetState = false; + _model.signUp = await action_blocks + .signUpActionApp( + context, + name: _model + .nameRegisterFormTextController + .text, + passwd: _model + .passwordRegisterFormTextController + .text, + email: _model + .emailRegisterFormTextController + .text, + device: FFAppState().device, + ); + shouldSetState = true; + if (_model.signUp == true) { + await widget + .toggleOnBoardingPageAction + ?.call( + 'SignIn', + ); + } else { + if (shouldSetState) { + setState(() {}); + } + return; + } + + if (shouldSetState) { + setState(() {}); + } + }, + text: FFLocalizations.of(context) + .getText( + 'rnvdwzei' /* Cadastrar-se */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .accent1, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + showLoadingIndicator: false, + ), + ), + + // You will have to add an action on this rich text to go to your login page. + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + await widget + .toggleOnBoardingPageAction + ?.call( + 'SignIn', + ); + }, + child: RichText( + textScaler: MediaQuery.of(context) + .textScaler, + text: TextSpan( + children: [ + TextSpan( + text: FFLocalizations.of( + context) + .getText( + 'a9smhn5b' /* Você já tem uma conta? */, + ), + style: TextStyle( + color: FlutterFlowTheme.of( + context) + .primaryText, + ), + ), + TextSpan( + text: FFLocalizations.of( + context) + .getText( + '09xv5ctc' /* Clique aqui */, + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .primary, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ) + ], + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ).animateOnPageLoad( + animationsMap['containerOnPageLoadAnimation']!), + ), + ), + ], + ), + Text( + FFLocalizations.of(context).getText( + 'huygnka2' /* Termo de Uso */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + color: FlutterFlowTheme.of(context).secondaryText, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_model.dart b/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_model.dart new file mode 100644 index 00000000..e794a1dc --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_model.dart @@ -0,0 +1,11 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'welcome_component_widget.dart' show WelcomeComponentWidget; +import 'package:flutter/material.dart'; + +class WelcomeComponentModel extends FlutterFlowModel { + @override + void initState(BuildContext context) {} + + @override + void dispose() {} +} diff --git a/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_widget.dart b/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_widget.dart new file mode 100644 index 00000000..125b6ee2 --- /dev/null +++ b/lib/on_boarding/on_boarding_beta/welcome_component/welcome_component_widget.dart @@ -0,0 +1,456 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'welcome_component_model.dart'; +export 'welcome_component_model.dart'; + +class WelcomeComponentWidget extends StatefulWidget { + const WelcomeComponentWidget({ + super.key, + required this.toggleOnboardingPageAction, + }); + + final Future Function(String toggleValueWelcomeParam)? + toggleOnboardingPageAction; + + @override + State createState() => _WelcomeComponentWidgetState(); +} + +class _WelcomeComponentWidgetState extends State + with TickerProviderStateMixin { + late WelcomeComponentModel _model; + + final animationsMap = {}; + + @override + void setState(VoidCallback callback) { + super.setState(callback); + _model.onUpdate(); + } + + @override + void initState() { + super.initState(); + _model = createModel(context, () => WelcomeComponentModel()); + + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.maybeDispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SafeArea( + child: Container( + width: 648.0, + height: 208.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(14.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + FFLocalizations.of(context).getText( + 'dsc9tuc8' /* UMA EXPERIÊCIA COMPLETA */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).accent1, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Text( + FFLocalizations.of(context).getText( + '5bgqn16z' /* COM CONFORTO ONDE VOCÊ ESTIVER... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + Container( + width: 284.0, + height: 200.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(0.0), + child: SvgPicture.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/lv1waa0etd3j/undraw_appreciate_it_re_yc8h_(1)_1.svg', + width: 603.0, + height: double.infinity, + fit: BoxFit.contain, + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(34.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + boxShadow: const [ + BoxShadow( + blurRadius: 0.0, + color: Colors.transparent, + offset: Offset( + 0.0, + 0.0, + ), + ) + ], + borderRadius: BorderRadius.circular(12.0), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Builder( + builder: (context) { + if (MediaQuery.sizeOf(context).width < + kBreakpointSmall + ? true + : false) { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + await widget + .toggleOnboardingPageAction + ?.call( + 'SignIn', + ); + }, + text: + FFLocalizations.of(context).getText( + 'dynet730' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primary, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of(context) + .info, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + showLoadingIndicator: false, + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + await widget + .toggleOnboardingPageAction + ?.call( + 'SignUp', + ); + }, + text: + FFLocalizations.of(context).getText( + 'hha60cg7' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .customColor1, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of(context) + .customColor3, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + showLoadingIndicator: false, + ), + ), + ], + ); + } else { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': serializeParam( + '', + ParamType.String, + ), + }.withoutNulls, + ); + }, + text: FFLocalizations.of(context) + .getText( + 'zvtay8ee' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primary, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + showLoadingIndicator: false, + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed('RegisterPage'); + }, + text: FFLocalizations.of(context) + .getText( + 'o6zob50a' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context) + .primary, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular(12.0), + ), + showLoadingIndicator: false, + ), + ), + ), + ].divide(const SizedBox(width: 7.0)), + ); + } + }, + ), + ], + ), + ), + ), + ).animateOnPageLoad( + animationsMap['containerOnPageLoadAnimation']!), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_model.dart b/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_model.dart new file mode 100644 index 00000000..9455c218 --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_model.dart @@ -0,0 +1,29 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import 'forgot_password_page_widget.dart' show ForgotPasswordPageWidget; +import 'package:flutter/material.dart'; + +class ForgotPasswordPageModel + extends FlutterFlowModel { + /// Local state fields for this page. + + String? email; + + /// State fields for stateful widgets in this page. + + // State field(s) for emailAddress widget. + FocusNode? emailAddressFocusNode; + TextEditingController? emailAddressTextController; + String? Function(BuildContext, String?)? emailAddressTextControllerValidator; + // Stores action output result for [Backend Call - API (forgotPassword)] action in Button-Login widget. + ApiCallResponse? req; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + emailAddressFocusNode?.dispose(); + emailAddressTextController?.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_widget.dart b/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_widget.dart new file mode 100644 index 00000000..51646517 --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/forgot_password_page/forgot_password_page_widget.dart @@ -0,0 +1,335 @@ +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'forgot_password_page_model.dart'; +export 'forgot_password_page_model.dart'; + +class ForgotPasswordPageWidget extends StatefulWidget { + const ForgotPasswordPageWidget({super.key}); + + @override + State createState() => + _ForgotPasswordPageWidgetState(); +} + +class _ForgotPasswordPageWidgetState extends State { + late ForgotPasswordPageModel _model; + + final scaffoldKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _model = createModel(context, () => ForgotPasswordPageModel()); + + _model.emailAddressTextController ??= TextEditingController(); + _model.emailAddressFocusNode ??= FocusNode(); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + actions: const [], + flexibleSpace: FlexibleSpaceBar( + title: Row( + mainAxisSize: MainAxisSize.max, + children: [ + if (isWeb == false) + Align( + alignment: const AlignmentDirectional(-1.0, 1.0), + child: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.arrow_back_rounded, + color: FlutterFlowTheme.of(context).customColor1, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + ), + ], + ), + centerTitle: true, + expandedTitleScale: 1.0, + ), + elevation: 0.0, + ), + body: Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // This row exists for when the "app bar" is hidden on desktop, having a way back for the user can work well. + if (responsiveVisibility( + context: context, + phone: false, + tablet: false, + )) + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 16.0, 8.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + context.safePop(); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + const Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: Icon( + Icons.arrow_back_rounded, + color: Color(0xFF15161E), + size: 24.0, + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 12.0, 0.0, 0.0, 0.0), + child: Text( + '', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Plus Jakarta Sans', + color: const Color(0xFF15161E), + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'gfvplb0h' /* ESQUECEU SUA SENHA? */, + ), + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Outfit', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Outfit'), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 4.0, 16.0, 4.0), + child: Text( + FFLocalizations.of(context).getText( + 'azssgpdi' /* Não se preucupe nós vamos te a... */, + ), + style: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 16.0, 0.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model.emailAddressTextController, + focusNode: _model.emailAddressFocusNode, + autofillHints: const [AutofillHints.email], + obscureText: false, + decoration: InputDecoration( + labelText: FFLocalizations.of(context).getText( + '0o139961' /* Email */, + ), + labelStyle: + FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).accent1, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + hintText: FFLocalizations.of(context).getText( + 'aanw1fp3' /* digite o seu email..... */, + ), + hintStyle: + FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent3, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 2.0, + ), + borderRadius: BorderRadius.circular(12.0), + ), + filled: true, + fillColor: FlutterFlowTheme.of(context).primaryBackground, + contentPadding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 24.0, 20.0, 24.0), + suffixIcon: Icon( + Icons.email, + color: FlutterFlowTheme.of(context).accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context).secondaryText, + fontSize: 14.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + maxLines: null, + keyboardType: TextInputType.emailAddress, + cursorColor: const Color(0xFF6F61EF), + validator: _model.emailAddressTextControllerValidator + .asValidator(context), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 24.0, 0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + var shouldSetState = false; + _model.email = _model.emailAddressTextController.text; + setState(() {}); + _model.req = await PhpGroup.forgotPasswordCall.call( + email: _model.email, + ); + shouldSetState = true; + if (PhpGroup.forgotPasswordCall.error( + (_model.req?.jsonBody ?? ''), + ) == + false) { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': serializeParam( + '', + ParamType.String, + ), + }.withoutNulls, + ); + } else { + if (shouldSetState) setState(() {}); + return; + } + + if (shouldSetState) setState(() {}); + }, + text: FFLocalizations.of(context).getText( + 'e7hdgc4q' /* Enviar */, + ), + options: FFButtonOptions( + width: 270.0, + height: 50.0, + padding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0), + color: const Color(0xFF1AAB5F), + textStyle: + FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Plus Jakarta Sans', + color: Colors.white, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + ), + showLoadingIndicator: false, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/login_page/login_page_model.dart b/lib/on_boarding/on_boarding_legacy/login_page/login_page_model.dart new file mode 100644 index 00000000..d56459f4 --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/login_page/login_page_model.dart @@ -0,0 +1,113 @@ +import '/application_components/molecular_components/throw_exception/throw_exception_widget.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/custom_code/actions/index.dart' as actions; +import 'login_page_widget.dart' show LoginPageWidget; +import 'package:flutter/material.dart'; + +class LoginPageModel extends FlutterFlowModel { + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // State field(s) for emailAddress widget. + FocusNode? emailAddressFocusNode; + TextEditingController? emailAddressTextController; + String? Function(BuildContext, String?)? emailAddressTextControllerValidator; + // State field(s) for password widget. + FocusNode? passwordFocusNode; + TextEditingController? passwordTextController; + late bool passwordVisibility; + String? Function(BuildContext, String?)? passwordTextControllerValidator; + + @override + void initState(BuildContext context) { + passwordVisibility = false; + } + + @override + void dispose() { + unfocusNode.dispose(); + emailAddressFocusNode?.dispose(); + emailAddressTextController?.dispose(); + + passwordFocusNode?.dispose(); + passwordTextController?.dispose(); + } + + /// Action blocks. + Future signInActionPage( + BuildContext context, { + required String? emailAdress, + required String? passwd, + }) async { + String? devUUID; + ApiCallResponse? loginCall; + + await Future.wait([ + Future(() async { + FFAppState().email = emailAdress!; + }), + Future(() async { + FFAppState().passwd = passwd!; + }), + ]); + if ((FFAppState().email != '') && + (FFAppState().passwd != '')) { + devUUID = await actions.getDevUUID(); + FFAppState().devUUID = devUUID!; + loginCall = await PhpGroup.loginCall.call( + email: FFAppState().email, + password: FFAppState().passwd, + uuid: FFAppState().devUUID, + type: FFAppState().device, + description: '', + ); + FFAppState().userUUID = FFAppState().userUUID; + if (PhpGroup.loginCall.error( + (loginCall.jsonBody ?? ''), + ) == + false) { + FFAppState().isLogged = true; + + context.goNamed( + 'homePage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.fade, + ), + }, + ); + } else { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: MediaQuery.viewInsetsOf(context), + child: ThrowExceptionWidget( + msg: PhpGroup.loginCall.msg( + (loginCall?.jsonBody ?? ''), + )!, + ), + ), + ); + }, + ); + + FFAppState().email = ''; + FFAppState().passwd = ''; + FFAppState().update(() {}); + } + } else { + FFAppState().email = ''; + FFAppState().passwd = ''; + } + } +} diff --git a/lib/on_boarding/on_boarding_legacy/login_page/login_page_widget.dart b/lib/on_boarding/on_boarding_legacy/login_page/login_page_widget.dart new file mode 100644 index 00000000..ab64048d --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/login_page/login_page_widget.dart @@ -0,0 +1,971 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/actions/actions.dart' as action_blocks; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'login_page_model.dart'; +export 'login_page_model.dart'; + +class LoginPageWidget extends StatefulWidget { + const LoginPageWidget({ + super.key, + required this.device, + }); + + final String? device; + + @override + State createState() => _LoginPageWidgetState(); +} + +class _LoginPageWidgetState extends State + with TickerProviderStateMixin { + late LoginPageModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = {}; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => LoginPageModel()); + + _model.emailAddressTextController ??= TextEditingController(); + _model.emailAddressFocusNode ??= FocusNode(); + + _model.passwordTextController ??= TextEditingController(); + _model.passwordFocusNode ??= FocusNode(); + + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: WillPopScope( + onWillPop: () async => false, + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 6, + child: Container( + width: 100.0, + height: double.infinity, + decoration: const BoxDecoration(), + alignment: const AlignmentDirectional(0.0, -1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 35.0, 0.0, 35.0), + child: Container( + width: 548.0, + height: 112.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(0.0, 1.0), + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Text( + FFLocalizations.of(context) + .getText( + '0113wf5c' /* VAMOS LA! ENTRE COM A SUA CONT... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of( + context) + .displaySmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Container( + width: 291.0, + height: 167.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/sr43ucngg4a4/Vector.png', + width: 603.0, + height: 155.0, + fit: BoxFit.contain, + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 34.0, 0.0, 34.0, 0.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: + BorderRadius.circular(12.0), + shape: BoxShape.rectangle, + ), + child: Align( + alignment: + const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .emailAddressTextController, + focusNode: _model + .emailAddressFocusNode, + autofocus: false, + textCapitalization: + TextCapitalization.none, + textInputAction: + TextInputAction.next, + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of( + context) + .getText( + 'f2go5a71' /* Email */, + ), + labelStyle: + FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + suffixIcon: Icon( + Icons.email, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: TextInputType + .emailAddress, + validator: _model + .emailAddressTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .passwordTextController, + focusNode: _model + .passwordFocusNode, + autofocus: false, + textInputAction: + TextInputAction.send, + obscureText: !_model + .passwordVisibility, + decoration: InputDecoration( + labelText: + FFLocalizations.of( + context) + .getText( + 'paon3y0v' /* Senha */, + ), + labelStyle: + FlutterFlowTheme.of( + context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme + .of(context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFF1AAB5F), + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius + .circular(12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of( + context) + .primaryBackground, + suffixIcon: InkWell( + onTap: () => setState( + () => _model + .passwordVisibility = + !_model + .passwordVisibility, + ), + focusNode: FocusNode( + skipTraversal: + true), + child: Icon( + _model.passwordVisibility + ? Icons + .visibility_outlined + : Icons + .visibility_off_outlined, + color: FlutterFlowTheme + .of(context) + .accent1, + size: 24.0, + ), + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + validator: _model + .passwordTextControllerValidator + .asValidator(context), + ), + ), + ), + Builder( + builder: (context) { + if (MediaQuery.sizeOf(context) + .width < + kBreakpointSmall + ? true + : false) { + return Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 16.0), + child: FFButtonWidget( + onPressed: + () async { + await action_blocks + .singInActionApp( + context, + emailAdress: _model + .emailAddressTextController + .text, + password: _model + .passwordTextController + .text, + ); + }, + text: FFLocalizations + .of(context) + .getText( + 'wmbzwstw' /* Entrar */, + ), + options: + FFButtonOptions( + width: double + .infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: FlutterFlowTheme + .of(context) + .primary, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .info, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: + const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular( + 12.0), + ), + showLoadingIndicator: + false, + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 16.0), + child: FFButtonWidget( + onPressed: + () async { + context.pushNamed( + 'RegisterPage'); + }, + text: FFLocalizations + .of(context) + .getText( + 'j8567afe' /* Cadastrar */, + ), + options: + FFButtonOptions( + width: double + .infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: FlutterFlowTheme + .of(context) + .customColor1, + textStyle: + FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts.asMap().containsKey('Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: + const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular( + 12.0), + ), + showLoadingIndicator: + false, + ), + ), + ], + ); + } else { + return Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .spaceEvenly, + children: [ + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 16.0), + child: + FFButtonWidget( + onPressed: () { + print( + 'signInButtonLoginForm pressed ...'); + }, + text: FFLocalizations + .of(context) + .getText( + 'y3wd9q18' /* Entrar */, + ), + options: + FFButtonOptions( + width: double + .infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: FlutterFlowTheme.of( + context) + .accent1, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: + const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular( + 12.0), + ), + showLoadingIndicator: + false, + ), + ), + ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 16.0), + child: + FFButtonWidget( + onPressed: + () async { + context.pushNamed( + 'RegisterPage'); + }, + text: FFLocalizations + .of(context) + .getText( + 'j6ufb6sq' /* Cadastrar */, + ), + options: + FFButtonOptions( + width: double + .infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0.0, + 0.0, + 0.0, + 0.0), + color: FlutterFlowTheme.of( + context) + .customColor1, + textStyle: FlutterFlowTheme.of( + context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: + 16.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: + const BorderSide( + color: Colors + .transparent, + width: 1.0, + ), + borderRadius: + BorderRadius + .circular( + 12.0), + ), + showLoadingIndicator: + false, + ), + ), + ), + ].divide( + const SizedBox(width: 7.0)), + ); + } + }, + ), + + // You will have to add an action on this rich text to go to your login page. + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: InkWell( + splashColor: + Colors.transparent, + focusColor: + Colors.transparent, + hoverColor: + Colors.transparent, + highlightColor: + Colors.transparent, + onTap: () async { + context.pushNamed( + 'ForgotPasswordPage'); + }, + child: RichText( + textScaler: + MediaQuery.of(context) + .textScaler, + text: TextSpan( + children: [ + TextSpan( + text: FFLocalizations + .of(context) + .getText( + 'h85112qs' /* Você esqueceu a sua senha? */, + ), + style: TextStyle( + color: FlutterFlowTheme + .of(context) + .primaryText, + ), + ), + TextSpan( + text: FFLocalizations + .of(context) + .getText( + 'di48hdaj' /* Recupere aqui */, + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primary, + fontSize: 14.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .normal, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + mouseCursor: + SystemMouseCursors + .click, + recognizer: + TapGestureRecognizer() + ..onTap = + () async { + context.pushNamed( + 'ForgotPasswordPage'); + }, + ) + ], + style: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: + 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ).animateOnPageLoad(animationsMap[ + 'containerOnPageLoadAnimation']!), + ), + ), + ], + ), + Text( + FFLocalizations.of(context).getText( + 'gx2fp6zq' /* Termo de Uso */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/register_page/register_page_model.dart b/lib/on_boarding/on_boarding_legacy/register_page/register_page_model.dart new file mode 100644 index 00000000..4583ef8e --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/register_page/register_page_model.dart @@ -0,0 +1,53 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'register_page_widget.dart' show RegisterPageWidget; +import 'package:flutter/material.dart'; + +class RegisterPageModel extends FlutterFlowModel { + /// Local state fields for this page. + + String? email = 'danielsan@confia.com'; + + String? passwd = '12345678'; + + String? device = 'android'; + + String? name = 'Daniel-San'; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + // State field(s) for nameRegisterForm widget. + FocusNode? nameRegisterFormFocusNode; + TextEditingController? nameRegisterFormTextController; + String? Function(BuildContext, String?)? + nameRegisterFormTextControllerValidator; + // State field(s) for emailRegisterForm widget. + FocusNode? emailRegisterFormFocusNode; + TextEditingController? emailRegisterFormTextController; + String? Function(BuildContext, String?)? + emailRegisterFormTextControllerValidator; + // State field(s) for passwordRegisterForm widget. + FocusNode? passwordRegisterFormFocusNode; + TextEditingController? passwordRegisterFormTextController; + late bool passwordRegisterFormVisibility; + String? Function(BuildContext, String?)? + passwordRegisterFormTextControllerValidator; + + @override + void initState(BuildContext context) { + passwordRegisterFormVisibility = false; + } + + @override + void dispose() { + unfocusNode.dispose(); + nameRegisterFormFocusNode?.dispose(); + nameRegisterFormTextController?.dispose(); + + emailRegisterFormFocusNode?.dispose(); + emailRegisterFormTextController?.dispose(); + + passwordRegisterFormFocusNode?.dispose(); + passwordRegisterFormTextController?.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/register_page/register_page_widget.dart b/lib/on_boarding/on_boarding_legacy/register_page/register_page_widget.dart new file mode 100644 index 00000000..da8f34cc --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/register_page/register_page_widget.dart @@ -0,0 +1,867 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import '/actions/actions.dart' as action_blocks; +import 'package:easy_debounce/easy_debounce.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'register_page_model.dart'; +export 'register_page_model.dart'; + +class RegisterPageWidget extends StatefulWidget { + const RegisterPageWidget({super.key}); + + @override + State createState() => _RegisterPageWidgetState(); +} + +class _RegisterPageWidgetState extends State + with TickerProviderStateMixin { + late RegisterPageModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = {}; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => RegisterPageModel()); + + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + await Future.wait([ + Future(() async {}), + Future(() async { + if (isAndroid == true) { + _model.device = 'android'; + setState(() {}); + } else if (isiOS == true) { + _model.device = 'ios'; + setState(() {}); + } else { + _model.device = 'web'; + setState(() {}); + } + }), + ]); + }); + + _model.nameRegisterFormTextController ??= TextEditingController(); + _model.nameRegisterFormFocusNode ??= FocusNode(); + _model.nameRegisterFormFocusNode!.addListener(() => setState(() {})); + _model.emailRegisterFormTextController ??= TextEditingController(); + _model.emailRegisterFormFocusNode ??= FocusNode(); + _model.emailRegisterFormFocusNode!.addListener(() => setState(() {})); + _model.passwordRegisterFormTextController ??= TextEditingController(); + _model.passwordRegisterFormFocusNode ??= FocusNode(); + _model.passwordRegisterFormFocusNode!.addListener(() => setState(() {})); + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + flex: 6, + child: Container( + width: 100.0, + height: double.infinity, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + ), + alignment: const AlignmentDirectional(0.0, -1.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(4.0), + child: Container( + width: 669.0, + height: 112.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Align( + alignment: + const AlignmentDirectional(0.0, -1.0), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Text( + FFLocalizations.of(context).getText( + '2d8uulm3' /* INSIRA SEU EMAIL E SENHA, VAMO... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Container( + width: 291.0, + height: 167.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: SvgPicture.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/ug2zlyhca2sh/Frame_5.svg', + width: 603.0, + height: 155.0, + fit: BoxFit.contain, + ), + ), + ), + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(34.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .primaryBackground, + borderRadius: BorderRadius.circular(12.0), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .nameRegisterFormTextController, + focusNode: _model + .nameRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.nameRegisterFormTextController', + const Duration( + milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [ + AutofillHints.name + ], + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of( + context) + .getText( + '8kjhi406' /* Nome */, + ), + labelStyle: FlutterFlowTheme + .of(context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of( + context) + .primaryBackground, + suffixIcon: Icon( + Icons.person, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: + TextInputType.name, + validator: _model + .nameRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .emailRegisterFormTextController, + focusNode: _model + .emailRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.emailRegisterFormTextController', + const Duration( + milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [ + AutofillHints.email + ], + obscureText: false, + decoration: InputDecoration( + labelText: + FFLocalizations.of( + context) + .getText( + 'ro4zkkxp' /* Email */, + ), + labelStyle: FlutterFlowTheme + .of(context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .primaryText, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .success, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .error, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of( + context) + .primaryBackground, + suffixIcon: Icon( + Icons.email, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 22.0, + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .customColor1, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + keyboardType: TextInputType + .emailAddress, + validator: _model + .emailRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: SizedBox( + width: double.infinity, + child: TextFormField( + controller: _model + .passwordRegisterFormTextController, + focusNode: _model + .passwordRegisterFormFocusNode, + onChanged: (_) => + EasyDebounce.debounce( + '_model.passwordRegisterFormTextController', + const Duration( + milliseconds: 2000), + () => setState(() {}), + ), + autofocus: false, + autofillHints: const [ + AutofillHints.password + ], + obscureText: !_model + .passwordRegisterFormVisibility, + decoration: InputDecoration( + labelText: + FFLocalizations.of( + context) + .getText( + 'lzgobioa' /* Senha */, + ), + labelStyle: FlutterFlowTheme + .of(context) + .labelLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + FlutterFlowTheme.of( + context) + .customColor1, + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFF1AAB5F), + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + errorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: const BorderSide( + color: + Color(0xFFFF5963), + width: 0.5, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + filled: true, + fillColor: + FlutterFlowTheme.of( + context) + .primaryBackground, + suffixIcon: InkWell( + onTap: () => setState( + () => _model + .passwordRegisterFormVisibility = + !_model + .passwordRegisterFormVisibility, + ), + focusNode: FocusNode( + skipTraversal: true), + child: Icon( + _model.passwordRegisterFormVisibility + ? Icons + .visibility_outlined + : Icons + .visibility_off_outlined, + color: + FlutterFlowTheme.of( + context) + .accent1, + size: 24.0, + ), + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyLarge + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + validator: _model + .passwordRegisterFormTextControllerValidator + .asValidator(context), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + await action_blocks + .signUpActionApp( + context, + name: _model + .nameRegisterFormTextController + .text, + passwd: _model + .passwordRegisterFormTextController + .text, + email: _model + .emailRegisterFormTextController + .text, + device: FFAppState().device, + ); + }, + text: + FFLocalizations.of(context) + .getText( + 'c7sfyeh8' /* Cadastrar-se */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .accent1, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + + // You will have to add an action on this rich text to go to your login page. + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 12.0, 0.0, 12.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: + Colors.transparent, + onTap: () async { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': serializeParam( + '', + ParamType.String, + ), + }.withoutNulls, + ); + }, + child: RichText( + textScaler: + MediaQuery.of(context) + .textScaler, + text: TextSpan( + children: [ + TextSpan( + text: + FFLocalizations.of( + context) + .getText( + 'jglpa1tr' /* Você já tem uma conta? */, + ), + style: TextStyle( + color: FlutterFlowTheme + .of(context) + .primaryText, + ), + ), + TextSpan( + text: + FFLocalizations.of( + context) + .getText( + 'hfcm0td9' /* Clique aqui */, + ), + style: + FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme.of( + context) + .primary, + fontSize: + 14.0, + letterSpacing: + 0.0, + fontWeight: + FontWeight + .w600, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ) + ], + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + FlutterFlowTheme.of( + context) + .bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + FlutterFlowTheme.of( + context) + .bodyMediumFamily), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ).animateOnPageLoad(animationsMap[ + 'containerOnPageLoadAnimation']!), + ), + ), + ], + ), + Text( + FFLocalizations.of(context).getText( + 'c3kno4t9' /* Termo de Uso */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .secondaryText, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_model.dart b/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_model.dart new file mode 100644 index 00000000..974fc120 --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_model.dart @@ -0,0 +1,21 @@ +import '/flutter_flow/flutter_flow_util.dart'; +import 'welcome_page_widget.dart' show WelcomePageWidget; +import 'package:flutter/material.dart'; + +class WelcomePageModel extends FlutterFlowModel { + /// Local state fields for this page. + + String? device; + + /// State fields for stateful widgets in this page. + + final unfocusNode = FocusNode(); + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + unfocusNode.dispose(); + } +} diff --git a/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_widget.dart b/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_widget.dart new file mode 100644 index 00000000..1ec859fe --- /dev/null +++ b/lib/on_boarding/on_boarding_legacy/welcome_page/welcome_page_widget.dart @@ -0,0 +1,529 @@ +import '/flutter_flow/flutter_flow_animations.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'welcome_page_model.dart'; +export 'welcome_page_model.dart'; + +class WelcomePageWidget extends StatefulWidget { + const WelcomePageWidget({super.key}); + + @override + State createState() => _WelcomePageWidgetState(); +} + +class _WelcomePageWidgetState extends State + with TickerProviderStateMixin { + late WelcomePageModel _model; + + final scaffoldKey = GlobalKey(); + + final animationsMap = {}; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => WelcomePageModel()); + + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + if (FFAppState().isLogged == true) { + context.pushNamed( + 'homePage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.fade, + duration: Duration(milliseconds: 0), + ), + }, + ); + } else { + if (isAndroid == true) { + FFAppState().device = 'Android'; + setState(() {}); + } else if (isiOS == true) { + FFAppState().device = 'iOS'; + setState(() {}); + } else { + FFAppState().device = 'Web'; + setState(() {}); + } + } + }); + + animationsMap.addAll({ + 'containerOnPageLoadAnimation': AnimationInfo( + trigger: AnimationTrigger.onPageLoad, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + FadeEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: 0.0, + end: 1.0, + ), + MoveEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.0, 140.0), + end: const Offset(0.0, 0.0), + ), + ScaleEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(0.9, 0.9), + end: const Offset(1.0, 1.0), + ), + TiltEffect( + curve: Curves.easeInOut, + delay: 0.0.ms, + duration: 300.0.ms, + begin: const Offset(-0.349, 0), + end: const Offset(0, 0), + ), + ], + ), + }); + } + + @override + void dispose() { + _model.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + context.watch(); + + return GestureDetector( + onTap: () => _model.unfocusNode.canRequestFocus + ? FocusScope.of(context).requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: WillPopScope( + onWillPop: () async => false, + child: Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: SafeArea( + top: true, + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: SafeArea( + child: Container( + width: 648.0, + height: 208.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + ), + alignment: const AlignmentDirectional(0.0, 0.0), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(14.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + FFLocalizations.of(context).getText( + 'xflxvs9y' /* UMA EXPERIÊCIA COMPLETA */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .accent1, + fontSize: 24.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap() + .containsKey('Plus Jakarta Sans'), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, -1.0), + child: Text( + FFLocalizations.of(context).getText( + '5a86wzd1' /* COM CONFORTO ONDE VOCÊ ESTIVER... */, + ), + textAlign: TextAlign.start, + style: FlutterFlowTheme.of(context) + .displaySmall + .override( + fontFamily: 'Plus Jakarta Sans', + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 15.0, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + Container( + width: 284.0, + height: 200.0, + decoration: const BoxDecoration(), + child: ClipRRect( + borderRadius: BorderRadius.circular(0.0), + child: SvgPicture.network( + 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/lv1waa0etd3j/undraw_appreciate_it_re_yc8h_(1)_1.svg', + width: 603.0, + height: double.infinity, + fit: BoxFit.contain, + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(34.0), + child: Container( + width: double.infinity, + constraints: const BoxConstraints( + maxWidth: 570.0, + ), + decoration: BoxDecoration( + boxShadow: const [ + BoxShadow( + blurRadius: 0.0, + color: Colors.transparent, + offset: Offset( + 0.0, + 0.0, + ), + ) + ], + borderRadius: BorderRadius.circular(12.0), + ), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Builder( + builder: (context) { + if (MediaQuery.sizeOf(context).width < + kBreakpointSmall + ? true + : false) { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': serializeParam( + '', + ParamType.String, + ), + }.withoutNulls, + ); + }, + text: + FFLocalizations.of(context) + .getText( + '65nuva6j' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .primary, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .info, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'RegisterPage'); + }, + text: + FFLocalizations.of(context) + .getText( + '9u6oaw01' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .customColor1, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: + FlutterFlowTheme.of( + context) + .customColor3, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + ], + ); + } else { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'LoginPage', + queryParameters: { + 'device': + serializeParam( + '', + ParamType.String, + ), + }.withoutNulls, + ); + }, + text: FFLocalizations.of( + context) + .getText( + 'd1qem43w' /* Entrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .primary, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB( + 0.0, 0.0, 0.0, 16.0), + child: FFButtonWidget( + onPressed: () async { + context.pushNamed( + 'RegisterPage'); + }, + text: FFLocalizations.of( + context) + .getText( + 'bhowzv2u' /* Cadastrar */, + ), + options: FFButtonOptions( + width: double.infinity, + height: 44.0, + padding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0.0, 0.0, + 0.0, 0.0), + color: FlutterFlowTheme.of( + context) + .primary, + textStyle: FlutterFlowTheme + .of(context) + .titleSmall + .override( + fontFamily: + 'Plus Jakarta Sans', + color: FlutterFlowTheme + .of(context) + .secondaryText, + fontSize: 16.0, + letterSpacing: 0.0, + fontWeight: + FontWeight.w500, + useGoogleFonts: + GoogleFonts + .asMap() + .containsKey( + 'Plus Jakarta Sans'), + ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: + BorderRadius.circular( + 12.0), + ), + showLoadingIndicator: false, + ), + ), + ), + ].divide(const SizedBox(width: 7.0)), + ); + } + }, + ), + ], + ), + ), + ), + ).animateOnPageLoad( + animationsMap['containerOnPageLoadAnimation']!), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 00000000..19887d02 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,171 @@ +name: f_r_e_hub +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flutter: + sdk: flutter + flutter_localizations: + sdk: flutter + auto_size_text: 3.0.0 + cached_network_image: 3.3.1 + collection: 1.18.0 + crop_your_image: 1.0.0 + device_info_plus: 9.1.2 + dropdown_button2: 2.3.9 + easy_debounce: 2.0.1 + equatable: 2.0.5 + file_picker: 6.1.1 + flutter_animate: 4.1.1+1 + flutter_cache_manager: 3.3.1 + flutter_plugin_android_lifecycle: 2.0.17 + flutter_spinkit: 5.2.0 + flutter_staggered_grid_view: 0.7.0 + flutter_svg: 2.0.9 + font_awesome_flutter: 10.6.0 + from_css_color: 2.0.0 + go_router: 12.1.3 + google_fonts: 6.1.0 + http: 1.2.0 + image_picker: 1.0.4 + image_picker_android: 0.8.8 + image_picker_for_web: 3.0.1 + image_picker_ios: 0.8.8+2 + image_picker_platform_interface: 2.9.1 + intl: 0.18.1 + json_path: 0.6.2 + mime_type: 1.0.0 + page_transition: 2.1.0 + path_provider: 2.0.14 + path_provider_android: 2.0.25 + path_provider_foundation: 2.2.2 + path_provider_platform_interface: 2.0.6 + plugin_platform_interface: 2.1.8 + provider: 6.0.5 + shared_preferences: 2.2.2 + shared_preferences_android: 2.2.1 + shared_preferences_foundation: 2.3.4 + shared_preferences_platform_interface: 2.3.1 + shared_preferences_web: 2.2.1 + sqflite: 2.2.6 + timeago: 3.2.2 + url_launcher: 6.2.5 + url_launcher_android: 6.3.0 + url_launcher_ios: 6.2.5 + url_launcher_platform_interface: 2.3.2 + video_player: 2.8.1 + video_player_android: 2.4.10 + video_player_avfoundation: 2.5.1 + video_player_platform_interface: 6.2.1 + video_player_web: 2.1.2 + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.0 + +dependency_overrides: + http: 1.2.0 + uuid: ^4.0.0 + +dev_dependencies: + flutter_launcher_icons: 0.13.1 + flutter_lints: 3.0.0 + image: 4.0.17 + lints: 3.0.0 + + flutter_test: + sdk: flutter + + +flutter_launcher_icons: + android: 'launcher_icon' + ios: true + web: + generate: true + image_path: 'assets/images/app_launcher_icon.svg' + adaptive_icon_background: 'assets/images/adaptive_background_icon.svg' + adaptive_icon_foreground: 'assets/images/adaptive_foreground_icon.svg' + + +# 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/fonts/ + - assets/images/ + - assets/videos/ + - assets/audios/ + - assets/lottie_animations/ + - assets/rive_animations/ + - assets/pdfs/ + fonts: + - family: 'SF Pro' + fonts: + - asset: assets/fonts/SFPRODISPLAYREGULAR.OTF + - asset: assets/fonts/SFPRODISPLAYMEDIUM.OTF + weight: 500 + - asset: assets/fonts/SFPRODISPLAYBOLD.OTF + weight: 700 + + - family: Icons + fonts: + - asset: assets/fonts/icons.ttf + - family: Menu + fonts: + - asset: assets/fonts/menu.ttf + + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages + diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 00000000..9e847a93 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,17 @@ +// 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_test/flutter_test.dart'; + +import 'package:f_r_e_hub/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 00000000..300efaef Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/app_launcher_icon.svg b/web/icons/app_launcher_icon.svg new file mode 100644 index 00000000..5e3c0b13 --- /dev/null +++ b/web/icons/app_launcher_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/web/index.html b/web/index.html new file mode 100644 index 00000000..4001623d --- /dev/null +++ b/web/index.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FREHub + + + + + + + + + + + + + + + + + + + + +