refinamento e modularização

This commit is contained in:
jantunemesssias 2025-02-03 11:35:07 -03:00
commit f64d65425f
34 changed files with 860 additions and 18284 deletions

3
.gitignore vendored
View File

@ -29,6 +29,9 @@
.pub-cache/
.pub/
/build/
/coverage
.crashlytics
pubspec.lock
# Web related
lib/generated_plugin_registrant.dart

View File

@ -5,4 +5,4 @@
"other": "off"
},
"java.configuration.updateBuildConfiguration": "automatic"
}
}

View File

@ -1,2 +1,2 @@
gradle 8.10.2
kotlin 1.8.22
kotlin 2.0.20

View File

@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'com.android.library' apply false
id 'com.google.firebase.crashlytics'
id 'org.jetbrains.kotlin.android'
id "kotlin-android"
@ -35,6 +36,7 @@ android {
namespace 'com.freaccess.hub'
compileSdkVersion 34
compileSdk 35
// ndkVersion "25.1.8937393" // Example version
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@ -96,6 +98,15 @@ android {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
firebaseCrashlytics {
mappingFileUploadEnabled true
nativeSymbolUploadEnabled false // Disable NDK symbol upload
unstrippedNativeLibsDir "build/intermediates/merged_native_libs/release/out/lib" // Add this
strippedNativeLibsDir "build/intermediates/stripped_native_libs/release/out/lib"
// Point to your google-services.json location
// googleServicesResourceRoot "${project.projectDir}/../../android/app"
}
}
debug {
signingConfig signingConfigs.debug
@ -128,4 +139,5 @@ dependencies {
}
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'
// id 'com.google.firebase.crashlytics'

View File

@ -3,7 +3,7 @@
"project_number": "187064172787",
"firebase_url": "https://accessmoblie-da839.firebaseio.com",
"project_id": "accessmoblie-da839",
"storage_bucket": "accessmoblie-da839.appspot.com"
"storage_bucket": "accessmoblie-da839.firebasestorage.app"
},
"client": [
{

View File

@ -1,8 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.8.22'
ext.gradle_version = '8.6.0' // Replace with the latest version
ext.google_services_version = '4.4.2' // Replace with the latest version
ext.kotlin_version = '2.0.20'
ext.gradle_version = '8.8.0' // Replace with the latest version
ext.google_services_version = '4.4.1' // Replace with the latest version
repositories {
google()
mavenCentral()
@ -12,6 +12,7 @@ buildscript {
// Use a versão do Gradle que corresponde à sua configuração
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_services_version"
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
// Google Services plugin
}
}

View File

@ -18,13 +18,13 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id 'com.android.application' version '8.6.0' apply false
id 'com.android.library' version '8.6.0' apply false
id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
id 'com.android.application' version '8.8.0' apply false
id 'com.android.library' version '8.8.0' apply false
id 'org.jetbrains.kotlin.android' version '2.0.20' apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.gms.google-services" version "4.4.1" apply false
// END: FlutterFire Configuration
// id "org.jetbrains.kotlin.android" version "1.7.10" apply false
// id "org.jetbrains.kotlin.android" version "1.8.10" apply false

File diff suppressed because it is too large Load Diff

View File

@ -25,29 +25,44 @@ import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart
import 'package:integration_test/integration_test.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:patrol/patrol.dart';
import 'app_test.dart';
import 'fuzzer/fuzzer.dart';
import 'package:patrol_finders/patrol_finders.dart';
import 'package:integration_test/integration_test.dart';
export 'package:flutter_test/flutter_test.dart';
export 'package:patrol/patrol.dart';
part 'auth_test.dart';
part 'common.dart';
part 'home_test.dart';
part 'locals_test.dart';
part 'menu_test.dart';
part 'module_test.dart';
part 'notify_test.dart';
part 'profile_test.dart';
part 'property_test.dart';
part 'setting_test.dart';
part 'storage_test.dart';
part 'utils_test.dart';
part 'welcome_test.dart';
part 'vehicle_test.dart';
late PatrolIntegrationTester $;
late PatrolTester $;
void main() {
//init integration test
@ -56,20 +71,20 @@ void main() {
// setUp(() async {});
// tearDown(() async {});
// WelcomeTest.signInToSignUp();
// WelcomeTest.signUpToSignIn();
WelcomeTest.signInToSignUp();
WelcomeTest.signUpToSignIn();
// AuthenticationTest.signIn();
// AuthenticationTest.signUp();
// AuthenticationTest.signOut();
// AuthenticationTest.recovery();
// ModularizationTest.switchLicense();
// ModularizationTest.containLicense();
ModularizationTest.switchLicense();
ModularizationTest.containLicense();
// MenuTest.navToEntries();
// MenuTest.containEntries();
// MenuTest.labels2AppbarConsistency();
MenuTest.navToEntries();
MenuTest.containEntries();
MenuTest.labels2AppbarConsistency();
// LocalsTest.setLocal();
// LocalsTest.unlinkLocal();

View File

@ -2,9 +2,9 @@ part of 'app_test.dart';
class AuthenticationTest {
static Future<void> signIn() async {
patrol(
patrolWidgetTest(
'Sign-In with fuzzed emails',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester
.printToConsole('Authentication Test - Sign-In with fuzzed emails');
@ -43,7 +43,7 @@ class AuthenticationTest {
final credentials = fuzzer.fuzz(concat);
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
@ -59,9 +59,9 @@ class AuthenticationTest {
},
);
patrol(
patrolWidgetTest(
'Sign-In with email_app@exemplo.com',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-In with email_app@exemplo.com');
@ -72,7 +72,7 @@ class AuthenticationTest {
'passwordTextFormField': '12345678',
};
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
await _auth(credentials, $, throwsException);
@ -81,9 +81,9 @@ class AuthenticationTest {
}
static Future<void> signUp() async {
patrol(
patrolWidgetTest(
'Sign Up - credenciais já registradas',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-Up: credenciais já registradas');
@ -94,7 +94,7 @@ class AuthenticationTest {
'emailTextFormField': 'email_app@exemplo.com',
'passwordTextFormField': '12345678',
};
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
@ -102,9 +102,9 @@ class AuthenticationTest {
},
);
patrol(
patrolWidgetTest(
'Sign Up - credenciais novas',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester
.printToConsole('Authentication Test - Sign-Up: credenciais novas');
@ -151,7 +151,7 @@ class AuthenticationTest {
final credentials = fuzzer.fuzz(concat);
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
@ -170,14 +170,14 @@ class AuthenticationTest {
}
static Future<void> signOut() async {
patrol(
patrolWidgetTest(
'Deslogar da Conta',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Authentication Test - Sign-Out: Deslogar da Conta');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidget(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -197,7 +197,7 @@ class AuthenticationTest {
static void recovery() async {
patrol('Open url in the app', ($) async {
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidget(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -221,7 +221,7 @@ class AuthenticationTest {
Future<void> _auth(
Map<String, String> credentials,
PatrolIntegrationTester $,
PatrolTester $,
PatrolFinder throwsException,
) async {
await _enterCredentials(credentials, $);
@ -230,7 +230,7 @@ Future<void> _auth(
Future<void> _enterCredentials(
Map<String, String> credentials,
PatrolIntegrationTester $,
PatrolTester $,
) async {
for (var entry in credentials.entries) {
await $(ValueKey(entry.key)) //
@ -241,7 +241,7 @@ Future<void> _enterCredentials(
}
Future<void> _submit(
String key, PatrolIntegrationTester $, PatrolFinder throwsException) async {
String key, PatrolTester $, PatrolFinder throwsException) async {
await $(ValueKey(key)) //
.waitUntilVisible()
.tap();

View File

@ -1,11 +1,11 @@
part of 'app_test.dart';
final _patrolTesterConfig = PatrolTesterConfig(printLogs: true);
final _PatrolTesterConfig = PatrolTesterConfig(printLogs: true);
final _nativeAutomatorConfig = NativeAutomatorConfig(
findTimeout: Duration(seconds: 20), // 10 seconds is too short for some CIs
);
// Future<void> createApp(PatrolIntegrationTester $) async {
// Future<void> createApp(PatrolTester $) async {
// await app_main.main();
// await $.pumpAndSettle();
// }
@ -21,7 +21,7 @@ void patrol(
}) {
patrolTest(
description,
config: _patrolTesterConfig,
config: _PatrolTesterConfig,
nativeAutomatorConfig: nativeAutomatorConfig ?? _nativeAutomatorConfig,
framePolicy: framePolicy,
skip: skip,

View File

@ -46,13 +46,13 @@ class LocalsTest {
// }
// },
// );
patrol(
patrolWidgetTest(
'Selecionar um local disponível com somente um local disponivel', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Locals Test - Selecionar um local disponível');
await _loggedWithSomeoneLocalAccount($, false);
await _loggedWithSomeoneLocalAccount(false);
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
await $.waitUntilVisible($(LocalProfileComponentWidget));
@ -184,14 +184,14 @@ class LocalsTest {
// // }
// },
// );
patrol(
patrolWidgetTest(
'Desvincular do local selecionado com somente um local disponivel', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Locals Test - Desvincular do local selecionado com multiplos locais disponiveis');
await _loggedWithSomeoneLocalAccount($);
await _loggedWithSomeoneLocalAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -247,13 +247,13 @@ class LocalsTest {
expect(entriesFinder, findsWidgets);
});
patrol(
patrolWidgetTest(
'Vincular um local desvinculado com somente um local disponivel', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Locals Test - Vincular um local desvinculado');
await _loggedWithSomeoneLocalAccount($, false);
await _loggedWithSomeoneLocalAccount(false);
await $.pumpWidget(const App());
final PatrolFinder bottomSheetFinder =
@ -302,74 +302,62 @@ class LocalsTest {
}
static Future attachLocal() async {
patrol(
'Selecionar um local disponível com multíplos locais disponíveis', //
(PatrolIntegrationTester tester) async {
patrolWidgetTest(
'Auto-Validação de Locais com Multiplos Locais', //
(PatrolTester tester) async {
$ = tester;
await _loggedWithMultiLocalsAccount($);
$.tester.printToConsole('Locals Test - Vincular um local desvinculado');
await _loggedWithMultiLocalsAccount(false);
await $.pumpWidget(const App());
late Map<String, String> credentials;
final PatrolFinder throwsException = $('');
var name = ff.randomString(7, 7, true, true, true);
var email = '$name@example.com';
var password = '12345678';
credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password
};
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
await $.pumpWidget(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
credentials = {
'emailTextFormField': email,
'passwordTextFormField': password
};
await _auth(credentials, $, throwsException);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder listViewFinder = $(bottomSheetFinder) //
.$(ListView);
expect(listViewFinder, findsOneWidget);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder entriesFinder = $(listViewFinder) //
.$(CardItemTemplateComponentWidget);
expect(entriesFinder, findsWidgets);
await $.pumpAndSettle();
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await $.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 500));
return;
},
);
patrol(
'Selecionar um local disponível com somente um local disponível', //
(PatrolIntegrationTester tester) async {
patrolWidgetTest(
'Auto-Validação de Locais com local unico', //
(PatrolTester tester) async {
$ = tester;
await _loggedWithSomeoneLocalAccount($);
$.tester.printToConsole('Locals Test - Vincular um local desvinculado');
await _loggedWithSomeoneLocalAccount(false);
await $.pumpWidget(const App());
late Map<String, String> credentials;
final PatrolFinder throwsException = $('');
var name = ff.randomString(7, 7, true, true, true);
var email = '$name@example.com';
var password = '12345678';
credentials = {
'nameTextFormField': name,
'emailTextFormField': email,
'passwordTextFormField': password
};
final PatrolFinder bottomSheetFinder =
await $(BottomArrowLinkedLocalsComponentWidget) //
.waitUntilVisible();
expect(bottomSheetFinder, findsOneWidget);
await $.pumpWidget(const App());
await _navigateToSignUp($);
await _auth(credentials, $, throwsException);
credentials = {
'emailTextFormField': email,
'passwordTextFormField': password
};
await _auth(credentials, $, throwsException);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder listViewFinder = $(bottomSheetFinder) //
.$(ListView);
expect(listViewFinder, findsOneWidget);
await $.pump(const Duration(milliseconds: 500));
final PatrolFinder entriesFinder = $(listViewFinder) //
.$(CardItemTemplateComponentWidget);
expect(entriesFinder, findsWidgets);
await $.pumpAndSettle();
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await $.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 500));
return;
},
);
}

View File

@ -2,15 +2,15 @@ part of 'app_test.dart';
class MenuTest {
static Future labels2AppbarConsistency() async {
patrol(
patrolWidgetTest(
'As labels dos menuItems correspondem aos títulos das AppBars? (MultiLocais)',
//
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Menu Test - As labels dos menuItems correspondem aos títulos das AppBars?');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -96,13 +96,13 @@ class MenuTest {
}
static Future containEntries() async {
patrol(
patrolWidgetTest(
'HomeMenu contém seus itens? (MultiLocais)', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - HomeMenu contém seus itens?');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -135,13 +135,13 @@ class MenuTest {
expect(entriesKey, containsAll(menuKeys));
},
);
patrol(
patrolWidgetTest(
'HomeMenu contém seus itens? (MonoLocal)', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - HomeMenu contém seus itens?');
await _loggedWithSomeoneLocalAccount($);
await _loggedWithSomeoneLocalAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -175,13 +175,13 @@ class MenuTest {
},
);
patrol(
patrolWidgetTest(
'DrawerMenu contém seus itens? (MultiLocais)', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - DrawerMenu contém seus itens?');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -222,13 +222,13 @@ class MenuTest {
await Future.delayed(const Duration(milliseconds: 500));
},
);
patrol(
patrolWidgetTest(
'DrawerMenu contém seus itens? (MonoLocal)', //
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - DrawerMenu contém seus itens?');
await _loggedWithSomeoneLocalAccount($);
await _loggedWithSomeoneLocalAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -272,13 +272,13 @@ class MenuTest {
}
static Future navToEntries() async {
patrol(
patrolWidgetTest(
'Navegação entre items do Menu (MultiLocais)',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Menu Test - Navegação entre items do Menu');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));

View File

@ -2,13 +2,14 @@ part of 'app_test.dart';
class ModularizationTest {
static Future containLicense() async {
patrol('Os modulos de licença está sendo processados? (MultiLocais)',
(PatrolIntegrationTester tester) async {
patrolWidgetTest(
'Os modulos de licença está sendo processados? (MultiLocais)',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Modularization Test - Os modulos de licença está sendo processados?');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -27,13 +28,14 @@ class ModularizationTest {
return;
});
patrol('Os modulos de licença está sendo processados? (MonoLocal)',
(PatrolIntegrationTester tester) async {
patrolWidgetTest(
'Os modulos de licença está sendo processados? (MonoLocal)',
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole(
'Modularization Test - Os modulos de licença está sendo processados?');
await _loggedWithSomeoneLocalAccount($);
await _loggedWithSomeoneLocalAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));
@ -55,13 +57,13 @@ class ModularizationTest {
}
static Future switchLicense() async {
patrol(
patrolWidgetTest(
'Licença está sendo atualizada?',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Licença está sendo atualizada?');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
await $.waitUntilVisible($(MenuStaggeredView));

View File

@ -1,8 +1,8 @@
part of 'app_test.dart';
Future<void> _loggedWithMultiLocalsAccount(PatrolIntegrationTester $,
Future<void> _loggedWithMultiLocalsAccount(
[bool forceLinkedLocal = true]) async {
await _init($);
await _init();
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'true');
await StorageHelper() //
@ -19,18 +19,23 @@ Future<void> _loggedWithMultiLocalsAccount(PatrolIntegrationTester $,
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
if (forceLinkedLocal == true) {
await StorageHelper().set(ProfileStorageKey.clientUUID.key, '7');
await StorageHelper().set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper()
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO');
await PhpGroup.resopndeVinculo.call(tarefa: 'A');
await LicenseRepositoryImpl().resetLicense();
await PhpGroup //
.resopndeVinculo
.call(tarefa: 'A');
await LicenseRepositoryImpl() //
.resetLicense();
}
}
Future<void> _loggedWithSomeoneLocalAccount(PatrolIntegrationTester $,
Future<void> _loggedWithSomeoneLocalAccount(
[bool forceLinkedLocal = true]) async {
await _init($);
await _init();
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'true');
await StorageHelper() //
@ -47,17 +52,22 @@ Future<void> _loggedWithSomeoneLocalAccount(PatrolIntegrationTester $,
await StorageHelper() //
.set(LocalsStorageKey.isNewVersion.key, true);
if (forceLinkedLocal == true) {
await StorageHelper().set(ProfileStorageKey.clientUUID.key, '7');
await StorageHelper().set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper()
await StorageHelper() //
.set(ProfileStorageKey.clientUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO');
await PhpGroup.resopndeVinculo.call(tarefa: 'A');
await LicenseRepositoryImpl().resetLicense();
await PhpGroup //
.resopndeVinculo
.call(tarefa: 'A');
await LicenseRepositoryImpl() //
.resetLicense();
}
}
Future<void> _unlogged(PatrolIntegrationTester $) async {
await _init($);
Future<void> _unlogged() async {
await _init();
await StorageHelper() //
.set(SecureStorageKey.isLogged.value, 'false');
await StorageHelper() //
@ -76,7 +86,7 @@ Future<void> _unlogged(PatrolIntegrationTester $) async {
.set(LocalsStorageKey.isNewVersion.key, true);
}
Future<void> _init(PatrolIntegrationTester $) async {
Future<void> _init() async {
WidgetsFlutterBinding.ensureInitialized();
await _initializeTracking();
await _initializeStorage();
@ -88,12 +98,12 @@ Future<void> _init(PatrolIntegrationTester $) async {
await _initializeNav();
}
Future<void> _navigateToSignIn(PatrolIntegrationTester $) async {
Future<void> _navigateToSignIn(PatrolTester $) async {
final signInButton = $(#toggleSignInPage).waitUntilVisible();
await signInButton.tap();
}
Future<void> _navigateToSignUp(PatrolIntegrationTester $) async {
Future<void> _navigateToSignUp(PatrolTester $) async {
final signUpButton = $(#toggleSignUpPage).waitUntilVisible();
await signUpButton.tap();
}

View File

@ -2,14 +2,14 @@ part of 'app_test.dart';
class VehicleTest {
static Future<void> vehiclePage() async {
patrol(
patrolWidgetTest(
'Vehicle Page',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Vehicle Page');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
ff.navigatorKey.currentContext!.go('/vehiclesOnThePropertyPage');
@ -64,17 +64,19 @@ class VehicleTest {
await $(DetailsComponentWidget).waitUntilVisible();
expect(detailsFinder, findsOneWidget);
await $.native.pressBack().then((_) => $.pumpAndSettle());
await _navigateBackUsingSystemGesture();
// await $.native.pressBack().then((_) => $.pumpAndSettle());
}
},
);
patrol(
patrolWidgetTest(
'License',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Vehicle Page');
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
// await StorageHelper().set(
// LicenseKeys.vehiclesManager.value,
@ -140,14 +142,14 @@ class VehicleTest {
}
static Future<void> historyScreen() async {
patrol(
patrolWidgetTest(
'historyScreen',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Vehicle Page');
final PatrolFinder throwsException = $(Dialog).$(ThrowExceptionWidget);
await _loggedWithMultiLocalsAccount($);
await _loggedWithMultiLocalsAccount();
await $.pumpWidgetAndSettle(const App());
ff.navigatorKey.currentContext!.go('/vehiclesOnThePropertyPage');
@ -198,7 +200,9 @@ class VehicleTest {
await $(DetailsComponentWidget).waitUntilVisible();
expect(detailsFinder, findsOneWidget);
await $.native.pressBack().then((_) => $.pumpAndSettle());
await _navigateBackUsingSystemGesture();
// await $.native.pressBack().then((_) => $.pumpAndSettle());
}
},
);

View File

@ -2,12 +2,12 @@ part of 'app_test.dart';
class WelcomeTest {
static Future signInToSignUp() async {
patrol(
patrolWidgetTest(
'Sign-In to Sign-Up',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Welcome Test - Sign-In to Sign-Up');
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignIn($);
@ -17,12 +17,12 @@ class WelcomeTest {
}
static Future signUpToSignIn() async {
patrol(
patrolWidgetTest(
'Sign-Up to Sign-In',
(PatrolIntegrationTester tester) async {
(PatrolTester tester) async {
$ = tester;
$.tester.printToConsole('Welcome Test - Sign-Up to Sign-In');
await _unlogged($);
await _unlogged();
await $.pumpWidgetAndSettle(const App());
await _navigateToSignUp($);
await _navigateToSignIn($);

View File

@ -396,19 +396,19 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0
app_tracking_transparency: e169b653478da7bb15a6c61209015378ca73e375
awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5
app_links: 3da4c36b46cac3bf24eb897f1a6ce80bda109874
app_tracking_transparency: 3d84f147f67ca82d3c15355c36b1fa6b66ca7c92
awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
firebase_analytics: 1a66fe8d4375eccff44671ea37897683a78b2675
firebase_core: ceec591a66629daaee82d3321551692c4a871493
firebase_crashlytics: e4f04180f443d5a8b56fbc0685bdbd7d90dd26f0
firebase_messaging: 15d8b557010f3bb7b98d0302e1c7c8fbcd244425
firebase_analytics: 2090f32a7f5364b03cdf11aa7e904f4610309563
firebase_core: 53cecb83c72fea329b267bb0accb06a33e9f036a
firebase_crashlytics: 4a35a15cbb0d9ba176f9bb2dfd3aa44c762c434f
firebase_messaging: 62c8a01f1ee118754d01dd4fd83ba670980326a3
FirebaseAnalytics: 27eb78b97880ea4a004839b9bac0b58880f5a92a
FirebaseCore: 3cf438f431f18c12cdf2aaf64434648b63f7e383
FirebaseCoreExtension: 30bb063476ef66cd46925243d64ad8b2c8ac3264
@ -419,42 +419,42 @@ SPEC CHECKSUMS:
FirebaseRemoteConfigInterop: c3a5c31b3c22079f41ba1dc645df889d9ce38cb9
FirebaseSessions: 655ff17f3cc1a635cbdc2d69b953878001f9e25b
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_secure_storage_darwin: 12d2375c690785d97a4e586f15f11be5ae35d5b0
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
google_mlkit_commons: 384e4e206e122b6dad430d3158205e0b2fac6789
google_mlkit_face_detection: ff627695d8eba051db7e0f13f7b20d802df1f84c
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038
google_mlkit_commons: 92c769cc2e0a2bfdeb3c38091a36e8a9cc8c63d4
google_mlkit_face_detection: 76f493a9ffcb1aeb0ad4abd13ea58403e092ab84
GoogleAppMeasurement: 6e49ffac7d3f2c3ded9cc663f912a13b67bbd0de
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleMLKit: eff9e23ec1d90ea4157a1ee2e32a4f610c5b3318
GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
IosAwnCore: 653786a911089012092ce831f2945cd339855a89
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
MLImage: 0ad1c5f50edd027672d8b26b0fee78a8b4a0fc56
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
MLKitFaceDetection: 2a593db4837db503ad3426b565e7aab045cefea5
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
patrol: 0564cee315ff6c86fb802b3647db05cc2d3d0624
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
patrol: dd82ffedfee3aba87c1d0ed2daad0b77bfb8ee1f
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
share_plus: 011d6fb4f9d2576b83179a3a5c5e323202cdabcf
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
PODFILE CHECKSUM: 1214504d483029dbea12c83e130a53cc7299687f
COCOAPODS: 1.15.2
COCOAPODS: 1.16.2

View File

@ -216,6 +216,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
DB4ADAD93A6C1B6E82A2FDA3 /* [CP] Copy Pods Resources */,
106EFC912B39433BCC0D0CA9 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
);
buildRules = (
);
@ -290,6 +291,24 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
106EFC912B39433BCC0D0CA9 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\"\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --platform=ios --apple-project-path=\"${SRCROOT}\" --env-platform-name=\"${PLATFORM_NAME}\" --env-configuration=\"${CONFIGURATION}\" --env-project-dir=\"${PROJECT_DIR}\" --env-built-products-dir=\"${BUILT_PRODUCTS_DIR}\" --env-dwarf-dsym-folder-path=\"${DWARF_DSYM_FOLDER_PATH}\" --env-dwarf-dsym-file-name=\"${DWARF_DSYM_FILE_NAME}\" --env-infoplist-path=\"${INFOPLIST_PATH}\" --default-config=default\n";
};
35A087622D3ED1C700BEE419 /* xcode_backend build */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

View File

@ -19,7 +19,7 @@
<key>PROJECT_ID</key>
<string>accessmoblie-da839</string>
<key>STORAGE_BUCKET</key>
<string>accessmoblie-da839.appspot.com</string>
<string>accessmoblie-da839.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>

View File

@ -235,6 +235,7 @@ class UpdateVehicle {
'licensePlate': licensePlate,
'color': color,
'model': model,
'vehicleId': vehicleId
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
@ -364,8 +365,8 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
enText: 'Name:',
): historyItem['AGP_NOME'] ?? '',
FFLocalizations.of(context).getVariableText(
ptText: 'Data:',
enText: 'Data:',
ptText: 'Vencimento',
enText: 'Expiration',
): formatDate(historyItem['AGP_DT_VISITA']),
FFLocalizations.of(context).getVariableText(
ptText: 'Observação:',
@ -398,19 +399,34 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
enText: 'Visitor',
): FlutterFlowTheme.of(context).alternate2,
},
_getStatusMap(context, historyItem['AGP_STATUS'])
_getStatusMap(context, historyItem)
];
}
Map<String, Color> _getStatusMap(BuildContext context, String status) {
switch (status) {
Map<String, Color> _getStatusMap(BuildContext context, dynamic json) {
late Map<String, Color> statusColorMap;
log(DateTime.parse(json['AGP_DT_VISITA']).toString());
log(DateTime.now().toString());
final DateTime now = DateTime.now();
final DateTime date = DateTime.parse(json['AGP_DT_VISITA']);
final bool isExpired = now.isAfter(date);
final String statusMap = json['AGP_STATUS'];
switch (statusMap) {
case 'AT':
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).success,
};
return isExpired
? {
FFLocalizations.of(context).getVariableText(
ptText: 'Vencido',
enText: 'Expired',
): FlutterFlowTheme.of(context).error,
}
: {
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).success,
};
case 'CO':
return {
FFLocalizations.of(context).getVariableText(

View File

@ -1,5 +1,6 @@
import 'dart:developer';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@ -7,6 +8,8 @@ import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
@ -132,6 +135,20 @@ class _AboutSystemPageState extends State<AboutSystemPage> {
width: 100,
child: Image.asset('assets/images/fre.png'),
);
// return GestureDetector(
// onTap: () {
// final exception = Exception('Crashando');
// final stackTrace = Trace.current();
// LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Pets",
// exception, stackTrace);
// FirebaseCrashlytics.instance.crash();
// },
// child: SizedBox(
// height: 100,
// width: 100,
// child: Image.asset('assets/images/fre.png'),
// ),
// );
}
Widget _buildLaunch() {

View File

@ -53,7 +53,7 @@ class DefaultFirebaseOptions {
projectId: 'accessmoblie-da839',
authDomain: 'accessmoblie-da839.firebaseapp.com',
databaseURL: 'https://accessmoblie-da839.firebaseio.com',
storageBucket: 'accessmoblie-da839.appspot.com',
storageBucket: 'accessmoblie-da839.firebasestorage.app',
measurementId: 'G-L4BQGX2WLZ',
);
@ -63,7 +63,7 @@ class DefaultFirebaseOptions {
messagingSenderId: '187064172787',
projectId: 'accessmoblie-da839',
databaseURL: 'https://accessmoblie-da839.firebaseio.com',
storageBucket: 'accessmoblie-da839.appspot.com',
storageBucket: 'accessmoblie-da839.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
@ -72,7 +72,7 @@ class DefaultFirebaseOptions {
messagingSenderId: '187064172787',
projectId: 'accessmoblie-da839',
databaseURL: 'https://accessmoblie-da839.firebaseio.com',
storageBucket: 'accessmoblie-da839.appspot.com',
storageBucket: 'accessmoblie-da839.firebasestorage.app',
androidClientId:
'187064172787-7et0qu5p2qtmisvqgndn3kfi1b7u9ifl.apps.googleusercontent.com',
iosClientId:

View File

@ -48,18 +48,32 @@ void _initializeUrlStrategy() {
print('URL Strategy initialized');
}
void _initializeSystemSettings() {
Future<void> _initializeSystemSettings() async {
print('Initializing System Settings...');
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
final crashlyticsInstance = FirebaseCrashlytics.instance;
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
if (kDebugMode) {
//kDebugMode
print('Debug mode');
} else {
final crashlyticsInstance = FirebaseCrashlytics.instance;
print('Release mode');
if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
FlutterError.onError = crashlyticsInstance.recordFlutterError;
print('Crashlytics enabled');
bool unsentReports =
await FirebaseCrashlytics.instance.checkForUnsentReports();
if (unsentReports) {
// Existem relatórios não enviados
await crashlyticsInstance.sendUnsentReports();
print('Existem relatórios de falhas não enviados.');
} else {
// Não existem relatórios não enviados
print('Todos os relatórios de falhas foram enviados.');
}
} else {
print('Release mode');
await crashlyticsInstance.setCrashlyticsCollectionEnabled(true);
// if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
FlutterError.onError = await crashlyticsInstance.recordFlutterError;
print('Crashlytics enabled');
// }
}
}

View File

@ -180,7 +180,7 @@ class _AppState extends State<App> {
);
_setupFirebaseMessaging();
// if (TestUtil.isInTest) //
// if (TestUtil.isInTest) //
DeepLinkService().ensureInitialization();
}

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/index.dart';
@ -196,6 +198,8 @@ class _VisitHistoryWidgetState extends State<VisitHistoryWidget>
}
Widget _item(BuildContext context, dynamic visitaWrapItem) {
log(DateTime.now().toString());
log(visitaWrapItem['VAW_DTFIM'].toString());
return CardItemTemplateComponentWidget(
imagePath:
'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=getFoto&Documento=${visitaWrapItem['VTE_DOCUMENTO'] ?? ''}&tipo=E',
@ -218,10 +222,19 @@ class _VisitHistoryWidgetState extends State<VisitHistoryWidget>
statusHashMap: [
if (Status.getStatus(visitaWrapItem['VAW_STATUS']) == StatusEnum.active)
{
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).warning,
if (visitaWrapItem['VAW_DTFIM'] != '' &&
visitaWrapItem['VAW_DTFIM'] != null)
if (DateTime.now().isAfter(
DateTime.parse(visitaWrapItem['VAW_DTFIM'] as String)))
FFLocalizations.of(context).getVariableText(
ptText: 'Vencido',
enText: 'Expired',
): FlutterFlowTheme.of(context).error
else
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).warning,
},
if (Status.getStatus(visitaWrapItem['VAW_STATUS']) ==
StatusEnum.finished)

View File

@ -6,27 +6,142 @@ part of 'vehicles_on_the_property.dart';
class VehicleHistoryScreen extends StatefulWidget {
VehicleHistoryScreen(this.model, {super.key});
late VehicleModel model;
late Future<void> _future;
List<dynamic> _wrap = [];
int _pageNumber = 1;
bool _hasData = false;
bool _loading = false;
int count = 0;
@override
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
}
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
late Future<void> _future = _fetchVisits();
late ScrollController _scrollController;
List<dynamic> _wrap = [];
int _pageNumber = 1;
bool _hasData = false;
bool _loading = false;
int count = 0;
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
with _FetchingMixin, _ScrollControllerMixin, _CardItemMixin {
@override
void initState() {
super.initState();
_initializeScrollController();
widget._future = _fetch();
}
// widget.model = createModel(context, () => VehicleModel());
_future = _fetchVisits();
@override
Widget build(BuildContext context) {
late final limitedHeaderTextSize =
LimitedFontSizeUtil.getHeaderFontSize(context);
late final double limitedBodyTextSize =
LimitedFontSizeUtil.getBodyFontSize(context);
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (widget._hasData == false &&
widget._pageNumber <= 1 &&
widget._loading == false)
_buildNoDataFound(context, limitedHeaderTextSize)
else if (widget._hasData == true || widget._pageNumber >= 1)
_buildVehicleList(context, limitedBodyTextSize),
if (widget._hasData == true && widget._loading == true)
_buildLoadingIndicator(context),
].addToStart(const SizedBox(height: 0)),
);
}
Widget _buildNoDataFound(BuildContext context, double limitedHeaderTextSize) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Center(
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Nenhum veículo encontrado!",
enText: "No vehicle found",
),
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedHeaderTextSize,
),
),
)
],
),
);
}
Widget _buildVehicleList(BuildContext context, double limitedBodyTextSize) {
return Expanded(
child: FutureBuilder<void>(
future: widget._future,
builder: (context, snapshot) {
return ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
controller: _scrollController,
itemCount: widget._wrap.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
return _buildHeader(context, limitedBodyTextSize);
} else {
Map<String, dynamic> item = widget._wrap[index - 1];
return FutureBuilder<Widget>(
future: _item(context, item),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return snapshot.data ?? Container();
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
},
);
},
),
);
}
Widget _buildHeader(BuildContext context, double limitedBodyTextSize) {
log('amountRegister: ${widget.model.amountRegister}');
return Padding(
padding: const EdgeInsets.only(right: 30, top: 10),
child: Text(
(widget.model.amountRegister == '0' ||
widget.model.amountRegister == null)
? ''
: "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Veículos: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/${widget.count}",
textAlign: TextAlign.right,
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedBodyTextSize,
),
),
);
}
Widget _buildLoadingIndicator(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
);
}
}
// Mixin for Scroll Controller
mixin _ScrollControllerMixin on _FetchingMixin {
late ScrollController _scrollController;
void _initializeScrollController() {
_scrollController = ScrollController()
..addListener(() {
if (_scrollController.position.atEdge &&
@ -36,6 +151,56 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
});
}
void _loadMore() {
if (widget._hasData == true) {
widget._pageNumber++;
widget._future = _fetch();
}
}
}
// Mixin for Fetch Visits
mixin _FetchingMixin on State<VehicleHistoryScreen> {
Future<ApiCallResponse?> _fetch() async {
try {
setState(() => widget._loading = true);
var response = await PhpGroup.getVehiclesByProperty
.call(widget._pageNumber.toString());
final List<dynamic> vehicles = response.jsonBody['vehicles'] ?? [];
safeSetState(() => widget.count = response.jsonBody['total_rows'] ?? 0);
if (vehicles.isNotEmpty) {
setState(() {
widget._wrap.addAll(vehicles);
widget._hasData = true;
widget._loading = false;
});
return response;
}
_showNoMoreDataSnackBar(context);
setState(() {
widget._hasData = false;
widget._loading = false;
});
return null;
} catch (e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículo", e, s);
setState(() {
widget._hasData = false;
widget._loading = false;
});
}
return null;
}
void _showNoMoreDataSnackBar(BuildContext context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
@ -54,36 +219,49 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
),
);
}
}
String mockRandomMapStatusColor() {
var statuses = [
'ATI',
'INA',
'APR_CREATE',
'APR_DELETE',
'APR_UPDATE',
'AGU_CHANGE'
];
statuses.shuffle();
return statuses.first;
}
// Mixin for Card Item
mixin _CardItemMixin on _FetchingMixin {
Future<Widget> _item(BuildContext context, Map<String, dynamic> uItem) async {
// uItem['status'] = mockRandomMapStatusColor();
final bool? isOwner = uItem['isOwnerVehicle'];
late final IconData? iconData;
late final FreCardIcon? cardIcon;
final IconData iconData =
isOwner == true ? Symbols.no_crash : Symbols.directions_car;
final FreCardIcon? cardIcon = isOwner != null
? FreCardIcon(
height: 50,
width: 100,
icon: Icon(iconData, size: 80, opticalSize: 10))
: null;
if (isOwner is bool) {
iconData = isOwner ? Symbols.no_crash : Symbols.directions_car;
cardIcon = FreCardIcon(
height: 50,
width: 100,
icon: Icon(iconData, size: 80, opticalSize: 10));
}
final String? tag = uItem['tag'];
final bool containTag = tag.isNotNullAndEmpty;
final Map<String, String> labelsHashMap = {
final Map<String, String> labelsHashMap =
_generateLabelsHashMap(context, uItem, tag, containTag);
final statusHashMapList = await _generateStatusHashMapList(uItem);
Future<void> onTapCardItemAction() async {
await _handleCardItemTap(context, cardIcon, uItem);
}
final statusLinkedHashMap = statusHashMapList
.map((map) => LinkedHashMap<String, Color>.from(map))
.toList();
final length = statusLinkedHashMap.expand((e) => [e.length]);
return CardItemTemplateComponentWidget(
icon: cardIcon,
labelsHashMap: labelsHashMap,
statusHashMap: statusHashMapList,
onTapCardItemAction: onTapCardItemAction,
itemWidthFactor: length == 1 ? 0.25 : 0.50,
);
}
Map<String, String> _generateLabelsHashMap(BuildContext context,
Map<String, dynamic> uItem, String? tag, bool containTag) {
return {
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
uItem['licensePlate'] ?? '',
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
@ -92,208 +270,47 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
uItem['personName'] ?? '',
if (containTag)
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:':
uItem['tag'] ?? '',
tag ?? '',
};
final Map<String, Color>? statusHashMap =
await widget.model.generateStatusColorMap(uItem, 2);
final List<Map<String, Color>?> statusHashMapList = [
await widget.model.generateStatusColorMap(uItem, 2)
];
Future<void> onTapCardItemAction() async {
final widgetFuture = widget.model.buildVehicleDetails(
icon: isOwner is bool ? cardIcon : null,
}
Future<List<Map<String, Color>>> _generateStatusHashMapList(
Map<String, dynamic> uItem) async {
final statusHashMap =
await widget.model.generateStatusColorMap(uItem, false);
return statusHashMap != null ? [statusHashMap] : [];
}
Future<void> _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon,
Map<String, dynamic> uItem) async {
try {
final dialogContent = await widget.model.buildVehicleDetails(
icon: cardIcon,
item: uItem,
context: context,
model: widget.model,
);
final dialogContent = await widgetFuture;
await showDialog(
useSafeArea: true,
context: context,
builder: (context) {
return Dialog(
alignment: Alignment.center,
child: dialogContent,
);
},
builder: (context) =>
Dialog(alignment: Alignment.center, child: dialogContent),
).whenComplete(() {
safeSetState(() {
_pageNumber = 1;
_wrap = [];
_future = _fetchVisits();
});
}).catchError((e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículos", e, s);
safeSetState(() {
_hasData = false;
_loading = false;
widget._pageNumber = 1;
widget._wrap = [];
widget._future = _fetch();
});
});
}
final statusLinkedHashMap = statusHashMapList
.map((map) => LinkedHashMap<String, Color>.from(map ?? {}))
.toList();
final length = statusLinkedHashMap.expand((e) => [e.length]);
print('CardItemTemplateComponentWidget: ${length}');
return CardItemTemplateComponentWidget(
icon: cardIcon,
labelsHashMap: labelsHashMap,
statusHashMap: statusHashMapList,
onTapCardItemAction: onTapCardItemAction,
itemWidthFactor: length == 1 ? 0.25 : 0.50,
);
// double itemWidthFactor = statusHashMap.length == 1 ? 0.5 : 0.5;
// double itemWidthFactor;
// if (statusCount >= 3 && statusCount % 3 != 0) {
// itemWidthFactor = (index % 3 == 2) ? 0.5 : 0.25;
// } else if (statusCount == 3) {
// itemWidthFactor = (index == 2) ? 0.52 : 0.25;
// } else {
// itemWidthFactor = statusCount == 1 ? 0.5 : 0.25;
// }
}
Future<ApiCallResponse?> _fetchVisits() async {
try {
setState(() => _loading = true);
var response =
await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString());
final List<dynamic> vehicles = response.jsonBody['vehicles'] ?? [];
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);
if (vehicles.isNotEmpty) {
setState(() {
_wrap.addAll(vehicles);
_hasData = true;
_loading = false;
});
return response;
}
_showNoMoreDataSnackBar(context);
setState(() {
_hasData = false;
_loading = false;
});
return null;
} catch (e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículo", e, s);
setState(() {
_hasData = false;
_loading = false;
"proccessRequest.php", "", "Consulta de Veículos", e, s);
safeSetState(() {
widget._hasData = false;
widget._loading = false;
});
}
return null;
}
void _loadMore() {
if (_hasData == true) {
_pageNumber++;
_future = _fetchVisits();
}
}
@override
Widget build(BuildContext context) {
late final limitedHeaderTextSize =
LimitedFontSizeUtil.getHeaderFontSize(context);
late final double limitedBodyTextSize =
LimitedFontSizeUtil.getBodyFontSize(context);
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (_hasData == false && _pageNumber <= 1 && _loading == false)
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Center(
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Nenhum veículo encontrado!",
enText: "No vehicle found",
),
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedHeaderTextSize,
),
),
)
],
),
)
else if (_hasData == true || _pageNumber >= 1)
Expanded(
child: FutureBuilder<void>(
future: _future,
builder: (context, snapshot) {
return ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
controller: _scrollController,
itemCount: _wrap.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
// Add your item here
return Padding(
padding: const EdgeInsets.only(right: 30, top: 10),
child: Text(
(widget.model.amountRegister == '0' ||
widget.model.amountRegister == null)
? ''
: "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Pets: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/$count",
textAlign: TextAlign.right,
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedBodyTextSize,
),
),
);
} else {
Map<String, dynamic> item = _wrap[index - 1];
return FutureBuilder<Widget>(
future: _item(context, item),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return snapshot.data ?? Container();
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
});
},
)),
if (_hasData == true && _loading == true)
Container(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
)
].addToStart(const SizedBox(height: 0)),
);
}
}

View File

@ -25,8 +25,16 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
@override
void initState(BuildContext context) {
log('VehicleModel -> initState');
resetInstance();
initAsync();
initializeControllers(context);
WidgetsBinding.instance.addPostFrameCallback((_) async {
amountRegister = '0';
});
}
void initializeControllers(BuildContext context) {
tabBarController = TabController(
vsync: Navigator.of(context),
length: 2,
@ -40,14 +48,14 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
textFieldFocusModel = FocusNode();
textFieldControllerModel = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) async {
amountRegister = '0';
});
}
@override
void dispose() {
disposeControllers();
}
void disposeControllers() {
tabBarController.dispose();
textFieldFocusLicensePlate!.dispose();
textFieldControllerLicensePlate!.dispose();
@ -65,9 +73,9 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
await StorageHelper().get(LocalsStorageKey.vehicleAmountRegister.key);
}
bool isFormValid(BuildContext context) {
if (registerFormKey.currentState == null) return false;
return registerFormKey.currentState!.validate();
bool isFormValid(BuildContext context, GlobalKey<FormState> formKey) {
if (formKey.currentState == null) return false;
return formKey.currentState!.validate();
}
}
@ -77,9 +85,9 @@ mixin class _BaseVehiclePage {
late final VehicleModel model;
late final TabController tabBarController;
// dynamic item;
String? vehicleId;
BuildContext context = navigatorKey.currentContext!;
bool isEditing = false;
String? vehicleId;
ApiCallResponse? vehicleResponse;
String? amountRegister = '0';
@ -91,19 +99,14 @@ mixin class _BaseVehiclePage {
TextEditingController? textFieldControllerLicensePlate;
String? textControllerLicensePlateValidator(
BuildContext context, String? value) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Placa é obrigatória',
enText: 'License Plate is required',
);
}
final validationMessage = validateField(
context, value, 'Placa é obrigatória', 'License Plate is required');
if (validationMessage != null) return validationMessage;
// (ABC-1234)
final brazilianPlateRegex = RegExp(r'^[A-Z]{3}\d{4}$');
// (ABC1D23)
final mercosurPlateRegex = RegExp(r'^[A-Z]{3}\d[A-Z0-9]\d{2}$');
if (!brazilianPlateRegex.hasMatch(value) &&
if (!brazilianPlateRegex.hasMatch(value!) &&
!mercosurPlateRegex.hasMatch(value)) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Placa inválida',
@ -117,49 +120,49 @@ mixin class _BaseVehiclePage {
FocusNode? textFieldFocusColor;
TextEditingController? textFieldControllerColor;
String? textControllerColorValidator(BuildContext contexnt, String? value) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Cor é obrigatória',
enText: 'Color is required',
);
}
return null;
return validateField(
context, value, 'Cor é obrigatória', 'Color is required');
}
FocusNode? textFieldFocusModel;
TextEditingController? textFieldControllerModel;
String? textControllerModelValidator(BuildContext contexnt, String? value) {
return validateField(
context, value, 'Modelo é obrigatório', 'Model is required');
}
String? validateField(
BuildContext context, String? value, String ptText, String enText) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Modelo é obrigatório',
enText: 'Model is required',
ptText: ptText,
enText: enText,
);
}
return null;
}
void switchTab(int index) {
Future<void> switchTab(int index) async {
tabBarController.animateTo(index);
if (index == 0) handleEditingChanged(false);
if (index == 0) await handleEditingChanged(false);
safeSetState?.call();
}
void clearFields() async {
Future<void> clearFields() async {
textFieldControllerLicensePlate = TextEditingController(text: '');
textFieldControllerColor = TextEditingController(text: '');
textFieldControllerModel = TextEditingController(text: '');
}
void handleEditingChanged(bool editing) {
Future<void> handleEditingChanged(bool editing) async {
isEditing = editing;
clearFields();
await clearFields();
}
void setEditForm(dynamic item) {
Future<void> setEditForm(dynamic item) async {
if (item != null) {
vehicleId = item['vehicleId'];
log("setEditForm ");
log("setEditForm -> ${item.toString()}");
textFieldControllerLicensePlate = TextEditingController(
text: item != null ? item['licensePlate'] ?? '' : '');
@ -169,6 +172,23 @@ mixin class _BaseVehiclePage {
TextEditingController(text: item != null ? item['model'] ?? '' : '');
}
}
Future<void> handleVehicleResponse(ApiCallResponse response,
String successMessage, String errorMessage) async {
if (response.jsonBody['error'] == false) {
await DialogUtil.success(context, successMessage).then((_) async {
await switchTab(0);
});
} else {
String errorMsg;
try {
errorMsg = response.jsonBody['error_msg'];
} catch (e) {
errorMsg = errorMessage;
}
await DialogUtil.error(context, errorMsg);
}
}
}
/// [_VehicleRegisterScreenModel] is a mixin that contains the business logic of the vehicle register page.
@ -179,27 +199,17 @@ mixin _VehicleRegisterScreenModel on _BaseVehiclePage {
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
);
if (response.jsonBody['error'] == false) {
await DialogUtil.success(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo cadastrado com sucesso',
enText: 'Vehicle registered successfully',
)).then((_) async {
switchTab(0);
});
} else {
String errorMessage;
try {
errorMessage = response.jsonBody['message'];
} catch (e) {
errorMessage = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao cadastrar veículo',
enText: 'Error registering vehicle',
);
}
await DialogUtil.error(context, errorMessage);
}
await handleVehicleResponse(
response,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo cadastrado com sucesso',
enText: 'Vehicle registered successfully',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao cadastrar veículo',
enText: 'Error registering vehicle',
),
);
}
}
@ -210,36 +220,26 @@ mixin _VehicleUpdateScreenModel on _BaseVehiclePage {
licensePlate: textFieldControllerLicensePlate!.text,
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
vehicleId: vehicleId!,
vehicleId: vehicleId,
);
await handleVehicleResponse(
response,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo atualizado com sucesso',
enText: 'Vehicle updated successfully',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao atualizar veículo',
enText: 'Error updating vehicle',
),
);
if (response.jsonBody['error'] == false) {
await DialogUtil.success(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo atualizado com sucesso',
enText: 'Vehicle updated successfully',
)).then((_) async {
switchTab(0);
});
} else {
String errorMessage;
try {
errorMessage = response.jsonBody['message'];
} catch (e) {
errorMessage = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao atualizar veículo',
enText: 'Error updating vehicle',
);
}
await DialogUtil.error(context, errorMessage);
}
}
}
/// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page.
mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
Future<Map<String, Color>?> generateStatusColorMap(
dynamic uItem, int count) async {
dynamic uItem, bool isDetail) async {
final autoApproval =
await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key);
if (autoApproval.toBoolean == true) return null;
@ -247,26 +247,9 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
final theme = FlutterFlowTheme.of(context);
final localization = FFLocalizations.of(context);
byLanguage(en, pt) => localization.getVariableText(enText: en, ptText: pt);
String byLanguage(String en, String pt) =>
localization.getVariableText(enText: en, ptText: pt);
final preFixStatusMap = {
"APR_CREATE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.warning,
},
"APR_DELETE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.warning,
},
"APR_UPDATE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.warning,
},
"AGU_CHANGE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.accent2,
},
};
final vehicleStatusMap = {
"ATI": {
"text": byLanguage('Active', 'Ativo'),
@ -277,26 +260,20 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
"color": theme.accent2,
},
"APR_CREATE": {
"text": byLanguage('Creation', 'Criação'),
"text": byLanguage('Awaiting Creation', 'Aguardando Criação'),
"color": theme.success,
},
"APR_DELETE": {
"text": byLanguage('Awaiting Deletion', 'Exclusão'),
"color": theme.warning,
"text": byLanguage('Awaiting Deletion', 'Aguardando Exclusão'),
"color": theme.error,
},
"APR_UPDATE": {
"text": byLanguage('Update', 'Atualização'),
"color": theme.warning,
},
"AGU_CHANGE": {
"text": byLanguage('Correction', 'Correção'),
"text": byLanguage('Awaiting Update', 'Aguardando Atualização'),
"color": theme.accent2,
},
};
final ownerStatusMap = {
true: {
"text": byLanguage('My Vehicle', 'Meu Veículo'),
"color": theme.primaryText,
"AGU_CHANGE": {
"text": byLanguage('Awaiting Change', 'Aguardando Alteração'),
"color": theme.warning,
},
};
@ -304,27 +281,18 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
final isOwner = uItem['isOwnerVehicle'];
if (vehicleStatusMap.containsKey(status)) {
if (count > 1)
return {
// if (preFixStatusMap.containsKey(status))
// preFixStatusMap[status]!['text'] as String: preFixStatusMap[status]!['color'] as Color,
vehicleStatusMap[status]!['text'] as String:
vehicleStatusMap[status]!['color'] as Color,
if (ownerStatusMap.containsKey(isOwner) &&
(status != 'ATI' || status != 'INA'))
ownerStatusMap[isOwner]!['text'] as String:
ownerStatusMap[isOwner]!['color'] as Color
};
if (status == 'ATI' || status == 'INA')
return {
vehicleStatusMap[status]!['text'] as String:
vehicleStatusMap[status]!['color'] as Color,
};
return {
"${preFixStatusMap[status]!['text']} ${vehicleStatusMap[status]!['text']}":
vehicleStatusMap[status]!['color'] as Color
final statusMap = {
vehicleStatusMap[status]!['text'] as String:
vehicleStatusMap[status]!['color'] as Color,
};
if (!isDetail && isOwner && (status != 'ATI' && status != 'INA')) {
statusMap[byLanguage('My Vehicle', 'Meu Veículo')] = theme.primaryText;
}
return statusMap;
}
return {};
}
@ -352,8 +320,10 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
context.pop();
isEditing = true;
switchTab(1);
setEditForm(item);
await switchTab(1);
await setEditForm(item);
}
final cancelText = FFLocalizations.of(context)
@ -584,7 +554,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
required VehicleModel model,
required FreCardIcon? icon,
}) async {
final status = await generateStatusColorMap(item, 1);
final status = await generateStatusColorMap(item, true);
final buttons = await generateActionButtons(item);
final labels = await generateLabelsHashMap(item);
return DetailsComponentWidget(

View File

@ -27,76 +27,86 @@ class _VehicleRegisterScreenState extends State<VehicleRegisterScreen> {
Form _buildBody(BuildContext context) {
return Form(
key: widget.model.registerFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CustomInputUtil(
controller: widget.model.textFieldControllerLicensePlate,
validator: widget.model.textControllerLicensePlateValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusLicensePlate,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
suffixIcon: Symbols.format_color_text,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
),
CustomInputUtil(
controller: widget.model.textFieldControllerModel,
validator: widget.model.textControllerModelValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusModel,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Modelo', enText: 'Model'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Voyage, Ford',
enText: 'e.g. Voyage, Ford',
),
suffixIcon: Symbols.car_repair,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
),
CustomInputUtil(
controller: widget.model.textFieldControllerColor,
validator: widget.model.textControllerColorValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusColor,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context).getVariableText(
key: widget.model.registerFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerLicensePlate!,
validator: widget.model.textControllerLicensePlateValidator,
focusNode: widget.model.textFieldFocusLicensePlate!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
suffixIcon: Symbols.format_color_text,
),
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerModel!,
validator: widget.model.textControllerModelValidator,
focusNode: widget.model.textFieldFocusModel!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Modelo', enText: 'Model'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Voyage, Ford', enText: 'e.g. Voyage, Ford'),
suffixIcon: Symbols.car_repair,
),
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerColor!,
validator: widget.model.textControllerColorValidator,
focusNode: widget.model.textFieldFocusColor!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Preto, Amarelo, Branco',
enText: 'e.g. Black, Yellow, White',
),
suffixIcon: Symbols.palette,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
enText: 'e.g. Black, Yellow, White'),
suffixIcon: Symbols.palette,
),
Padding(
padding: const EdgeInsets.fromLTRB(70, 20, 70, 30),
child: SubmitButtonUtil(
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cadastrar', enText: 'Register'),
onPressed: widget.model.isFormValid(context, widget.model.registerFormKey)
? widget.model.registerVehicle
: null,
),
Padding(
padding: const EdgeInsets.fromLTRB(70, 20, 70, 30),
child: SubmitButtonUtil(
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cadastrar', enText: 'Register'),
onPressed: widget.model.isFormValid(context)
? widget.model.registerVehicle
: null),
),
],
));
),
],
),
);
}
Widget _buildCustomInput({
required BuildContext context,
required TextEditingController controller,
required String? Function(BuildContext, String?) validator,
required FocusNode focusNode,
required String labelText,
required String hintText,
required IconData suffixIcon,
}) {
return CustomInputUtil(
controller: controller,
validator: (value) => validator(context, value),
focusNode: focusNode,
labelText: labelText,
hintText: hintText,
suffixIcon: suffixIcon,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
);
}
Align _buildHeader(BuildContext context) {
// double limitedInputFontSize = LimitedFontSizeUtil.getInputFontSize(context);
double limitedHeaderFontSize =
LimitedFontSizeUtil.getHeaderFontSize(context);
// double limitedSubHeaderFontSize = LimitedFontSizeUtil.getSubHeaderFontSize(context);
return Align(
alignment: const AlignmentDirectional(-1.0, 0.0),

View File

@ -18,98 +18,116 @@ class _VehicleUpdateScreenState extends State<VehicleUpdateScreen> {
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment: const AlignmentDirectional(-1.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(24.0, 20, 0.0, 15),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText:
'Preencha o formulário de alteração com os dados do seu veículo',
enText: 'Fill out the update form with your vehicle data',
),
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),
),
),
),
),
Form(
key: widget.model.updateFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CustomInputUtil(
controller: widget.model.textFieldControllerLicensePlate,
validator: widget.model.textControllerLicensePlateValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusLicensePlate,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'Placa', enText: 'License Plate'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Placa', enText: 'License Plate'),
suffixIcon: Symbols.format_color_text,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomInputUtil(
controller: widget.model.textFieldControllerModel,
validator: widget.model.textControllerModelValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusModel,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Modelo', enText: 'Model'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Voyage, Ford',
enText: 'e.g. Voyage, Ford',
),
suffixIcon: Icons.car_repair,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 15),
child: CustomInputUtil(
controller: widget.model.textFieldControllerColor,
validator: widget.model.textControllerColorValidator
.asValidator(context),
focusNode: widget.model.textFieldFocusColor,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Preto, Amarelo, Branco',
enText: 'e.g. Black, Yellow, White',
),
suffixIcon: Icons.pets_outlined,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(70, 20, 70, 30),
child: SubmitButtonUtil(
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Salvar', enText: 'Save'),
onPressed: widget.model.isFormValid(context)
? widget.model.updateVehicle
: null),
),
],
)),
_buildHeader(context),
buildBody(context),
],
),
);
}
Form buildBody(BuildContext context) {
return Form(
key: widget.model.updateFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerLicensePlate!,
validator: widget.model.textControllerLicensePlateValidator,
focusNode: widget.model.textFieldFocusLicensePlate!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
hintText: FFLocalizations.of(context)
.getVariableText(ptText: 'Placa', enText: 'License Plate'),
suffixIcon: Symbols.format_color_text,
),
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerModel!,
validator: widget.model.textControllerModelValidator,
focusNode: widget.model.textFieldFocusModel!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Modelo', enText: 'Model'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Voyage, Ford', enText: 'e.g. Voyage, Ford'),
suffixIcon: Symbols.car_repair,
),
_buildCustomInput(
context: context,
controller: widget.model.textFieldControllerColor!,
validator: widget.model.textControllerColorValidator,
focusNode: widget.model.textFieldFocusColor!,
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Cor', enText: 'Color'),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Ex: Preto, Amarelo, Branco',
enText: 'e.g. Black, Yellow, White'),
suffixIcon: Symbols.palette,
),
_buildSubmitButton(context),
],
),
);
}
Widget _buildHeader(BuildContext context) {
return Align(
alignment: const AlignmentDirectional(-1.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(24.0, 20, 0.0, 15),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText:
'Preencha o formulário de alteração com os dados do seu veículo',
enText: 'Fill out the update form with your vehicle data',
),
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),
),
),
),
);
}
Widget _buildCustomInput({
required BuildContext context,
required TextEditingController controller,
required String? Function(BuildContext, String?) validator,
required FocusNode focusNode,
required String labelText,
required String hintText,
required IconData suffixIcon,
}) {
return CustomInputUtil(
controller: controller,
validator: (value) => validator(context, value),
focusNode: focusNode,
labelText: labelText,
hintText: hintText,
suffixIcon: suffixIcon,
haveMaxLength: true,
onChanged: (value) => setState(() {}),
maxLength: 80,
);
}
Widget _buildSubmitButton(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(70, 20, 70, 30),
child: SubmitButtonUtil(
labelText: FFLocalizations.of(context)
.getVariableText(ptText: 'Salvar', enText: 'Save'),
onPressed: widget.model.isFormValid(context, widget.model.updateFormKey)
? () => widget.model.updateVehicle()
: null,
),
);
}
}

View File

@ -1,4 +1,5 @@
import 'dart:collection';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ description: A new Flutter project.
publish_to: "none"
version: 1.3.3+22
version: 1.3.5+24
environment:
sdk: ">=3.0.0 <4.0.0"