diff --git a/analysis_options.yaml b/analysis_options.yaml index 78e77505..4934b3e6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -28,8 +28,10 @@ linter: # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options - analyzer: + errors: + curly_braces_in_flow_control_structures: ignore + use_build_context_synchronously: ignore exclude: - lib/custom_code/** - lib/flutter_flow/custom_functions.dart diff --git a/lib/backend/api_requests/api_calls.dart b/lib/backend/api_requests/api_calls.dart index 1de34639..d7303aa6 100644 --- a/lib/backend/api_requests/api_calls.dart +++ b/lib/backend/api_requests/api_calls.dart @@ -6,7 +6,6 @@ import 'package:flutter/foundation.dart'; import 'package:hub/backend/notifications/firebase_messaging_service.dart'; import 'package:hub/shared/helpers/base_storage.dart'; import 'package:hub/shared/helpers/storage_helper.dart'; -import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/validator_util.dart'; @@ -56,6 +55,103 @@ class PhpGroup { static GetPets getPets = GetPets(); static GetPetPhoto getPetPhoto = GetPetPhoto(); static UnregisterDevice unregisterDevice = UnregisterDevice(); + static GetVehiclesByProperty getVehiclesByProperty = GetVehiclesByProperty(); + static GetResidentsByProperty getResidentsByProperty = GetResidentsByProperty(); + static GetOpenedVisits getOpenedVisits = GetOpenedVisits(); +} + +class GetOpenedVisits { + Future call(final String page) async { + final String baseUrl = PhpGroup.getBaseUrl(); + final String devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; + final String userUUID = (await StorageHelper().get(SQLiteStorageKey.userUUID.value, Storage.SQLiteStorage)) ?? ''; + final String cliID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; + const String atividade = 'getOpenedVisits'; + const String pageSize = '10'; + return ApiManager.instance.makeApiCall( + callName: 'getOpenedVisits', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'page': page, + 'pageSize': pageSize, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + isStreamingApi: false, + alwaysAllowBody: false, + ); + } +} + +class GetResidentsByProperty { + Future call(final String page) async { + final String baseUrl = PhpGroup.getBaseUrl(); + final String devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; + final String userUUID = (await StorageHelper().get(SQLiteStorageKey.userUUID.value, Storage.SQLiteStorage)) ?? ''; + final String cliID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; + const String atividade = 'getResidentsByProperty'; + const String pageSize = '10'; + return ApiManager.instance.makeApiCall( + callName: 'getResidentsByProperty', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'page': page, + 'pageSize': pageSize, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } +} + +class GetVehiclesByProperty { + Future call(final String page) async { + final String baseUrl = PhpGroup.getBaseUrl(); + final String devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; + final String userUUID = (await StorageHelper().get(SQLiteStorageKey.userUUID.value, Storage.SQLiteStorage)) ?? ''; + final String cliID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; + const String atividade = 'getVehiclesByProperty'; + const String pageSize = '10'; + return ApiManager.instance.makeApiCall( + callName: 'getVehiclesByProperty', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'page': page, + 'pageSize': pageSize, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + alwaysAllowBody: false, + ); + } static GetLicense getLicense = GetLicense(); static TestCall testCall = TestCall(); } @@ -686,7 +782,7 @@ class LoginCall { late final String token; try { token = await FirebaseMessagingService.getToken(); - if (token == null || token.isEmpty) throw Exception('Token is empty'); + if (token == 'null' || token.isEmpty) throw Exception('Token is empty'); } catch (e, s) { token = ''; log('Error getting token', error: e, stackTrace: s); diff --git a/lib/components/atomic_components/menu_button_item/menu_button_item_widget.dart b/lib/components/atomic_components/menu_button_item/menu_button_item_widget.dart index 453e89be..ced0373e 100644 --- a/lib/components/atomic_components/menu_button_item/menu_button_item_widget.dart +++ b/lib/components/atomic_components/menu_button_item/menu_button_item_widget.dart @@ -3,15 +3,13 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; -import '../../../shared/extensions/dialog_extensions.dart'; -import '../../../shared/services/localization/localization_service.dart'; - class MenuButtonWidget extends MenuEntry { const MenuButtonWidget({ super.key, required this.action, required this.title, required this.icon, + required super.safeSetState, }) : super(action: action, title: title, icon: icon); @override diff --git a/lib/components/atomic_components/menu_card_item/menu_card_item.dart b/lib/components/atomic_components/menu_card_item/menu_card_item.dart index 77d351d9..5696f83a 100644 --- a/lib/components/atomic_components/menu_card_item/menu_card_item.dart +++ b/lib/components/atomic_components/menu_card_item/menu_card_item.dart @@ -3,15 +3,13 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; -import '../../../shared/extensions/dialog_extensions.dart'; -import '../../../shared/services/localization/localization_service.dart'; - class MenuCardItem extends MenuEntry { const MenuCardItem({ super.key, required this.action, required this.title, required this.icon, + required super.safeSetState, }) : super(action: action, title: title, icon: icon); @override diff --git a/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart b/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart index 7b712455..2977f7cb 100644 --- a/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart +++ b/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; -import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/upload_data.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; diff --git a/lib/components/molecular_components/menu_item/menu_item.dart b/lib/components/molecular_components/menu_item/menu_item.dart index 8030ad6d..fe97affd 100644 --- a/lib/components/molecular_components/menu_item/menu_item.dart +++ b/lib/components/molecular_components/menu_item/menu_item.dart @@ -1,14 +1,38 @@ import 'package:flutter/material.dart'; +enum MenuOption { + CompleteSchedule, + DeliverySchedule, + WorkersOnTheProperty, + FastPassSchedule, + QRCodeAccessInProperty, + AccessOnTheProperty, + LiberationsOnTheProperty, + MessagesOnTheProperty, + ReservationsOnTheLocal, + PackagesOnTheProperty, + VehiclesOnTheProperty, + PetsOnTheProperty, + PetsRegister, + VisitorsRegister, + VisitsOnTheProperty, + ResidentsOnTheProperty, + SettingsOnTheApp, + AboutProperty, + LogoutOnTheApp, +} + abstract class MenuEntry extends StatefulWidget { const MenuEntry({ super.key, required this.action, required this.title, required this.icon, + required this.safeSetState, }); final Function() action; final String title; final IconData icon; + final VoidCallback safeSetState; } diff --git a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart index 13b497f0..30214c33 100644 --- a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart +++ b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart @@ -27,14 +27,14 @@ class _LocalProfileComponentWidgetState extends State LocalProfileComponentModel()); - _model.setOnUpdate(onUpdate: () => setState(() {})); + _model.setOnUpdate(onUpdate: () => safeSetState(() {})); _model.setStateCallback = () => safeSetState(() {}); WidgetsBinding.instance.addPostFrameCallback((_) async { @@ -54,11 +54,10 @@ class _LocalProfileComponentWidgetState extends State onUpdate()'); - safeSetState(() { - _model.getData(); - }); + await _model.getData(); + safeSetState(() {}); } @override diff --git a/lib/components/organism_components/menu_component/menu_component_model.dart b/lib/components/organism_components/menu_component/menu_component_model.dart index 4c58370d..d0854a97 100644 --- a/lib/components/organism_components/menu_component/menu_component_model.dart +++ b/lib/components/organism_components/menu_component/menu_component_model.dart @@ -1,21 +1,37 @@ import 'package:flutter/material.dart'; +import 'package:hub/backend/schema/enums/enums.dart'; +import 'package:hub/components/atomic_components/menu_button_item/menu_button_item_widget.dart'; +import 'package:hub/components/atomic_components/menu_card_item/menu_card_item.dart'; +import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; +import 'package:hub/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart'; +import 'package:hub/components/organism_components/menu_component/menu_component_widget.dart'; +import 'package:hub/components/organism_components/menu_list_view_component/menu_list_view_component_model.dart'; import 'package:hub/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_model.dart'; +import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/shared/extensions/dialog_extensions.dart'; import 'package:hub/shared/helpers/base_storage.dart'; import 'package:hub/shared/helpers/storage_helper.dart'; import 'package:hub/shared/services/authentication/authentication_service.dart'; +import 'package:material_symbols_icons/symbols.dart'; -import '/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart'; import '/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart'; -import '/flutter_flow/flutter_flow_util.dart'; import 'menu_component_widget.dart' show MenuComponentWidget; class MenuComponentModel extends FlutterFlowModel { + final MenuView style; + final MenuItem item; + final bool expandable; + final List menuOptions; + + MenuComponentModel({required this.style, required this.item, required this.expandable, required this.menuOptions}); + bool isGrid = false; late MenuListViewComponentModel menuListViewComponentModel; late MenuStaggeredViewComponentModel menuStaggeredViewComponentModel; + late VoidCallback safeSetState; + late List menuEntries; @override void initState(BuildContext context) { @@ -29,13 +45,160 @@ class MenuComponentModel extends FlutterFlowModel { menuStaggeredViewComponentModel.dispose(); } - Future changeMenuStyle(BuildContext context) async { - isGrid = !isGrid; + List generateMenuEntries(BuildContext context, MenuItem item, List options) { + List entries = []; + MenuEntry? addMenuEntry(IconData icon, String enText, String ptText, Function() action) { + entries.add( + item == MenuItem.button + ? MenuButtonWidget( + icon: icon, + action: action, + title: FFLocalizations.of(context).getVariableText(enText: enText, ptText: ptText), + safeSetState: safeSetState) + : item == MenuItem.card + ? MenuCardItem( + icon: icon, + action: action, + title: FFLocalizations.of(context).getVariableText(enText: enText, ptText: ptText), + safeSetState: safeSetState) + : item == MenuItem.tile + ? MenuCardItem( + icon: icon, + action: action, + title: FFLocalizations.of(context).getVariableText(enText: enText, ptText: ptText), + safeSetState: safeSetState) + : null, + ); + return null; + } + + if (options.contains(MenuOption.WorkersOnTheProperty)) + addMenuEntry(Icons.engineering_outlined, 'Schedule Providers', 'Agendar Prestadores', () async { + if (await StorageHelper().get(SQLiteStorageKey.provisional.value, Storage.SQLiteStorage) == 'true') + await open(context, '/provisionalSchedule'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.DeliverySchedule)) + addMenuEntry(Icons.sports_motorsports_outlined, 'Schedule Deliveries', 'Agendar Entregas', () async { + if (await StorageHelper().get(SQLiteStorageKey.provisional.value, Storage.SQLiteStorage) == 'true') + await open(context, '/deliverySchedule'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.FastPassSchedule)) + addMenuEntry(Icons.attach_email_outlined, 'Invite Visitor', 'Convidar Visitante', () async { + if (await StorageHelper().get(SQLiteStorageKey.whatsapp.value, Storage.SQLiteStorage) == 'true') + await open(context, '/fastPassPage'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.CompleteSchedule)) + addMenuEntry(Icons.event, 'Complete Schedule', 'Agenda Completa', () async { + await open(context, '/scheduleCompleteVisitPage'); + safeSetState; + }); + if (options.contains(MenuOption.PackagesOnTheProperty)) + addMenuEntry(Icons.inventory_2_outlined, 'Orders', 'Encomendas', () async { + if (await StorageHelper().get(SQLiteStorageKey.whatsapp.value, Storage.SQLiteStorage) == 'true') + await open(context, '/packageOrder'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.ReservationsOnTheLocal)) + addMenuEntry(Icons.event_available, 'Reservations', 'Reservas', () async { + if (await StorageHelper().get(SQLiteStorageKey.whatsapp.value, Storage.SQLiteStorage) == 'true') + await open(context, '/reservation'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.VisitorsRegister)) + addMenuEntry(Icons.person_add_alt_1_outlined, 'Register Visitor', 'Cadastrar Visitante', () async { + await open(context, '/registerVisitorPage'); + safeSetState; + }); + if (options.contains(MenuOption.QRCodeAccessInProperty)) + addMenuEntry(Icons.qr_code, 'QRCode Access', 'QRCode de Acesso', () async { + await open(context, '/qrCodePage'); + safeSetState; + }); + if (options.contains(MenuOption.PetsOnTheProperty)) + addMenuEntry(Icons.pets, 'Pets', 'Pets', () async { + if (await StorageHelper().get(SQLiteStorageKey.pets.value, Storage.SQLiteStorage) == 'true') + await open(context, '/petsOnThePropertyPage'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.PetsRegister)) + addMenuEntry(Icons.pets, 'Pets Register', 'Cadastrar Pet', () async { + if (await StorageHelper().get(SQLiteStorageKey.pets.value, Storage.SQLiteStorage) == 'true') + await open(context, '/petsPage'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.AccessOnTheProperty)) + addMenuEntry(Icons.transfer_within_a_station_outlined, 'Access History', 'Consultar Acessos', () async { + await open(context, '/acessHistoryPage'); + safeSetState; + }); + if (options.contains(MenuOption.ResidentsOnTheProperty)) + addMenuEntry(Icons.groups, 'Residents', 'Moradores', () async { + await open(context, '/peopleOnThePropertyPage'); + safeSetState; + }); + if (options.contains(MenuOption.LiberationsOnTheProperty)) + addMenuEntry(Icons.how_to_reg_outlined, 'Liberations History', 'Consultar Liberações', () async { + await open(context, '/liberationHistory'); + safeSetState; + }); + if (options.contains(MenuOption.MessagesOnTheProperty)) + addMenuEntry(Icons.chat_outlined, 'Message History', 'Consultar Mensagens', () async { + await open(context, '/messageHistoryPage'); + safeSetState; + }); + if (options.contains(MenuOption.VehiclesOnTheProperty)) + addMenuEntry(Symbols.directions_car, 'Vehicles', 'Veículos', () async { + await open(context, '/vehiclesOnThePropertyPage'); + safeSetState; + }); + if (options.contains(MenuOption.VisitsOnTheProperty)) + addMenuEntry(Symbols.perm_contact_calendar, 'Opened Visits', 'Visitas em Aberto', () async { + await open(context, '/visitsOnThePropertyPage'); + safeSetState; + }); + + if (options.contains(MenuOption.AboutProperty)) + addMenuEntry(Icons.home, 'About Property', 'Sobre a Propriedade', () async { + if (await StorageHelper().get(SQLiteStorageKey.whatsapp.value, Storage.SQLiteStorage) == 'true') + await open(context, '/aboutProperty'); + else + DialogUnavailable.unavailableFeature(context); + safeSetState; + }); + if (options.contains(MenuOption.SettingsOnTheApp)) + addMenuEntry(Icons.settings, 'System Settings', 'Opções do Sistema', () async { + await open(context, '/preferencesSettings'); + safeSetState; + }); + if (options.contains(MenuOption.LogoutOnTheApp)) + addMenuEntry(Icons.logout, 'Logout', 'Sair', () async { + await out(context); + safeSetState; + }); + + return entries; } - Future openQRCodeScanner(BuildContext context) async { + Future open(BuildContext context, String link) async { context.push( - '/qrCodePage', + link, extra: { kTransitionInfoKey: const TransitionInfo( hasTransition: false, @@ -46,17 +209,16 @@ class MenuComponentModel extends FlutterFlowModel { ); } - Future openCompleteSchedule(BuildContext context) async { - context.push( - '/scheduleCompleteVisitPage', - extra: { - kTransitionInfoKey: const TransitionInfo( - hasTransition: false, - transitionType: PageTransitionType.scale, - alignment: Alignment.bottomCenter, - ), - }, + Future out(BuildContext context) async { + final String title = FFLocalizations.of(context).getVariableText( + ptText: 'Sair', + enText: 'Logout', ); + final String content = FFLocalizations.of(context).getVariableText( + ptText: 'Tem certeza que deseja sair?', + enText: 'Are you sure you want to logout?', + ); + showAlertDialog(context, title, content, () async => await AuthenticationService.signOut(context)); } Future openDeliverySchedule(BuildContext context) async { diff --git a/lib/components/organism_components/menu_component/menu_component_widget.dart b/lib/components/organism_components/menu_component/menu_component_widget.dart index f9b12e64..795982cd 100644 --- a/lib/components/organism_components/menu_component/menu_component_widget.dart +++ b/lib/components/organism_components/menu_component/menu_component_widget.dart @@ -1,8 +1,5 @@ import 'package:flutter/material.dart'; import 'package:hub/backend/schema/enums/enums.dart'; -import 'package:hub/components/atomic_components/menu_button_item/menu_button_item_widget.dart'; -import 'package:hub/components/atomic_components/menu_card_item/menu_card_item.dart'; -import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; import '/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart'; import '/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart'; @@ -12,612 +9,68 @@ import 'menu_component_model.dart'; export 'menu_component_model.dart'; class MenuComponentWidget extends StatefulWidget { - const MenuComponentWidget({ - Key? key, - required this.style, - required this.item, - required this.expandable, - }); - final MenuView style; - final MenuItem item; - final bool expandable; + final MenuComponentModel model; + const MenuComponentWidget({super.key, required this.model}); + @override State createState() => _MenuComponentWidgetState(); } class _MenuComponentWidgetState extends State { - late MenuComponentModel _model; - @override void setState(VoidCallback callback) { super.setState(callback); - _model.onUpdate(); + widget.model.onUpdate(); } @override void initState() { super.initState(); - _model = createModel(context, () => MenuComponentModel()); + widget.model.safeSetState = () => safeSetState(() {}); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + widget.model.menuEntries = widget.model.generateMenuEntries(context, widget.model.item, widget.model.menuOptions); } @override void dispose() { - _model.maybeDispose(); - + widget.model.maybeDispose(); super.dispose(); } - // MenuButtonWidget(icon: FFIcons.kvector2, action: () async {setState(() {});}, title: FFLocalizations.of(context).getVariableText(enText:'Link\nCondominum' , ptText:'' ,),), - // MenuButtonWidget(icon: FFIcons.kpets, action: () async {setState(() {});}, title: FFLocalizations.of(context).getVariableText(enText:'Register\Pet' , ptText:'' ,),), - @override Widget build(BuildContext context) { - final options = () { - if (widget.item == MenuItem.button) { - if (_model.isGrid == true) - return [ - MenuButtonWidget( - icon: FFIcons.kvector1, - action: () async { - await _model.showSchedules(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule\nVisit', - ptText: 'Agendar\nVisita', - ), - ), - MenuButtonWidget( - icon: FFIcons.khome, - action: () async { - await _model.openVisitorsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Register\nVisitor', - ptText: 'Cadastro\nde Visitante', - ), - ), - MenuButtonWidget( - icon: Icons.qr_code, - action: () async { - await _model.openQRCodeScanner(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'QRCode\nAccess', - ptText: 'QRCode\nde Acesso', - ), - ), - MenuButtonWidget( - icon: Icons.pets, - action: () async { - await _model.openPetsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Pets\nRegister', - ptText: 'Cadastro\nde Pet', - ), - ), - MenuButtonWidget( - icon: Icons.people, - action: () async { - await _model.openPoepleOnTheProperty(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'People on\nthe Property', - ptText: 'Pessoas na\nPropriedade', - ), - ), - MenuButtonWidget( - icon: Icons.history_sharp, - action: () async { - await _model.showHistories(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Consult\nHistories', - ptText: 'Consultar\nHistóricos', - ), - ), - MenuButtonWidget( - icon: Icons.settings, - action: () async { - await _model.openPreferencesSettings(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Preferences\nSettings', - ptText: 'Opções\ndo Sistema', - ), - ), - ]; - else - return [ - MenuButtonWidget( - icon: Icons.engineering_outlined, - action: () async { - await _model.openProvisionalSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule\nProviders', - ptText: 'Agendar\nPrestadores', - ), - ), - MenuButtonWidget( - icon: Icons.sports_motorsports_outlined, - action: () async { - await _model.openDeliverySchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule\nDeliveries', - ptText: 'Agendar\nEntregas', - ), - ), - MenuButtonWidget( - icon: Icons.attach_email_outlined, - action: () async { - await _model.openFastPassSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Convidar\nVisitante', - enText: 'Invite\nVisitor', - ), - ), - MenuButtonWidget( - icon: Icons.event, - action: () async { - await _model.openCompleteSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Complete\nSchedule', - ptText: 'Agenda\nCompleta', - ), - ), - MenuButtonWidget( - icon: Icons.inventory_2_outlined, - action: () async { - await _model.openMyOrders(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Minhas\nEncomendas', - enText: 'My\nOrders', - ), - ), - MenuButtonWidget( - icon: Icons.event_available, - action: () async { - await _model.openReservations(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Reservas', - enText: 'Reservations', - ), - ), - MenuButtonWidget( - icon: Icons.person_add_alt_1_outlined, - action: () async { - await _model.openVisitorsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Register\nVisitor', - ptText: 'Cadastrar\nVisitante', - ), - ), - MenuButtonWidget( - icon: Icons.qr_code, - action: () async { - await _model.openQRCodeScanner(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'QRCode\nAccess', - ptText: 'QRCode\nde Acesso', - ), - ), - MenuButtonWidget( - icon: Icons.pets, - action: () async { - await _model.openPetsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Pets\nRegister', - ptText: 'Cadastrar\nPet', - ), - ), - MenuButtonWidget( - icon: Icons.transfer_within_a_station_outlined, - action: () async { - await _model.openAccessHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Access\nHistory', - ptText: 'Consultar\nAcessos', - ), - ), - MenuButtonWidget( - icon: Icons.how_to_reg_outlined, - action: () async { - await _model.openLiberationsHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Liberations\nHistory', - ptText: 'Consultar\nLiberações', - ), - ), - MenuButtonWidget( - icon: Icons.chat_outlined, - action: () async { - await _model.openMessagesHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Message\nHistory', - ptText: 'Consultar\nMensagens', - ), - ), - MenuButtonWidget( - icon: Icons.groups, - action: () async { - await _model.openPoepleOnTheProperty(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'People on\nthe Property', - ptText: 'Pessoas na\nPropriedade', - ), - ), - MenuButtonWidget( - icon: Icons.settings, - action: () async { - await _model.openPreferencesSettings(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'System\n Settings', - ptText: 'Opções\ndo Sistema', - ), - ), - ]; - } - if (widget.item == MenuItem.card) { - return [ - MenuCardItem( - icon: FFIcons.kvector1, - action: () async { - await _model.showSchedules(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule\nVisit', - ptText: 'Agendar\nVisita', - ), - ), - MenuCardItem( - icon: FFIcons.khome, - action: () async { - await _model.openVisitorsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Register\nVisitor', - ptText: 'Cadastro\nde Visitante', - ), - ), - MenuCardItem( - icon: Icons.qr_code, - action: () async { - await _model.openQRCodeScanner(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'QRCode\nAccess', - ptText: 'QRCode\nde Acesso', - ), - ), - MenuCardItem( - icon: Icons.people, - action: () async { - await _model.openPoepleOnTheProperty(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'People on\nthe Property', - ptText: 'Pessoas\nna Propriedade', - ), - ), - MenuCardItem( - icon: Icons.history_sharp, - action: () async { - await _model.showHistories(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Consult\nHistories', - ptText: 'Consultar\nHistoricos', - ), - ), - MenuCardItem( - icon: Icons.inventory_2_rounded, - action: () async { - await _model.openMyOrders(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Orders', - ptText: 'Encomendas', - ), - ), - MenuButtonWidget( - icon: Icons.pets, - action: () async { - await _model.openPetsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Pets\nRegister', - ptText: 'Cadastrar\nPet', - ), - ), - MenuCardItem( - icon: Icons.event_available, - action: () async { - await _model.openReservations(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Reservations', - ptText: 'Reservas', - ), - ), - MenuCardItem( - icon: Icons.settings, - action: () async { - await _model.openPreferencesSettings(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Preferences\nSettings', - ptText: 'Preferências\nde Configuração', - ), - ), - ]; - } - // if (MenuItem.tile) - return [ - MenuCardItem( - icon: Icons.engineering_outlined, - action: () async { - await _model.openProvisionalSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule Providers', - ptText: 'Agendar Prestadores', - ), - ), - MenuCardItem( - icon: Icons.sports_motorsports_outlined, - action: () async { - await _model.openDeliverySchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Schedule Deliveries', - ptText: 'Agendar Entregas', - ), - ), - MenuCardItem( - icon: Icons.attach_email_outlined, - action: () async { - await _model.openFastPassSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Convidar Visitante', - enText: 'Invite Visitor', - ), - ), - MenuCardItem( - icon: Icons.event, - action: () async { - await _model.openCompleteSchedule(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Complete Schedule', - ptText: 'Agenda Completa', - ), - ), - MenuCardItem( - icon: Icons.inventory_2_outlined, - action: () async { - await _model.openMyOrders(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Minhas Encomendas', - enText: 'My Orders', - ), - ), - MenuCardItem( - icon: Icons.event_available, - action: () async { - await _model.openReservations(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - ptText: 'Reservas', - enText: 'Reservations', - ), - ), - MenuCardItem( - icon: Icons.person_add_alt_1_outlined, - action: () async { - await _model.openVisitorsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Register Visitor', - ptText: 'Cadastrar Visitante', - ), - ), - MenuCardItem( - icon: Icons.qr_code, - action: () async { - await _model.openQRCodeScanner(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'QRCode Access', - ptText: 'QRCode de Acesso', - ), - ), - MenuCardItem( - icon: Icons.pets, - action: () async { - await _model.openPetsRegister(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Pets Register', - ptText: 'Cadastro de Pet', - ), - ), - MenuCardItem( - icon: Icons.transfer_within_a_station_outlined, - action: () async { - await _model.openAccessHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Access History', - ptText: 'Consultar Acessos', - ), - ), - MenuCardItem( - icon: Icons.how_to_reg_outlined, - action: () async { - await _model.openLiberationsHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Liberations History', - ptText: 'Consultar Liberações', - ), - ), - MenuCardItem( - icon: Icons.chat_outlined, - action: () async { - await _model.openMessagesHistory(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Message History', - ptText: 'Consultar Mensagens', - ), - ), - MenuCardItem( - icon: Icons.groups, - action: () async { - await _model.openPoepleOnTheProperty(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'People on the Property', - ptText: 'Pessoas na Propriedade', - ), - ), - MenuCardItem( - icon: Icons.settings, - action: () async { - await _model.openPreferencesSettings(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'System Settings', - ptText: 'Opções do Sistema', - ), - ), - MenuCardItem( - icon: Icons.logout, - action: () async { - await _model.Logout(context); - setState(() {}); - }, - title: FFLocalizations.of(context).getVariableText( - enText: 'Logout Account', - ptText: 'Sair da Conta', - ), - ), - ]; - }(); - return Builder( builder: (context) { - if (widget.style == MenuView.list_grid && widget.expandable == true && widget.item == MenuItem.button) { - if (_model.isGrid == true) { - return wrapWithModel( - model: _model.menuStaggeredViewComponentModel, - updateCallback: () => setState(() {}), - updateOnChange: true, - child: MenuStaggeredViewComponentWidget( - options: options, - expandable: widget.expandable, - item: widget.item, - changeMenuStyle: () async { - await _model.changeMenuStyle(context); - setState(() {}); - }, - isGrid: _model.isGrid, - ), - ); - } else { - return wrapWithModel( - model: _model.menuStaggeredViewComponentModel, - updateCallback: () => setState(() {}), - updateOnChange: true, - child: MenuStaggeredViewComponentWidget( - options: options, - expandable: widget.expandable, - item: widget.item, - changeMenuStyle: () async { - await _model.changeMenuStyle(context); - setState(() {}); - }, - isGrid: _model.isGrid, - ), - ); - } - } - if (widget.style == MenuView.list && widget.expandable == false && widget.item == MenuItem.tile) { + if (widget.model.style == MenuView.list_grid) return wrapWithModel( - model: _model.menuListViewComponentModel, + model: widget.model.menuStaggeredViewComponentModel, + updateCallback: () => setState(() {}), + updateOnChange: true, + child: MenuStaggeredViewComponentWidget( + options: widget.model.menuEntries, + expandable: widget.model.expandable, + item: widget.model.item, + changeMenuStyle: () async {}, + isGrid: widget.model.isGrid, + ), + ); + if (widget.model.style == MenuView.list) + return wrapWithModel( + model: widget.model.menuListViewComponentModel, updateCallback: () => setState(() {}), updateOnChange: true, child: MenuListViewComponentWidget( - options: options, - expandable: widget.expandable, - item: widget.item, - changeMenuStyle: () async { - await _model.changeMenuStyle(context); - setState(() {}); - }, + options: widget.model.menuEntries, + expandable: widget.model.expandable, + item: widget.model.item, + changeMenuStyle: () async {}, ), ); - } + return const SizedBox(); }, ); diff --git a/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart b/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart index 5a3b74df..88f6153e 100644 --- a/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart +++ b/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart @@ -23,7 +23,7 @@ class MenuListViewComponentWidget extends StatefulWidget { final bool expandable; final MenuItem item; - final List options; + final List options; final Future Function()? changeMenuStyle; @override diff --git a/lib/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart b/lib/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart index f605dc82..64161e26 100644 --- a/lib/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart +++ b/lib/components/organism_components/menu_staggered_view_component/menu_staggered_view_component_widget.dart @@ -19,7 +19,7 @@ class MenuStaggeredViewComponentWidget extends StatefulWidget { final MenuItem item; final bool isGrid; - final List options; + final List options; final Future Function()? changeMenuStyle; @override diff --git a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart index 26b1d53d..4814763e 100644 --- a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart +++ b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart @@ -4,6 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; +import 'package:material_symbols_icons/symbols.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -175,14 +176,14 @@ class _CardItemTemplateComponentWidgetState extends State?> statusHashMap; final String? imagePath; final Future Function()? onTapCardItemAction; - final List buttons; + final List? buttons; @override State createState() => _DetailsComponentWidgetState(); @@ -75,21 +75,22 @@ class _DetailsComponentWidgetState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ SizedBox(height: MediaQuery.of(context).size.height * 0.02), - Container( - width: MediaQuery.of(context).size.width * 0.3, - height: MediaQuery.of(context).size.width * 0.3, - clipBehavior: Clip.antiAlias, - decoration: const BoxDecoration( - shape: BoxShape.circle, + if (widget.imagePath != null && widget.imagePath != '') + Container( + width: MediaQuery.of(context).size.width * 0.3, + height: MediaQuery.of(context).size.width * 0.3, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: CachedNetworkImage( + fadeInDuration: const Duration(milliseconds: 100), + fadeOutDuration: const Duration(milliseconds: 100), + imageUrl: widget.imagePath!, + fit: BoxFit.cover, + useOldImageOnUrlChange: true, + ), ), - child: CachedNetworkImage( - fadeInDuration: const Duration(milliseconds: 100), - fadeOutDuration: const Duration(milliseconds: 100), - imageUrl: widget.imagePath ?? '', - fit: BoxFit.cover, - useOldImageOnUrlChange: true, - ), - ), SizedBox(height: MediaQuery.of(context).size.height * 0.03), Row( children: statusLinkedHashMap.expand((linkedHashMap) { @@ -100,8 +101,6 @@ class _DetailsComponentWidgetState extends State { horizontal: MediaQuery.of(context).size.width * 0.05, ), child: TextFormField( - // controller: _model.textControllerStatus, - // focusNode: _model.textFieldFocusNodeStatus, autofocus: false, canRequestFocus: false, readOnly: true, @@ -153,7 +152,7 @@ class _DetailsComponentWidgetState extends State { ), fontSize: limitedBodyFontSize, ), - textAlign: TextAlign.start, + textAlign: TextAlign.center, maxLines: null, keyboardType: TextInputType.name, validator: _model.textController1Validator.asValidator(context), @@ -239,14 +238,14 @@ class _DetailsComponentWidgetState extends State { }, ), SizedBox(height: MediaQuery.of(context).size.height * 0.02), - if (widget.buttons.isNotEmpty) // Adicione este SizedBox com a altura desejada + if (widget.buttons!.isNotEmpty || widget.buttons != null) OverflowBar( overflowAlignment: OverflowBarAlignment.center, alignment: MainAxisAlignment.center, overflowSpacing: 2, spacing: 2, // mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: widget.buttons, + children: widget.buttons!, ), SizedBox(height: MediaQuery.of(context).size.height * 0.02), ], diff --git a/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart b/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart index d098ecfb..df0b3610 100644 --- a/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart +++ b/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart @@ -95,7 +95,9 @@ class _ScheduleProvisionalVisitPageWidgetState extends State EasyDebounce.debounce('model.personNameTextController', - const Duration(milliseconds: 500), () => setState(() {})), + onChanged: (_) => EasyDebounce.debounce( + 'model.personNameTextController', + const Duration(milliseconds: 500), + () => setState(() {}), + ), autofocus: false, textInputAction: TextInputAction.next, obscureText: false, decoration: InputDecoration( isDense: true, - labelText: FFLocalizations.of(context).getText('wehvxbz4'), + labelText: FFLocalizations.of(context).getText( + 'wehvxbz4' /* Nome / Apelido do Visitante */, + ), labelStyle: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, color: FlutterFlowTheme.of(context).primaryText, @@ -299,8 +308,11 @@ class _ScheduleProvisionalVisitPageWidgetState extends State EasyDebounce.debounce('model.dateTimeTextController', - const Duration(milliseconds: 500), () => setState(() {})), + onChanged: (_) => EasyDebounce.debounce( + 'model.dateTimeTextController', + const Duration(milliseconds: 500), + () => setState(() {}), + ), readOnly: true, autofocus: false, obscureText: false, @@ -460,6 +472,7 @@ class _ScheduleProvisionalVisitPageWidgetState extends State appStateNotifier.showSplashImage - // ? Builder( - // builder: (context) => Container( - // color: FlutterFlowTheme.of(context).primary, - // child: Image.asset( - // 'assets/images/logo.svg', - // fit: BoxFit.cover, - // ), - // ), - // ) + // ? Builder( builder: (context) => Container(color: FlutterFlowTheme.of(context).primary, child: Image.asset( 'assets/images/logo.svg', fit: BoxFit.cover))) // : const PeopleOnThePropertyPageWidget(), routes: [ - // FFRoute( - // name: '_initialize', - // path: '/', - // builder: (context, _) => appStateNotifier.showSplashImage - // ? Builder( - // builder: (context) => Container( - // color: FlutterFlowTheme.of(context).primary, - // child: Image.asset( - // 'assets/images/favicon.png', - // fit: BoxFit.cover, - // ), - // ), - // ) + // FFRoute(name: '_initialize', path: '/',builder: (context, _) => appStateNotifier.showSplashImage + // ? Builder(builder: (context) => Container(color: FlutterFlowTheme.of(context).primary, child: Image.asset('assets/images/favicon.png', fit: BoxFit.cover))) // : const OnBoardingPageWidget(), // ), FFRoute( @@ -108,130 +100,78 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { FFRoute( name: 'forgotPassword', path: '/forgotPassword', - builder: (context, params) { - late final String email = params.getParam('email', ParamType.String); - late final String token = params.getParam('token', ParamType.String); - - return ForgotPasswordScreen( + builder: (context, params) => ForgotPasswordScreen( key: UniqueKey(), - email: email, - token: token, - ); - }), + email: params.getParam('email', ParamType.String), + token: params.getParam('token', ParamType.String))), + FFRoute(name: 'homePage', path: '/homePage', builder: (context, params) => HomePageWidget(key: UniqueKey())), FFRoute( - name: 'homePage', - path: '/homePage', - builder: (context, params) => HomePageWidget(key: UniqueKey()), - ), + name: 'petsOnThePropertyPage', + path: '/petsOnThePropertyPage', + builder: (context, params) => Scaffold(body: const PetsHistoryScreen(isApp: true))), + FFRoute( + name: 'vehiclesOnThePropertyPage', + path: '/vehiclesOnThePropertyPage', + builder: (context, params) => const VehicleOnTheProperty()), + FFRoute( + name: 'visitsOnThePropertyPage', + path: '/visitsOnThePropertyPage', + builder: (context, params) => const VisitsOnTheProperty()), FFRoute(name: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()), FFRoute( name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()), FFRoute( - name: 'registerVisitorPage', - path: '/registerVisitorPage', - builder: (context, params) => const RegisterVisitorPageWidget(), - ), + name: 'registerVisitorPage', + path: '/registerVisitorPage', + builder: (context, params) => const RegisterVisitorPageWidget()), FFRoute( name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', - builder: (context, params) { - return const ScheduleCompleteVisitPageWidget(); - }), + builder: (context, params) => const ScheduleCompleteVisitPageWidget()), FFRoute( - name: 'deliverySchedule', - path: '/deliverySchedule', - builder: (context, params) => const DeliverySchedule(), - ), + name: 'deliverySchedule', path: '/deliverySchedule', builder: (context, params) => const DeliverySchedule()), FFRoute( - name: 'provisionalSchedule', - path: '/provisionalSchedule', - builder: (context, params) => const ProvisionalSchedule(), - ), + name: 'provisionalSchedule', + path: '/provisionalSchedule', + builder: (context, params) => const ProvisionalSchedule()), FFRoute( - name: 'fastPassPage', - path: '/fastPassPage', - builder: (context, params) => /*const*/ FastPassPageWidget(), - ), + name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => /*const*/ FastPassPageWidget()), FFRoute( name: 'preferencesSettings', path: '/preferencesSettings', builder: (context, params) => PreferencesPageWidget()), + FFRoute(name: 'aboutProperty', path: '/aboutProperty', builder: (context, params) => AboutPropertyPage()), FFRoute( - name: 'peopleOnThePropertyPage', - path: '/peopleOnThePropertyPage', - builder: (context, params) => const PeopleOnThePropertyPageWidget(), - ), + name: 'peopleOnThePropertyPage', + path: '/peopleOnThePropertyPage', + builder: (context, params) => PeopleOnThePropertyPage()), FFRoute( name: 'acessHistoryPage', path: '/acessHistoryPage', - builder: (context, params) => AccessHistoryScreen(opt: const { - 'personType': '.*', - 'accessType': '.*', - 'search': '.*', - })), + builder: (context, params) => + AccessHistoryScreen(opt: const {'personType': '.*', 'accessType': '.*', 'search': '.*'})), FFRoute( - name: 'liberationHistory', - path: '/liberationHistory', - builder: (context, params) => const LiberationHistoryWidget(), - ), - FFRoute( - name: 'signInPage', - path: '/signInPage', - builder: (context, params) => const SignInPageWidget(), - ), - FFRoute( - name: 'signUpPage', - path: '/signUpPage', - builder: (context, params) => const SignUpPageWidget(), - ), - FFRoute( - name: 'welcomePage', - path: '/welcomePage', - builder: (context, params) => const WelcomePageWidget(), - ), - FFRoute( - name: 'qrCodePage', - path: '/qrCodePage', - builder: (context, params) => const QrCodePageWidget(), - ), - FFRoute( - name: 'preferencesPage', - path: '/preferencesPage', - builder: (context, params) => PreferencesPageWidget(), - ), - FFRoute( - name: 'packageOrder', - path: '/packageOrder', - builder: (context, params) => const PackageOrderPage(), - ), - FFRoute( - name: 'reservation', - path: '/reservation', - builder: (context, params) => ReservationPageWidget(), - ), + name: 'liberationHistory', + path: '/liberationHistory', + builder: (context, params) => const LiberationHistoryWidget()), + FFRoute(name: 'signInPage', path: '/signInPage', builder: (context, params) => const SignInPageWidget()), + FFRoute(name: 'signUpPage', path: '/signUpPage', builder: (context, params) => const SignUpPageWidget()), + FFRoute(name: 'welcomePage', path: '/welcomePage', builder: (context, params) => const WelcomePageWidget()), + FFRoute(name: 'qrCodePage', path: '/qrCodePage', builder: (context, params) => const QrCodePageWidget()), + FFRoute(name: 'preferencesPage', path: '/preferencesPage', builder: (context, params) => PreferencesPageWidget()), + FFRoute(name: 'packageOrder', path: '/packageOrder', builder: (context, params) => const PackageOrderPage()), + FFRoute(name: 'reservation', path: '/reservation', builder: (context, params) => ReservationPageWidget()), FFRoute( name: 'petsPage', path: '/petsPage', builder: (context, params) { - final pet = params.getParam( - 'pet', - ParamType.JSON, - ); - - return PetsPageWidget( - pet: pet, - ); + final pet = params.getParam('pet', ParamType.JSON); + return PetsPageWidget(pet: pet); }, ), - // FFRoute( - // name: 'settingsPage', - // path: '/settingsPage', - // builder: (context, params) => params.isEmpty - // ? const NavBarPage(initialPage: 'settingsPage') - // : const SettingsPageWidget(), - // ) + // FFRoute(name: 'settingsPage', path: '/settingsPage', builder: (context, params) => params.isEmpty ? const NavBarPage(initialPage: 'settingsPage') : const SettingsPageWidget()) ].map((r) => r.toRoute(appStateNotifier)).toList(), ); } @@ -244,13 +184,10 @@ extension NavParamExtensions on Map { 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()) { + if (canPop()) pop(); - } else { + else go('/'); - } } } @@ -276,14 +213,11 @@ extension GoRouterLocationExtension on GoRouter { class FFParameters { FFParameters(this.state, [this.asyncParams = const {}]); - final GoRouterState state; - final Map Function(String)> asyncParams; + 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; @@ -295,36 +229,18 @@ class FFParameters { if (doc != null) { futureParamValues[param.key] = doc; return true; - } - return false; + } else + 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; - } + 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, - ); + if (param is! String) return param; + return deserializeParam(param, type, isList, structBuilder: structBuilder); } } @@ -358,7 +274,6 @@ class FFRoute { ) : builder(context, ffParams); final child = page; - final transitionInfo = state.transitionInfo; return transitionInfo.hasTransition ? CustomTransitionPage( @@ -371,12 +286,7 @@ class FFRoute { reverseDuration: transitionInfo.duration, alignment: transitionInfo.alignment, child: child, - ).buildTransitions( - context, - animation, - secondaryAnimation, - child, - ), + ).buildTransitions(context, animation, secondaryAnimation, child), ) : MaterialPage(key: state.pageKey, child: child); }, @@ -412,8 +322,6 @@ class RootPageContext { return isRootPage && location != '/' && location != rootPageContext?.errorRoute; } - static Widget wrap(Widget child, {String? errorRoute}) => Provider.value( - value: RootPageContext(true, errorRoute), - child: child, - ); + static Widget wrap(Widget child, {String? errorRoute}) => + Provider.value(value: RootPageContext(true, errorRoute), child: child); } diff --git a/lib/pages/about_property_page/about_property_model.dart b/lib/pages/about_property_page/about_property_model.dart new file mode 100644 index 00000000..4bd5e867 --- /dev/null +++ b/lib/pages/about_property_page/about_property_model.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +import 'package:hub/backend/schema/enums/enums.dart'; +import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; +import 'package:hub/components/organism_components/menu_component/menu_component_model.dart'; +import 'package:hub/flutter_flow/flutter_flow_model.dart'; + +import 'package:hub/pages/about_property_page/about_property_screen.dart'; + +class AboutPropertyModel extends FlutterFlowModel { + dynamic item; + + VoidCallback? safeSetState; + + late MenuComponentModel menuComponentModel; + + Future initAsync() async { + safeSetState?.call(); + } + + @override + void initState(BuildContext context) { + menuComponentModel = createModel( + context, + () => MenuComponentModel(expandable: true, style: MenuView.list_grid, item: MenuItem.button, menuOptions: [ + MenuOption.PetsOnTheProperty, + MenuOption.ResidentsOnTheProperty, + MenuOption.VisitsOnTheProperty, + MenuOption.VehiclesOnTheProperty, + MenuOption.PackagesOnTheProperty, + ])); + + initAsync(); + } + + @override + void dispose() {} +} diff --git a/lib/pages/about_property_page/about_property_screen.dart b/lib/pages/about_property_page/about_property_screen.dart new file mode 100644 index 00000000..9a80615a --- /dev/null +++ b/lib/pages/about_property_page/about_property_screen.dart @@ -0,0 +1,76 @@ +// ignore: must_be_immutable +import 'package:flutter/material.dart'; +import 'package:hub/components/atomic_components/shared_components_atoms/appbar.dart'; +import 'package:hub/components/organism_components/menu_component/menu_component_widget.dart'; +import 'package:hub/flutter_flow/flutter_flow_model.dart'; +import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +import 'package:hub/flutter_flow/flutter_flow_util.dart'; +import 'package:hub/flutter_flow/nav/nav.dart'; +import 'package:hub/pages/about_property_page/about_property_model.dart'; + +// ignore: must_be_immutable +class AboutPropertyPage extends StatefulWidget { + dynamic pet; + + AboutPropertyPage({ + super.key, + this.pet, + }); + + @override + State createState() => _AboutPropertyPageState(); +} + +class _AboutPropertyPageState extends State with SingleTickerProviderStateMixin { + late AboutPropertyModel _model; + + @override + void initState() { + super.initState(); + _model = createModel(context, () => AboutPropertyModel()); + _model.updateOnChange = true; + + _model.safeSetState = () { + safeSetState(() {}); + }; + } + + @override + void dispose() { + super.dispose(); + _model.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: _buildBody(context)); + } + + PreferredSizeWidget _buildAppBar(BuildContext context) { + final String title = + FFLocalizations.of(context).getVariableText(ptText: "Sobre a Propriedade", enText: "About the Property"); + return AppBarUtil( + title: title, + onBackButtonPressed: () => context.pop(), + ); + } + + Widget _buildBody(BuildContext context) { + return SingleChildScrollView( + child: Container( + color: FlutterFlowTheme.of(context).primaryBackground, + child: wrapWithModel( + model: _model.menuComponentModel, + updateCallback: () => setState(() {}), + child: Padding( + padding: EdgeInsets.only(bottom: 40), + child: MenuComponentWidget(model: _model.menuComponentModel), + ), + ), + ), + ); + } +} diff --git a/lib/pages/fast_pass_page/fast_pass_page_widget.dart b/lib/pages/fast_pass_page/fast_pass_page_widget.dart index c998e6cc..4cb346c3 100644 --- a/lib/pages/fast_pass_page/fast_pass_page_widget.dart +++ b/lib/pages/fast_pass_page/fast_pass_page_widget.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unused_field + import 'dart:io' show Platform; import 'package:flutter/material.dart'; @@ -32,7 +34,6 @@ class _FastPassPageWidgetState extends State { final url = 'https://hub.freaccess.com.br/hub/fast-pass/$cliUUID'; final freUserData = "{\"name\": \"$name\", \"email\": \"$email\",\"dev_id\": \"$devUUID\",\"created_at\":\"$createdAt\",\"updated_at\": \"0000-00-00 00:00:00\",\"status\": \"A\" }"; - return { 'url': url, 'name': name, @@ -53,84 +54,86 @@ class _FastPassPageWidgetState extends State { future: initVariables(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError || snapshot.hasData == false || snapshot.data!.isEmpty) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) { return Center( child: Text(FFLocalizations.of(context) .getVariableText(enText: 'Unexpected error', ptText: 'Erro inesperado'))); - } else if (snapshot.hasData) { + } else { final data = snapshot.data!; final url = data['url']!; final userUUID = data['userUUID']!; final freUserData = data['freUserData']!; - return Platform.isIOS - ? InAppWebView( - initialUrlRequest: URLRequest(url: WebUri(url)), - initialSettings: InAppWebViewSettings( - allowsBackForwardNavigationGestures: true, - javaScriptEnabled: true, - ), - onWebViewCreated: (controller) async => _controllerIOS = controller, - onLoadStop: (controller, url) async { - await controller.evaluateJavascript( - source: "window.localStorage.setItem('fre-token', '\"$userUUID\"')"); - await controller.evaluateJavascript( - source: "window.localStorage.setItem('fre-user-data', '$freUserData')"); - await controller.evaluateJavascript( - source: "window.localStorage.setItem('enableBackButton', true)"); - }, - onUpdateVisitedHistory: (controller, uri, isVisited) { - if (uri.toString().contains('/hub/home')) context.pop(); - }, - ) - : WebViewWidget( - controller: _controllerAndroid = WebViewController() - ..clearCache() - ..clearLocalStorage() - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setBackgroundColor(const Color(0x00000000)) - ..setNavigationDelegate( - NavigationDelegate( - onProgress: (int progress) {}, - onPageStarted: (String url) { - final String token = "localStorage.setItem('fre-token', '\"$userUUID\"');"; - final String data = "localStorage.setItem('fre-user-data', '$freUserData');"; - const String backNavigation = "localStorage.setItem('enableBackButton', true);"; - - _controllerAndroid.runJavaScript(token); - _controllerAndroid.runJavaScript(data); - _controllerAndroid.runJavaScript(backNavigation); - }, - onPageFinished: (String url) { - bool isDarkMode = - SchedulerBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; - - if (isDarkMode) { - _controllerAndroid.runJavaScript(WebviewUtil.jsEnableDarkMode); - } - }, - onNavigationRequest: (NavigationRequest request) { - if (request.url.startsWith('http') || - request.url.startsWith('https://api.whatsapp.com/send') || - request.url.startsWith('https://wa.me')) { - launchUrlString(request.url); - return NavigationDecision.prevent; - } - return NavigationDecision.prevent; - }, - onUrlChange: (url) { - if (url.url.toString().contains('/hub/home')) context.pop(); - }), - ) - ..loadRequest(Uri.parse(url)), - ); - } else { - return const Center(child: Text('Unexpected error')); + ? _buildIOSWebView(url, userUUID, freUserData) + : _buildAndroidWebView(url, userUUID, freUserData); } }, ), ), ); } + + Widget _buildIOSWebView(String url, String userUUID, String freUserData) { + return InAppWebView( + initialUrlRequest: URLRequest(url: WebUri(url)), + onLoadStart: (controller, url) {}, + initialSettings: InAppWebViewSettings( + allowsBackForwardNavigationGestures: true, + javaScriptEnabled: true, + ), + onWebViewCreated: (controller) async => _controllerIOS = controller, + onLoadStop: (controller, url) async { + await controller.evaluateJavascript(source: "window.localStorage.setItem('fre-token', '\"$userUUID\"')"); + await controller.evaluateJavascript(source: "window.localStorage.setItem('fre-user-data', '$freUserData')"); + await controller.evaluateJavascript(source: "window.localStorage.setItem('enableBackButton', 'true')"); + }, + onUpdateVisitedHistory: (controller, uri, isVisited) { + if (uri.toString().contains('/hub/home')) context.pop(); + }, + ); + } + + Widget _buildAndroidWebView(String url, String userUUID, String freUserData) { + return WebViewWidget( + controller: _controllerAndroid = WebViewController() + ..clearCache() + ..clearLocalStorage() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(const Color(0x00000000)) + ..setNavigationDelegate( + NavigationDelegate( + onPageStarted: (String url) { + final String token = "localStorage.setItem('fre-token', '\"$userUUID\"');"; + final String data = "localStorage.setItem('fre-user-data', '$freUserData');"; + const String backNavigation = "localStorage.setItem('enableBackButton', 'true');"; + + _controllerAndroid.runJavaScript(token); + _controllerAndroid.runJavaScript(data); + _controllerAndroid.runJavaScript(backNavigation); + }, + onPageFinished: (String url) { + bool isDarkMode = SchedulerBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; + + if (isDarkMode) { + _controllerAndroid.runJavaScript(WebviewUtil.jsEnableDarkMode); + } + }, + onNavigationRequest: (NavigationRequest request) { + if (request.url.startsWith('http') || + request.url.startsWith('https://api.whatsapp.com/send') || + request.url.startsWith('https://wa.me')) { + launchUrlString(request.url); + return NavigationDecision.prevent; + } + return NavigationDecision.prevent; + }, + onUrlChange: (url) { + if (url.url.toString().contains('/hub/home')) context.pop(); + }, + ), + ) + ..loadRequest(Uri.parse(url)), + ); + } } diff --git a/lib/pages/home_page/home_page_model.dart b/lib/pages/home_page/home_page_model.dart index b3032db6..17fc9a07 100644 --- a/lib/pages/home_page/home_page_model.dart +++ b/lib/pages/home_page/home_page_model.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:hub/backend/schema/enums/enums.dart'; +import 'package:hub/components/molecular_components/menu_item/menu_item.dart'; import 'package:hub/components/organism_components/local_profile_component/local_profile_component_model.dart'; import 'package:hub/components/organism_components/menu_component/menu_component_model.dart'; import 'package:hub/components/organism_components/message_well_component/message_well_component_model.dart'; @@ -8,6 +10,9 @@ import 'package:hub/shared/helpers/base_storage.dart'; import 'package:hub/shared/helpers/storage_helper.dart'; class HomePageModel extends FlutterFlowModel { + HomePageModel({required this.safeSetState}); + late final VoidCallback safeSetState; + bool isGrid = false; late final String devUUID; late final String cliUUID; @@ -20,7 +25,8 @@ class HomePageModel extends FlutterFlowModel { TextEditingController? textController; String? Function(BuildContext, String?)? textControllerValidator; late LocalProfileComponentModel localComponentModel; - late MenuComponentModel menuComponentModel; + late MenuComponentModel homeMenuComponentModel; + late MenuComponentModel drawerMenuComponentModel; late MessageWellComponentModel messageWellComponentModel; Future _initVariable() async { @@ -35,7 +41,43 @@ class HomePageModel extends FlutterFlowModel { void initState(BuildContext context) { _initVariable(); localComponentModel = createModel(context, () => LocalProfileComponentModel()); - menuComponentModel = createModel(context, () => MenuComponentModel()); + homeMenuComponentModel = createModel( + context, + () => MenuComponentModel(expandable: true, style: MenuView.list_grid, item: MenuItem.button, menuOptions: [ + MenuOption.SettingsOnTheApp, + MenuOption.MessagesOnTheProperty, + MenuOption.AccessOnTheProperty, + MenuOption.PetsRegister, + MenuOption.VisitorsRegister, + MenuOption.ReservationsOnTheLocal, + MenuOption.PackagesOnTheProperty, + MenuOption.DeliverySchedule, + MenuOption.WorkersOnTheProperty, + MenuOption.AboutProperty, + MenuOption.CompleteSchedule, + MenuOption.FastPassSchedule, + MenuOption.LiberationsOnTheProperty, + MenuOption.QRCodeAccessInProperty, + ])); + drawerMenuComponentModel = createModel( + context, + () => MenuComponentModel(expandable: false, style: MenuView.list, item: MenuItem.tile, menuOptions: [ + MenuOption.SettingsOnTheApp, + MenuOption.MessagesOnTheProperty, + MenuOption.AccessOnTheProperty, + MenuOption.PetsRegister, + MenuOption.VisitorsRegister, + MenuOption.ReservationsOnTheLocal, + MenuOption.PackagesOnTheProperty, + MenuOption.DeliverySchedule, + MenuOption.WorkersOnTheProperty, + MenuOption.AboutProperty, + MenuOption.CompleteSchedule, + MenuOption.FastPassSchedule, + MenuOption.LiberationsOnTheProperty, + MenuOption.QRCodeAccessInProperty, + MenuOption.LogoutOnTheApp, + ])); messageWellComponentModel = createModel(context, () => MessageWellComponentModel()); } @@ -46,7 +88,7 @@ class HomePageModel extends FlutterFlowModel { textController?.dispose(); localComponentModel.dispose(); - menuComponentModel.dispose(); + homeMenuComponentModel.dispose(); messageWellComponentModel.dispose(); } } diff --git a/lib/pages/home_page/home_page_widget.dart b/lib/pages/home_page/home_page_widget.dart index 6fa3f5e6..ca2ff3ce 100644 --- a/lib/pages/home_page/home_page_widget.dart +++ b/lib/pages/home_page/home_page_widget.dart @@ -1,8 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:hub/backend/notifications/firebase_messaging_service.dart'; -import 'package:hub/backend/schema/enums/enums.dart'; import 'package:hub/components/organism_components/local_profile_component/local_profile_component_widget.dart'; import 'package:hub/components/organism_components/menu_component/menu_component_widget.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; @@ -39,8 +37,7 @@ class _HomePageWidgetState extends State { void initState() { super.initState(); - _model = createModel(context, () => HomePageModel()); - _model.updateOnChange = true; + _model = createModel(context, () => HomePageModel(safeSetState: () => safeSetState(() {}))); _model.textController ??= TextEditingController(); _model.textFieldFocusNode ??= FocusNode(); @@ -56,55 +53,59 @@ class _HomePageWidgetState extends State { drawerEnableOpenDragGesture: true, drawerDragStartBehavior: DragStartBehavior.start, drawer: CustomDrawer(model: _model), - appBar: AppBar( - backgroundColor: FlutterFlowTheme.of(context).primary, - automaticallyImplyLeading: false, - leading: 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(); - }, - ), - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(8.0), - child: Image.asset( - 'assets/images/logo.png', - width: 15.0, - height: 15.0, - fit: BoxFit.cover, - ), - ), - Text( - '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), - ), - ), - ].divide(const SizedBox(width: 8.0)), - ), - actions: const [], - centerTitle: true, - elevation: 0.0, - ), + appBar: buildAppBar(context), body: buildPage(context), ); } + AppBar buildAppBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primary, + automaticallyImplyLeading: false, + leading: 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(); + }, + ), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.asset( + 'assets/images/logo.png', + width: 15.0, + height: 15.0, + fit: BoxFit.cover, + ), + ), + Text( + '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), + ), + ), + ].divide(const SizedBox(width: 8.0)), + ), + actions: const [], + centerTitle: true, + elevation: 0.0, + ); + } + Container buildPage(BuildContext context) { return Container( decoration: BoxDecoration( @@ -139,14 +140,13 @@ class _HomePageWidgetState extends State { return Container( color: FlutterFlowTheme.of(context).primaryBackground, child: wrapWithModel( - model: _model.menuComponentModel, + model: _model.homeMenuComponentModel, + updateOnChange: true, updateCallback: () => setState(() {}), - child: const Padding( - padding: EdgeInsets.only(bottom: 40), + child: Padding( + padding: const EdgeInsets.only(bottom: 40), child: MenuComponentWidget( - expandable: true, - style: MenuView.list_grid, - item: MenuItem.button, + model: _model.homeMenuComponentModel, ), ), ), diff --git a/lib/pages/package_order_page/package_order_page.dart b/lib/pages/package_order_page/package_order_page.dart index 93394c26..80583700 100644 --- a/lib/pages/package_order_page/package_order_page.dart +++ b/lib/pages/package_order_page/package_order_page.dart @@ -36,11 +36,11 @@ class _PackageOrderPage extends State { List _orderList = []; final Map filter = { - 'adresseeType': '.*', + 'adresseeType': 'PRO', 'status': 'notPickedUp', }; - String _adresseeType = '.*'; + String _adresseeType = 'PRO'; String _status = 'notPickedUp'; late BehaviorSubject> _selectedTypeSubject; @@ -224,7 +224,7 @@ class _PackageOrderPage extends State { return AppBar( backgroundColor: FlutterFlowTheme.of(context).primaryBackground, automaticallyImplyLeading: false, - title: Text(FFLocalizations.of(context).getVariableText(enText: 'My Orders', ptText: 'Minhas Encomendas'), + title: Text(FFLocalizations.of(context).getVariableText(enText: 'Orders', ptText: 'Encomendas'), style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: 'Nunito', color: FlutterFlowTheme.of(context).primaryText, @@ -412,6 +412,7 @@ class _PackageOrderPage extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, appBar: _appBar(context), body: _appBody(context), ); diff --git a/lib/pages/people_on_the_property_page/people_on_the_property_page_model.dart b/lib/pages/people_on_the_property_page/people_on_the_property_page_model.dart index 23a4779d..6e7114f8 100644 --- a/lib/pages/people_on_the_property_page/people_on_the_property_page_model.dart +++ b/lib/pages/people_on_the_property_page/people_on_the_property_page_model.dart @@ -1,14 +1,27 @@ import 'package:flutter/material.dart'; import 'package:hub/flutter_flow/flutter_flow_model.dart'; import 'package:hub/pages/people_on_the_property_page/people_on_the_property_page_widget.dart'; +import 'package:hub/shared/helpers/base_storage.dart'; +import 'package:hub/shared/helpers/storage_helper.dart'; -class PeopleOnThePropertyPageModel extends FlutterFlowModel { - /// State fields for stateful widgets in this page. +class PeopleOnThePropertyPageModel extends FlutterFlowModel { + PeopleOnThePropertyPageModel({this.onRefresh}); + late final VoidCallback? onRefresh; final unfocusNode = FocusNode(); + late final String devUUID; + late final String cliUUID; @override - void initState(BuildContext context) {} + void initState(BuildContext context) { + initVariables(); + } + + void initVariables() async { + devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; + cliUUID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; + onRefresh?.call(); + } @override void dispose() { diff --git a/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart b/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart index de433669..be16c18d 100644 --- a/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart +++ b/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart @@ -1,68 +1,135 @@ -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:hub/backend/api_requests/api_calls.dart'; +import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; 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/nav/nav.dart'; import 'package:hub/pages/people_on_the_property_page/people_on_the_property_page_model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/limited_text_size.dart'; +import 'package:hub/shared/utils/log_util.dart'; -import '../../shared/utils/log_util.dart'; - -class PeopleOnThePropertyPageWidget extends StatefulWidget { - const PeopleOnThePropertyPageWidget({super.key}); +class PeopleOnThePropertyPage extends StatefulWidget { + const PeopleOnThePropertyPage({super.key}); @override - State createState() => _PeopleOnThePropertyPageWidgetState(); + _PeopleOnThePropertyPageState createState() => _PeopleOnThePropertyPageState(); } -class _PeopleOnThePropertyPageWidgetState extends State { - late PeopleOnThePropertyPageModel _model; +class _PeopleOnThePropertyPageState extends State with TickerProviderStateMixin { + late ScrollController _scrollController; - final scaffoldKey = GlobalKey(); + int _pageNumber = 1; + bool _hasData = false; + bool _loading = false; + int count = 0; + + late final PeopleOnThePropertyPageModel model; + + late Future _future; + List _wrap = []; @override void initState() { super.initState(); - _model = createModel(context, () => PeopleOnThePropertyPageModel()); + model = createModel(context, () => PeopleOnThePropertyPageModel(onRefresh: () => safeSetState(() {}))); + _future = _fetchVisits(); + + _scrollController = ScrollController() + ..addListener(() { + if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { + _loadMore(); + } + }); } @override void dispose() { - _model.dispose(); - + _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { + late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); + return Scaffold( - key: scaffoldKey, + appBar: _appBar(context), backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - forceMaterialTransparency: true, - 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( - 'nsu13r5d' /* Pessoas na Propriedade */, - ), + body: 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 morador encontrado!", + enText: "No residents found!", + ), + style: TextStyle( + fontFamily: 'Nunito', + fontSize: limitedHeaderTextSize, + ), + ), + ) + ], + ), + ) + else if (_hasData == true || _pageNumber >= 1) + Expanded( + child: FutureBuilder( + 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( + '', + textAlign: TextAlign.right, + ), + ); + } else { + final item = _wrap[index - 1]; + return _item(context, item); + } + }); + }, + )), + if (_hasData == true && _loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ].addToStart(const SizedBox(height: 0)), + ), + ); + } + + PreferredSizeWidget _appBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text(FFLocalizations.of(context).getVariableText(ptText: 'Moradores', enText: 'Residents'), style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: 'Nunito', color: FlutterFlowTheme.of(context).primaryText, @@ -70,106 +137,114 @@ class _PeopleOnThePropertyPageWidgetState extends State( - future: PhpGroup.getPessoasLocalCall.call(), - 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, - ), - ), - ); - } + onPressed: () => Navigator.of(context).pop(), + ); + } - if (snapshot.hasError || snapshot.data?.exception != null) { - if (snapshot.error != null && snapshot.stackTrace != null) { - LogUtil.requestAPIFailed( - 'getPessoasLocal.php', "", 'Busca Pessoas no Local', snapshot.error, snapshot.stackTrace!); - } + Future _fetchVisits() async { + try { + setState(() => _loading = true); - return Center( - child: SizedBox( - width: double.infinity, - height: 100, - child: Text( - FFLocalizations.of(context) - .getVariableText(ptText: "Pessoas não encontradas", enText: "Persons not found"), - textAlign: TextAlign.center, - ), - ), - ); - } + var response = await PhpGroup.getResidentsByProperty.call(_pageNumber.toString()); - final columnGetPessoasLocalResponse = snapshot.data!; - final getPoepleProperty = PhpGroup.getPessoasLocalCall - .pessoas( - columnGetPessoasLocalResponse.jsonBody, - ) - ?.toList() ?? - []; + final List residents = response.jsonBody['residents'] ?? []; + safeSetState(() => count = response.jsonBody['total_rows'] ?? 0); - return ListView.builder( - physics: const AlwaysScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: getPoepleProperty.length, - itemBuilder: (context, index) { - final getPoeplePropertyItem = getPoepleProperty[index]; - return Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: 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: - 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', - fit: BoxFit.cover, - ), - ), - ), - Text( - getJsonField( - getPoeplePropertyItem, - r'''$.USU_NOME''', - ).toString(), - 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), - ), - ), - ].divide(const SizedBox(width: 20.0)).addToStart(const SizedBox(width: 40.0)), - ); - }, - ); - }, + if (residents.isNotEmpty) { + setState(() { + _wrap.addAll(residents); + _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 moradores", e, s); + setState(() { + _hasData = false; + _loading = false; + }); + } + return null; + } + + void _loadMore() { + if (_hasData == true) { + _pageNumber++; + + _future = _fetchVisits(); + } + } + + void _showNoMoreDataSnackBar(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + FFLocalizations.of(context).getVariableText( + ptText: "Não há mais dados.", + enText: "No more data.", + ), + style: TextStyle( + color: Colors.white, + fontSize: LimitedFontSizeUtil.getBodyFontSize(context), + ), ), + duration: const Duration(seconds: 3), + backgroundColor: FlutterFlowTheme.of(context).primary, ), ); } + + Widget _item(BuildContext context, dynamic uItem) { + return CardItemTemplateComponentWidget( + imagePath: + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${model.devUUID}&cliID=${model.cliUUID}&atividade=getFoto&Documento=${uItem['documento']}&tipo=Z', + labelsHashMap: { + '${FFLocalizations.of(context).getVariableText(ptText: "Nome", enText: "Name")}:': uItem['nome'] ?? '', + //statusweb + '${FFLocalizations.of(context).getVariableText(ptText: "Possui App", enText: "Has App")}:': + uItem['statusweb'] == "A" + ? FFLocalizations.of(context).getVariableText( + ptText: 'Sim', + enText: 'Yes', + ) + : FFLocalizations.of(context).getVariableText( + ptText: 'Não', + enText: 'No', + ), + }, + statusHashMap: [], + onTapCardItemAction: () async {}, + ); + } } diff --git a/lib/pages/pets_page/pets_history_screen.dart b/lib/pages/pets_on_the_property_page/pets_history_screen.dart similarity index 55% rename from lib/pages/pets_page/pets_history_screen.dart rename to lib/pages/pets_on_the_property_page/pets_history_screen.dart index ea951820..a7ee40c4 100644 --- a/lib/pages/pets_page/pets_history_screen.dart +++ b/lib/pages/pets_on_the_property_page/pets_history_screen.dart @@ -1,7 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; +import 'package:hub/backend/api_requests/api_manager.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +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/pages/pets_page/pets_page_model.dart'; import 'package:hub/shared/helpers/base_storage.dart'; @@ -11,8 +15,9 @@ import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/log_util.dart'; class PetsHistoryScreen extends StatefulWidget { - const PetsHistoryScreen({super.key, required this.model}); - final PetsPageModel model; + const PetsHistoryScreen({super.key, this.model, required this.isApp}); + final bool isApp; + final PetsPageModel? model; @override _PetsHistoryScreenState createState() => _PetsHistoryScreenState(); @@ -26,14 +31,15 @@ class _PetsHistoryScreenState extends State with TickerProvid bool _hasData = false; bool _loading = false; int count = 0; - + late final PetsPageModel model; late Future _petsFuture; List _petsWrap = []; @override void initState() { super.initState(); - _petsFuture = _fetch(); + model = widget.model ?? createModel(context, () => PetsPageModel(isInteractive: false)); + _petsFuture = _fetchVisits(); _scrollController = ScrollController() ..addListener(() { if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { @@ -48,7 +54,42 @@ class _PetsHistoryScreenState extends State with TickerProvid super.dispose(); } - Future _fetch() async { + PreferredSizeWidget _appBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text(FFLocalizations.of(context).getVariableText(enText: 'Pets', ptText: 'Pets'), + 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'), + )), + leading: _backButton(context, FlutterFlowTheme.of(context)), + centerTitle: true, + elevation: 0.0, + actions: [], + ); + } + + Widget _backButton(BuildContext context, FlutterFlowTheme theme) { + return FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: theme.primaryText, + size: 30.0, + ), + onPressed: () => Navigator.of(context).pop(), + ); + } + + Future _fetchVisits() async { try { setState(() => _loading = true); @@ -93,7 +134,7 @@ class _PetsHistoryScreenState extends State with TickerProvid if (_hasData == true) { _pageNumber++; - _petsFuture = _fetch(); + _petsFuture = _fetchVisits(); } } @@ -115,66 +156,87 @@ class _PetsHistoryScreenState extends State with TickerProvid @override Widget build(BuildContext context) { - double limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context); - double limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); + late final double limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context); + late final double limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(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 Pet encontrado!", enText: "No pets found"), - style: TextStyle( - fontFamily: 'Nunito', - fontSize: limitedHeaderTextSize, - )), - ) - ], - ), - ) - else if (_hasData == true || _pageNumber >= 1) - Expanded( - child: FutureBuilder( - future: _petsFuture, - builder: (context, snapshot) { - return ListView.builder( - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - controller: _scrollController, - itemCount: _petsWrap.length, - itemBuilder: (context, index) { - final item = _petsWrap[index]; - return _item(context, item); - }); - }, - )), - if (_hasData == true && _loading == true) - Container( - padding: const EdgeInsets.only(top: 15, bottom: 15), - child: Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - FlutterFlowTheme.of(context).primary, + return Scaffold( + appBar: widget.isApp ? _appBar(context) : null, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: 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 Pet encontrado!", enText: "No pets found"), + style: TextStyle( + fontFamily: 'Nunito', + fontSize: limitedHeaderTextSize, + )), + ) + ], + ), + ) + else if (_hasData == true || _pageNumber >= 1) + Expanded( + child: FutureBuilder( + future: _petsFuture, + builder: (context, snapshot) { + return ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + controller: _scrollController, + itemCount: _petsWrap.length + 1, + itemBuilder: (context, index) { + if (index == 0) { + // Add your item here + return Padding( + padding: const EdgeInsets.only(right: 30, top: 10), + child: Text( + model.petAmountRegister == '0' + ? FFLocalizations.of(context).getVariableText(ptText: "Ilimitado", enText: "Unlimited") + : "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Pets: ", enText: "Amount of Pets: ")}$count/${model.petAmountRegister}", + textAlign: TextAlign.right, + style: TextStyle( + fontFamily: 'Nunito', + fontSize: limitedBodyTextSize, + ), + ), + ); + } else { + final item = _petsWrap[index - 1]; + return _item(context, item); + } + }); + }, + )), + if (_hasData == true && _loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), ), ), - ), - ) - ].addToStart(const SizedBox(height: 0)), + ) + ].addToStart(const SizedBox(height: 0)), + ), ); } Widget _item(BuildContext context, dynamic uItem) { return CardItemTemplateComponentWidget( imagePath: - 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${widget.model.devUUID}&userUUID=${widget.model.userUUID}&cliID=${widget.model.cliUUID}&atividade=consultaFotoPet&petId=${uItem['id'] ?? ''}', + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${model.devUUID}&userUUID=${model.userUUID}&cliID=${model.cliUUID}&atividade=consultaFotoPet&petId=${uItem['id'] ?? ''}', labelsHashMap: { '${FFLocalizations.of(context).getVariableText(ptText: "Nome", enText: "Name")}:': uItem['name'] ?? '', '${FFLocalizations.of(context).getVariableText(ptText: "Espécie", enText: "Species")}:': uItem['species'] ?? '', @@ -239,14 +301,14 @@ class _PetsHistoryScreenState extends State with TickerProvid builder: (context) { return Dialog( alignment: Alignment.center, - child: widget.model.buildPetDetails( + child: model.buildPetDetails( item: uItem, context: context, devUUID: devUUID, userUUID: userUUID, cliUUID: cliUUID, cliName: cliName, - model: widget.model, + model: model, ), ); }, @@ -254,7 +316,7 @@ class _PetsHistoryScreenState extends State with TickerProvid safeSetState(() { _pageNumber = 1; _petsWrap = []; - _petsFuture = _fetch().then((value) => value!.jsonBody['pets'] ?? []); + _petsFuture = _fetchVisits().then((value) => value!.jsonBody['pets'] ?? []); }); }).catchError((e, s) async { await DialogUtil.errorDefault(context); diff --git a/lib/pages/pets_page/pets_page_model.dart b/lib/pages/pets_page/pets_page_model.dart index a7d1dca7..ec3d6ccc 100644 --- a/lib/pages/pets_page/pets_page_model.dart +++ b/lib/pages/pets_page/pets_page_model.dart @@ -20,6 +20,11 @@ import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/validator_util.dart'; class PetsPageModel extends FlutterFlowModel { + PetsPageModel({ + required this.isInteractive, + }); + late final bool isInteractive; + late String devUUID = ''; late String userUUID = ''; late String cliUUID = ''; @@ -393,118 +398,116 @@ class PetsPageModel extends FlutterFlowModel { required PetsPageModel model, }) { return DetailsComponentWidget( - buttons: [ - // EDIT ACTION - FFButtonWidget( - text: FFLocalizations.of(context).getVariableText( - ptText: 'Editar', - enText: 'Edit', - ), - icon: const Icon(Icons.edit), - onPressed: () async { - context.pop(); - - model.isEditing = true; - model.item = item; - model.switchTab(0); - model.setEditForm(); - // model.safeSetState!(); - }, - options: FFButtonOptions( - height: 40, - color: FlutterFlowTheme.of(context).primaryBackground, - elevation: 0, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context).primaryText, - fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), - ), - splashColor: const Color.fromARGB(95, 0, 146, 5), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primaryBackground, - width: 1, - ), - // borderRadius: 12, - ), - ), - - // DELETE ACTION - FFButtonWidget( - text: FFLocalizations.of(context).getVariableText( - ptText: 'Excluir', - enText: 'Delete', - ), - icon: const Icon(Icons.close), - onPressed: () async { - showAlertDialog( - context, - FFLocalizations.of(context).getVariableText( - ptText: 'Excluir Pet', - enText: 'Delete Pet', + buttons: isInteractive + ? [ + FFButtonWidget( + text: FFLocalizations.of(context).getVariableText( + ptText: 'Editar', + enText: 'Edit', ), - FFLocalizations.of(context).getVariableText( - ptText: 'Você tem certeza que deseja excluir esse pet?', - enText: 'Are you sure you want to delete this pet?', - ), () async { - int id = item['id']; - await PhpGroup.deletePet - .call( - petID: id, - ) - .then((value) { - // Navigator.pop(context, value); - context.pop(value); - context.pop(value); + icon: const Icon(Icons.edit), + onPressed: () async { + context.pop(); - if (value == false) { - showSnackbar( - context, - FFLocalizations.of(context).getVariableText( - ptText: 'Erro ao excluir pet', - enText: 'Error deleting pet', - ), - true, - ); - } else if (value == true) { - showSnackbar( - context, - FFLocalizations.of(context).getVariableText( - enText: 'Success deleting pet', - ptText: 'Succeso ao excluir pet', - ), - false, - ); - } - }).catchError((err, stack) { - context.pop(); - showSnackbar( - context, - FFLocalizations.of(context).getVariableText( - enText: 'Error deleting pet', - ptText: 'Erro ao excluir pet', + model.isEditing = true; + model.item = item; + model.switchTab(0); + model.setEditForm(); + // model.safeSetState!(); + }, + options: FFButtonOptions( + height: 40, + color: FlutterFlowTheme.of(context).primaryBackground, + elevation: 0, + textStyle: TextStyle( + color: FlutterFlowTheme.of(context).primaryText, + fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), ), - true, - ); - }); - }); - }, - options: FFButtonOptions( - height: 40, - color: FlutterFlowTheme.of(context).primaryBackground, - elevation: 0, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context).primaryText, - fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), - ), - splashColor: const Color.fromARGB(131, 255, 17, 0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primaryBackground, - width: 1, - ), - // borderRadius: 12, - ), - ), - ], - // 'MIN', 'PEQ', 'MED', 'GRA', 'GIG' + splashColor: const Color.fromARGB(95, 0, 146, 5), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, + ), + ), + FFButtonWidget( + text: FFLocalizations.of(context).getVariableText( + ptText: 'Excluir', + enText: 'Delete', + ), + icon: const Icon(Icons.close), + onPressed: () async { + showAlertDialog( + context, + FFLocalizations.of(context).getVariableText( + ptText: 'Excluir Pet', + enText: 'Delete Pet', + ), + FFLocalizations.of(context).getVariableText( + ptText: 'Você tem certeza que deseja excluir esse pet?', + enText: 'Are you sure you want to delete this pet?', + ), () async { + int id = item['id']; + await PhpGroup.deletePet + .call( + petID: id, + ) + .then((value) { + // Navigator.pop(context, value); + context.pop(value); + context.pop(value); + + if (value == false) { + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + ptText: 'Erro ao excluir pet', + enText: 'Error deleting pet', + ), + true, + ); + } else if (value == true) { + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + enText: 'Success deleting pet', + ptText: 'Succeso ao excluir pet', + ), + false, + ); + } + }).catchError((err, stack) { + context.pop(); + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + enText: 'Error deleting pet', + ptText: 'Erro ao excluir pet', + ), + true, + ); + }); + }); + }, + options: FFButtonOptions( + height: 40, + color: FlutterFlowTheme.of(context).primaryBackground, + elevation: 0, + textStyle: TextStyle( + color: FlutterFlowTheme.of(context).primaryText, + fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), + ), + splashColor: const Color.fromARGB(131, 255, 17, 0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, + ), + ), + ] + : [], labelsHashMap: Map.from({ if (item['species'] != null && item['species'] != '') '${FFLocalizations.of(context).getVariableText(ptText: "Espécie", enText: "Species")}:': diff --git a/lib/pages/pets_page/pets_page_widget.dart b/lib/pages/pets_page/pets_page_widget.dart index f3055279..4beac680 100644 --- a/lib/pages/pets_page/pets_page_widget.dart +++ b/lib/pages/pets_page/pets_page_widget.dart @@ -10,7 +10,7 @@ import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/form_field_controller.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/pages/pets_page/pets_history_screen.dart'; +import 'package:hub/pages/pets_on_the_property_page/pets_history_screen.dart'; import 'package:hub/pages/pets_page/pets_page_model.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -34,7 +34,7 @@ class _PetsPageWidgetState extends State with SingleTickerProvid @override void initState() { super.initState(); - _model = createModel(context, () => PetsPageModel()); + _model = createModel(context, () => PetsPageModel(isInteractive: true)); _model.updateOnChange = true; @@ -96,7 +96,7 @@ class _PetsPageWidgetState extends State with SingleTickerProvid labelTab2: FFLocalizations.of(context).getVariableText(ptText: 'Consultar', enText: 'History'), controller: _model.tabBarController, widget1: _model.isEditing ? _buildEditForm(context) : _buildRegisterForm(context), - widget2: PetsHistoryScreen(model: _model), + widget2: PetsHistoryScreen(model: _model, isApp: false), onEditingChanged: onEditingChanged, ); } diff --git a/lib/pages/reception_page/reception_page_widget.dart b/lib/pages/reception_page/reception_page_widget.dart index e6e76e17..77d4c65f 100644 --- a/lib/pages/reception_page/reception_page_widget.dart +++ b/lib/pages/reception_page/reception_page_widget.dart @@ -9,10 +9,9 @@ import 'package:hub/components/atomic_components/shared_components_atoms/atom_im import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; -import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/pages/reception_page/reception_page_model.dart'; -import 'package:hub/shared/helpers/base_storage.dart'; import 'package:hub/shared/helpers/storage_helper.dart'; +import 'package:hub/shared/services/authentication/authentication_service.dart'; import 'package:hub/shared/services/localization/localization_service.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:provider/provider.dart'; @@ -162,21 +161,8 @@ class _ReceptionPageWidgetState extends State with WidgetsB child: FFButtonWidget( onPressed: () async { PhpGroup.unregisterDevice(); - - StorageHelper().c(Storage.secureStorage); - + AuthenticationService.signOut(context); setState(() {}); - - context.go( - '/welcomePage', - extra: { - kTransitionInfoKey: const TransitionInfo( - hasTransition: true, - transitionType: PageTransitionType.scale, - alignment: Alignment.bottomCenter, - ), - }, - ); }, text: FFLocalizations.of(context) .getVariableText(ptText: 'Sair da Conta', enText: 'Logout'), diff --git a/lib/pages/reservation_page/reservation_page_widget.dart b/lib/pages/reservation_page/reservation_page_widget.dart index 1f5e4f47..828f57b4 100644 --- a/lib/pages/reservation_page/reservation_page_widget.dart +++ b/lib/pages/reservation_page/reservation_page_widget.dart @@ -28,12 +28,9 @@ class _ReservationPageWidgetState extends State { final userUUID = (await StorageHelper().g(hub.KeychainStorageKey.userUUID.value)) ?? ''; final clientId = (await StorageHelper().g(hub.KeychainStorageKey.clientUUID.value)) ?? ''; const createdAt = '0000-00-00 00:00:00'; - final url = 'https://hub.freaccess.com.br/hub/reservation/$clientId'; - final freUserData = - "{\"name\": \"$name\", \"email\": \"$email\",\"dev_id\": \"$devUUID\",\"created_at\": \"0000-00-00 00:00:00\",\"updated_at\": \"0000-00-00 00:00:00\",\"status\": \"A\" }"; - + "{\"name\": \"$name\", \"email\": \"$email\",\"dev_id\": \"$devUUID\",\"created_at\": \"$createdAt\",\"updated_at\": \"0000-00-00 00:00:00\",\"status\": \"A\" }"; return { 'url': url, 'name': name, @@ -55,87 +52,84 @@ class _ReservationPageWidgetState extends State { builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError || snapshot.hasData == false || snapshot.data!.isEmpty) { + } else if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) { return Center( child: Text(FFLocalizations.of(context) .getVariableText(enText: 'Unexpected error', ptText: 'Erro inesperado'))); - } else if (snapshot.hasData) { + } else { final data = snapshot.data!; final url = data['url']!; final userUUID = data['userUUID']!; final freUserData = data['freUserData']!; - return Platform.isIOS - ? InAppWebView( - initialUrlRequest: URLRequest(url: WebUri(url)), - initialSettings: InAppWebViewSettings( - allowsBackForwardNavigationGestures: true, - javaScriptEnabled: true, - ), - onWebViewCreated: (controller) async {}, - onLoadStop: (controller, url) async { - await controller.evaluateJavascript( - source: "window.localStorage.setItem('fre-token', '\"$userUUID\"')"); - await controller.evaluateJavascript( - source: "window.localStorage.setItem('fre-user-data', '$freUserData')"); - await controller.evaluateJavascript( - source: "window.localStorage.setItem('enableBackButton', true)"); - }, - onUpdateVisitedHistory: (controller, uri, isVisited) { - if (uri.toString().contains('/hub/home')) { - context.pop(); - } - }, - ) - : WebViewWidget( - controller: _controllerAll = WebViewController() - ..clearCache() - ..clearLocalStorage() - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setBackgroundColor(const Color(0x00000000)) - ..setNavigationDelegate( - NavigationDelegate( - onProgress: (int progress) {}, - onPageStarted: (String url) { - final String token = "localStorage.setItem('fre-token', '\"$userUUID\"');"; - final String data = "localStorage.setItem('fre-user-data', '$freUserData');"; - const String backNavigation = "localStorage.setItem('enableBackButton', true);"; - - _controllerAll.runJavaScript(token); - _controllerAll.runJavaScript(data); - _controllerAll.runJavaScript(backNavigation); - }, - onPageFinished: (String url) { - bool isDarkMode = - SchedulerBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; - - if (isDarkMode) { - _controllerAll.runJavaScript(WebviewUtil.jsEnableDarkMode); - } - }, - onNavigationRequest: (NavigationRequest request) { - if (request.url.startsWith('http') || - request.url.startsWith('https://api.whatsapp.com/send') || - request.url.startsWith('https://wa.me')) { - launchUrlString(request.url); - return NavigationDecision.prevent; - } - return NavigationDecision.prevent; - }, - onUrlChange: (url) { - if (url.url.toString().contains('/hub/home')) { - context.pop(); - } - }), - ) - ..loadRequest(Uri.parse(url)), - ); - } else { - return const Center(child: Text('Unexpected error')); + ? _buildIOSWebView(url, userUUID, freUserData) + : _buildAndroidWebView(url, userUUID, freUserData); } }, ), ), ); } + + Widget _buildIOSWebView(String url, String userUUID, String freUserData) { + return InAppWebView( + initialUrlRequest: URLRequest(url: WebUri(url)), + initialSettings: InAppWebViewSettings( + allowsBackForwardNavigationGestures: true, + javaScriptEnabled: true, + ), + onWebViewCreated: (controller) async {}, + onLoadStop: (controller, url) async { + await controller.evaluateJavascript(source: "window.localStorage.setItem('fre-token', '\"$userUUID\"')"); + await controller.evaluateJavascript(source: "window.localStorage.setItem('fre-user-data', '$freUserData')"); + await controller.evaluateJavascript(source: "window.localStorage.setItem('enableBackButton', 'true')"); + }, + onUpdateVisitedHistory: (controller, uri, isVisited) { + if (uri.toString().contains('/hub/home')) context.pop(); + }, + ); + } + + Widget _buildAndroidWebView(String url, String userUUID, String freUserData) { + return WebViewWidget( + controller: _controllerAll = WebViewController() + ..clearCache() + ..clearLocalStorage() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(const Color(0x00000000)) + ..setNavigationDelegate( + NavigationDelegate( + onPageStarted: (String url) { + final String token = "localStorage.setItem('fre-token', '\"$userUUID\"');"; + final String data = "localStorage.setItem('fre-user-data', '$freUserData');"; + const String backNavigation = "localStorage.setItem('enableBackButton', 'true');"; + + _controllerAll.runJavaScript(token); + _controllerAll.runJavaScript(data); + _controllerAll.runJavaScript(backNavigation); + }, + onPageFinished: (String url) { + bool isDarkMode = SchedulerBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; + + if (isDarkMode) { + _controllerAll.runJavaScript(WebviewUtil.jsEnableDarkMode); + } + }, + onNavigationRequest: (NavigationRequest request) { + if (request.url.startsWith('http') || + request.url.startsWith('https://api.whatsapp.com/send') || + request.url.startsWith('https://wa.me')) { + launchUrlString(request.url); + return NavigationDecision.prevent; + } + return NavigationDecision.prevent; + }, + onUrlChange: (url) { + if (url.url.toString().contains('/hub/home')) context.pop(); + }, + ), + ) + ..loadRequest(Uri.parse(url)), + ); + } } diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart index 6f61ea9f..00d863d2 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart @@ -17,7 +17,9 @@ import 'package:share_plus/share_plus.dart'; import '../../shared/utils/validator_util.dart'; class ScheduleCompleteVisitPageModel extends FlutterFlowModel { - late VoidCallback safeSetState; + ScheduleCompleteVisitPageModel({this.safeSetState}); + + late VoidCallback? safeSetState; late Function(Function) updateState; final _visitHistoryManager = FutureRequestManager(); late final String devUUID; @@ -371,7 +373,7 @@ class ScheduleCompleteVisitPageModel extends FlutterFlowModel void switchTab(int index) { tabBarController?.animateTo(index); - safeSetState.call(); + safeSetState?.call(); } void setFormField() { diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart index db495eb5..2cf0c1cb 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart @@ -1,4 +1,3 @@ -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_spinkit/flutter_spinkit.dart'; @@ -26,9 +25,7 @@ class ScheduleComplete extends StatefulWidget { const ScheduleComplete({super.key}); @override - State createState() { - throw UnimplementedError(); - } + State createState() => throw UnimplementedError(); } class ScheduleCompleteVisitPageWidget extends ScheduleComplete { @@ -52,8 +49,7 @@ class _ScheduleCompleteVisitPageWidgetState extends State ScheduleCompleteVisitPageModel()); - _model.safeSetState = () => safeSetState(() {}); + _model = createModel(context, () => ScheduleCompleteVisitPageModel(safeSetState: () => safeSetState(() {}))); _model.updateState = (Function fn) => safeSetState(fn()); _model.tabBarController = TabController( @@ -758,12 +754,10 @@ class _ScheduleCompleteVisitPageWidgetState extends State(); model.visitorJsonList = visitorsParam!.toList().cast(); safeSetState(() {}); }, getDocs: (docsParam) async { - model.visitorStrList = strListToStr(docsParam!.toList()); model.visitorStrList = strListToStr(docsParam!.toList()); safeSetState(() {}); }, diff --git a/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart b/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart index 0f655b49..ccc84b83 100644 --- a/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart @@ -44,7 +44,7 @@ class _VisitHistoryWidgetState extends State with TickerProv void initState() { super.initState(); - _model = createModel(context, () => ScheduleCompleteVisitPageModel()); + _model = createModel(context, () => ScheduleCompleteVisitPageModel(safeSetState: () => safeSetState(() {}))); _initVariables(); _visitFuture = _fetchVisits(); diff --git a/lib/pages/test_page/test_page.dart b/lib/pages/test_page/test_page.dart deleted file mode 100644 index b7a0e8db..00000000 --- a/lib/pages/test_page/test_page.dart +++ /dev/null @@ -1,62 +0,0 @@ -// import 'dart:developer'; - -// import 'package:f_r_e_hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; -// import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart'; -// import 'package:flutter/material.dart'; - -// class TestPage extends StatelessWidget { -// const TestPage({Key? key}) : super(key: key); - -// @override -// Widget build(BuildContext context) { -// // Exemplo de dados para os HashMaps -// final Map labelsHashMap = { -// 'Nome:': 'Gabriel da Silva', -// 'Entrada:': '08:00 AM 01/01/2022', -// 'Saída:': '17:00 PM 01/01/2022', -// }; - -// // Ajuste para o novo tipo esperado pelo componente -// final Map statusHashMap = { -// 'Ativo': FlutterFlowTheme.of(context).success, -// }; - -// // função set statusHashMap que recebe um String status faz um switch case e retorna um Map -// Map getStatusHashMap(String status) { -// switch (status) { -// case 'Ativo': -// return {'Ativo': FlutterFlowTheme.of(context).success}; -// case 'Inativo': -// return {'Inativo': FlutterFlowTheme.of(context).error}; -// default: -// return {'Desconhecido': FlutterFlowTheme.of(context).primaryColor}; -// } -// } - -// // Ajuste para passar os valores corretos para a URL da imagem -// final Map imageKeyValue = { -// 'key': 'docID', -// 'value': 'imageType', -// }; - -// return Scaffold( -// appBar: AppBar( -// title: const Text('Test Page'), -// ), -// body: Center( -// child: ListView.builder( -// itemCount: 10, -// itemBuilder: (context, index) { -// return CardItemTemplateComponentWidget( -// labelsHashMap: labelsHashMap, -// statusHashMap: statusHashMap, -// imageHashMap: imageKeyValue, -// onTapCardItemAction: () async { -// // Ação ao tocar no card -// }, -// ); -// }), -// ), -// ); -// } -// } diff --git a/lib/pages/vehicles_on_the_property/vehicle_model.dart b/lib/pages/vehicles_on_the_property/vehicle_model.dart new file mode 100644 index 00000000..826095f5 --- /dev/null +++ b/lib/pages/vehicles_on_the_property/vehicle_model.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:hub/components/templates_components/details_component/details_component_widget.dart'; +import 'package:hub/flutter_flow/flutter_flow_model.dart'; +import 'package:hub/flutter_flow/internationalization.dart'; +import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart'; + +class VehicleModel extends FlutterFlowModel { + static VehicleModel? _instance = VehicleModel._internal(); + VehicleModel._internal(); + factory VehicleModel() => _instance ?? VehicleModel._internal(); + static void resetInstance() => _instance = null; + + dynamic item; + + @override + void initState(BuildContext context) { + resetInstance(); + + initAsync(); + } + + @override + void dispose() {} + + Future initAsync() async {} + + Widget buildVehicleDetails({ + required dynamic item, + required BuildContext context, + required VehicleModel model, + }) { + return DetailsComponentWidget( + buttons: [], + labelsHashMap: Map.from({ + if (item['model'] != null && item['model'] != '') + '${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:': + item['model'].toString().toUpperCase(), + if (item['licensePlate'] != null && item['licensePlate'] != '') + '${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:': + item['licensePlate'].toString().toUpperCase(), + if (item['color'] != null && item['color'] != '') + '${FFLocalizations.of(context).getVariableText(ptText: "Cor", enText: "Color")}:': + item['color'].toString().toUpperCase(), + if (item['personName'] != null && item['personName'] != '') + '${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:': + item['personName'].toString().toUpperCase(), + if (item['tag'] != null && item['tag'] != '') + '${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:': + item['tag'].toString().toUpperCase(), + }), + statusHashMap: [], + ); + } +} diff --git a/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart b/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart new file mode 100644 index 00000000..263eb263 --- /dev/null +++ b/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart @@ -0,0 +1,267 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/backend/api_requests/api_calls.dart'; +import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +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/pages/vehicles_on_the_property/vehicle_model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/limited_text_size.dart'; +import 'package:hub/shared/utils/log_util.dart'; + +class VehicleOnTheProperty extends StatefulWidget { + const VehicleOnTheProperty({super.key}); + + @override + _VehicleOnThePropertyState createState() => _VehicleOnThePropertyState(); +} + +class _VehicleOnThePropertyState extends State with TickerProviderStateMixin { + late ScrollController _scrollController; + + int _pageNumber = 1; + bool _hasData = false; + bool _loading = false; + int count = 0; + late final VehicleModel model; + + late Future _future; + List _wrap = []; + + @override + void initState() { + super.initState(); + model = createModel(context, () => VehicleModel()); + _future = _fetchVisits(); + _scrollController = ScrollController() + ..addListener(() { + if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { + _loadMore(); + } + }); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); + + return Scaffold( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: _appBar(context), + body: 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( + 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( + '', + textAlign: TextAlign.right, + ), + ); + } else { + final item = _wrap[index - 1]; + return _item(context, item); + } + }); + }, + )), + if (_hasData == true && _loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ].addToStart(const SizedBox(height: 0)), + ), + ); + } + + PreferredSizeWidget _appBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text(FFLocalizations.of(context).getVariableText(enText: 'Vehicles', ptText: 'Veículos'), + 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'), + )), + leading: _backButton(context, FlutterFlowTheme.of(context)), + centerTitle: true, + elevation: 0.0, + actions: [], + ); + } + + Widget _backButton(BuildContext context, FlutterFlowTheme theme) { + return FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: theme.primaryText, + size: 30.0, + ), + onPressed: () => Navigator.of(context).pop(), + ); + } + + Future _fetchVisits() async { + try { + setState(() => _loading = true); + + var response = await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString()); + + final List 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; + }); + } + return null; + } + + void _loadMore() { + if (_hasData == true) { + _pageNumber++; + + _future = _fetchVisits(); + } + } + + void _showNoMoreDataSnackBar(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + FFLocalizations.of(context).getVariableText( + ptText: "Não há mais dados.", + enText: "No more data.", + ), + style: TextStyle( + color: Colors.white, + fontSize: LimitedFontSizeUtil.getBodyFontSize(context), + ), + ), + duration: const Duration(seconds: 3), + backgroundColor: FlutterFlowTheme.of(context).primary, + ), + ); + } + + Widget _item(BuildContext context, dynamic uItem) { + return CardItemTemplateComponentWidget( + imagePath: null, + labelsHashMap: { + '${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:': + uItem['licensePlate'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:': uItem['model'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:': uItem['tag'] ?? '', + }, + statusHashMap: [], + onTapCardItemAction: () async { + await showDialog( + useSafeArea: true, + context: context, + builder: (context) { + return Dialog( + alignment: Alignment.center, + child: model.buildVehicleDetails( + item: uItem, + context: context, + model: model, + ), + ); + }, + ).whenComplete(() { + safeSetState(() { + _pageNumber = 1; + _wrap = []; + _future = _fetchVisits().then((value) => value!.jsonBody['vehicles'] ?? []); + }); + }).catchError((e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículos", e, s); + safeSetState(() { + _hasData = false; + _loading = false; + }); + }); + }, + ); + } +} diff --git a/lib/pages/visits_on_the_property/model.dart b/lib/pages/visits_on_the_property/model.dart new file mode 100644 index 00000000..fe59a038 --- /dev/null +++ b/lib/pages/visits_on_the_property/model.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:hub/components/templates_components/details_component/details_component_widget.dart'; +import 'package:hub/flutter_flow/flutter_flow_model.dart'; +import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +import 'package:hub/flutter_flow/internationalization.dart'; +import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart'; +import 'package:hub/shared/helpers/base_storage.dart'; +import 'package:hub/shared/helpers/storage_helper.dart'; + +class VisitsModel extends FlutterFlowModel { + static VisitsModel? _instance; + VisitsModel._internal({this.onRefresh}); + factory VisitsModel({VoidCallback? onRefresh}) => _instance ??= VisitsModel._internal(onRefresh: onRefresh); + static void resetInstance() => _instance = null; + late final VoidCallback? onRefresh; + + late final String devUUID; + late final String cliUUID; + + dynamic item; + + @override + void initState(BuildContext context) { + resetInstance(); + + initAsync(); + } + + @override + void dispose() {} + + Future initAsync() async { + devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; + cliUUID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; + onRefresh?.call(); + } + + Widget buildVisitDetails({ + required dynamic item, + required BuildContext context, + required VisitsModel model, + }) { + return DetailsComponentWidget( + buttons: [], + labelsHashMap: Map.from({ + if (item['MOT_DESCRICAO'] != null && item['MOT_DESCRICAO'] != '') + '${FFLocalizations.of(context).getVariableText( + ptText: "Motivo", + enText: "Reason", + )}:': item['MOT_DESCRICAO'].toString().toUpperCase(), + if (item['VTA_DTINICIO'] != null && item['VTA_DTINICIO'] != '') + '${FFLocalizations.of(context).getVariableText( + ptText: "Data de Início", + enText: "Start Date", + )}:': item['VTA_DTINICIO'].toString().toUpperCase(), + if (item['VTA_VALIDADE'] != null && item['VTA_VALIDADE'] != '') + '${FFLocalizations.of(context).getVariableText( + ptText: "Validade", + enText: "Validity", + )}:': item['VTA_VALIDADE'].toString().toUpperCase(), + if (item['VTA_FIXA'] != null && item['VTA_FIXA'] != '') + '${FFLocalizations.of(context).getVariableText( + ptText: "Entrada Única", + enText: "Single Entry", + )}:': item['VTA_FIXA'] == true + ? FFLocalizations.of(context).getVariableText( + ptText: "Sim", + enText: "Yes", + ) + : FFLocalizations.of(context).getVariableText( + ptText: "Não", + enText: "No", + ), + }), + imagePath: + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${devUUID}&cliID=${cliUUID}&atividade=getFoto&Documento=${item['VDO_DOCUMENTO']}&tipo=E', + statusHashMap: [ + if (item['VTA_FIXA'] != null) + Map.from({ + item['VTA_FIXA'] + ? FFLocalizations.of(context).getVariableText(ptText: "Entrada Única", enText: "Single Entry") + : FFLocalizations.of(context).getVariableText( + ptText: "Entrada Recorrente", enText: "Recurrent Entry"): FlutterFlowTheme.of(context).warning + }), + ]); + } +} diff --git a/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart new file mode 100644 index 00000000..b4a283eb --- /dev/null +++ b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart @@ -0,0 +1,281 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/backend/api_requests/api_calls.dart'; +import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +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/pages/visits_on_the_property/model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/log_util.dart'; +import 'package:hub/shared/utils/limited_text_size.dart'; + +class VisitsOnTheProperty extends StatefulWidget { + const VisitsOnTheProperty({super.key}); + + @override + _VisitsOnThePropertyState createState() => _VisitsOnThePropertyState(); +} + +class _VisitsOnThePropertyState extends State with TickerProviderStateMixin { + late ScrollController _scrollController; + + int _pageNumber = 1; + bool _hasData = false; + bool _loading = false; + int count = 0; + late final VisitsModel model; + + late Future _future; + List _list = []; + + @override + void initState() { + super.initState(); + model = createModel(context, () => VisitsModel(onRefresh: () => safeSetState(() {}))); + _future = _fetchVisits(); + + _scrollController = ScrollController() + ..addListener(() { + if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { + _loadMore(); + } + }); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + late final limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context); + late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); + + return Scaffold( + appBar: _appBar(context), + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: 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: "Nenhuma visita em aberto encontrada!", enText: "No opened visits found"), + style: TextStyle( + fontFamily: 'Nunito', + fontSize: limitedHeaderTextSize, + ), + ), + ) + ], + ), + ) + else if (_hasData == true || _pageNumber >= 1) + Expanded( + child: FutureBuilder( + future: _future, + builder: (context, snapshot) { + return ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + controller: _scrollController, + itemCount: _list.length + 1, + itemBuilder: (context, index) { + if (index == 0) { + // Add your item here + return Padding( + padding: const EdgeInsets.only(right: 30, top: 10), + child: Text( + '', + textAlign: TextAlign.right, + ), + ); + } else { + final item = _list[index - 1]; + return _item(context, item); + } + }); + }, + )), + if (_hasData == true && _loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ].addToStart(const SizedBox(height: 0)), + ), + ); + } + + PreferredSizeWidget _appBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text(FFLocalizations.of(context).getVariableText(ptText: 'Visitas em aberto', enText: 'Opened visits'), + 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'), + )), + leading: _backButton(context, FlutterFlowTheme.of(context)), + centerTitle: true, + elevation: 0.0, + actions: [], + ); + } + + Widget _backButton(BuildContext context, FlutterFlowTheme theme) { + return FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: theme.primaryText, + size: 30.0, + ), + onPressed: () => Navigator.of(context).pop(), + ); + } + + Future _fetchVisits() async { + try { + setState(() => _loading = true); + + var response = await PhpGroup.getOpenedVisits.call(_pageNumber.toString()); + + final List visits = response.jsonBody['visitas'] ?? []; + safeSetState(() => count = response.jsonBody['total_rows'] ?? 0); + + if (visits.isNotEmpty) { + setState(() { + _list.addAll(visits); + _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 Visitas", e, s); + setState(() { + _hasData = false; + _loading = false; + }); + } + return null; + } + + void _loadMore() { + if (_hasData == true) { + _pageNumber++; + + _future = _fetchVisits(); + } + } + + void _showNoMoreDataSnackBar(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + FFLocalizations.of(context).getVariableText(ptText: "Não há mais dados.", enText: "No more data."), + style: TextStyle( + color: Colors.white, + fontSize: LimitedFontSizeUtil.getBodyFontSize(context), + ), + ), + duration: const Duration(seconds: 3), + backgroundColor: FlutterFlowTheme.of(context).primary, + ), + ); + } + + Widget _item(BuildContext context, dynamic uItem) { + return CardItemTemplateComponentWidget( + imagePath: + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${model.devUUID}&cliID=${model.cliUUID}&atividade=getFoto&Documento=${uItem['VDO_DOCUMENTO']}&tipo=E', + labelsHashMap: { + '${FFLocalizations.of(context).getVariableText(ptText: "Nome", enText: "Name")}:': uItem['VTA_NOME'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Validade", enText: "Valids")}:': + uItem['VTA_VALIDADE'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Motivo", enText: "Reason")}:': + uItem['MOT_DESCRICAO'][0].toUpperCase() + uItem['MOT_DESCRICAO'].substring(1).toLowerCase(), + }, + statusHashMap: [ + if (uItem['VTA_FIXA'] == true) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Recorrente', + enText: 'Recurrent', + ): FlutterFlowTheme.of(context).warning, + }, + if (uItem['VTA_FIXA'] == false) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Única', + enText: 'Single', + ): FlutterFlowTheme.of(context).success, + }, + ], + onTapCardItemAction: () async { + await showDialog( + useSafeArea: true, + context: context, + builder: (context) { + return Dialog( + alignment: Alignment.center, + child: model.buildVisitDetails( + item: uItem, + context: context, + model: model, + ), + ); + }, + ).whenComplete(() { + safeSetState(() { + _pageNumber = 1; + _list = []; + _future = _fetchVisits().then((value) => value!.jsonBody['visitas'] ?? []); + }); + }).catchError((e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Visitas", e, s); + safeSetState(() { + _hasData = false; + _loading = false; + }); + }); + }, + ); + } +} diff --git a/lib/shared/widgets/drawer_widget/drawer_widget.dart b/lib/shared/widgets/drawer_widget/drawer_widget.dart index 6518abb6..0e43594b 100644 --- a/lib/shared/widgets/drawer_widget/drawer_widget.dart +++ b/lib/shared/widgets/drawer_widget/drawer_widget.dart @@ -1,12 +1,10 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -import 'package:hub/backend/schema/enums/enums.dart'; +import 'package:hub/components/organism_components/menu_component/menu_component_widget.dart'; +import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/pages/home_page/home_page_model.dart'; -import '../../../components/organism_components/menu_component/menu_component_widget.dart'; -import '../../../flutter_flow/flutter_flow_theme.dart'; - class CustomDrawer extends StatelessWidget { const CustomDrawer({super.key, required this.model}); final HomePageModel model; @@ -162,13 +160,9 @@ class CustomDrawer extends StatelessWidget { Widget _buildDrawerBody() { return wrapWithModel( - model: model.menuComponentModel, + model: model.drawerMenuComponentModel, updateCallback: () {}, - child: const MenuComponentWidget( - expandable: false, - style: MenuView.list, - item: MenuItem.tile, - ), + child: MenuComponentWidget(model: model.drawerMenuComponentModel), ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 9ddc4690..19780be7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. publish_to: "none" -version: 1.1.2+13 +version: 1.2.0+14 environment: sdk: ">=3.0.0 <4.0.0"