diff --git a/lib/backend/api_requests/api_calls.dart b/lib/backend/api_requests/api_calls.dart index 6822bd1a..d75f0893 100644 --- a/lib/backend/api_requests/api_calls.dart +++ b/lib/backend/api_requests/api_calls.dart @@ -59,7 +59,7 @@ class PhpGroup { static GetResidentsByProperty getResidentsByProperty = GetResidentsByProperty(); static GetOpenedVisits getOpenedVisits = GetOpenedVisits(); static GetLicense getLicense = GetLicense(); - static GetProvSchedules getProvSchedules = GetProvSchedules(); + static FakeOpenedVisits getProvSchedules = FakeOpenedVisits(); } class GetProvSchedules { @@ -77,7 +77,7 @@ class GetProvSchedules { callType: ApiCallType.POST, headers: {'Content-Type': 'application/x-www-form-urlencoded'}, params: { - if(status != '') 'status': status, + if (status != '') 'status': status, 'devUUID': devUUID, 'userUUID': userUUID, 'cliID': cliID, @@ -128,6 +128,40 @@ class GetOpenedVisits { } } +class FakeOpenedVisits { + Future call(final String page, final String status) async { + final Map jsonBody = { + "error": false, + "agendamento": { + "total": 66, + "value": [ + {"AGP_ID": 32, "AGP_NOME": "assa", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-12-08T12:09:00.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 31, "AGP_NOME": "laksjsal", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-12-08T12:09:00.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 29, "AGP_NOME": "teste", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-12-08T12:01:00.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 30, "AGP_NOME": "jrjdj", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-12-08T12:01:00.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 28, "AGP_NOME": "Lucas test", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-12-08T11:57:00.000Z", "AGP_OBSERVACAO": "dds", "AGP_STATUS": "CO", "IS_DELETED": false}, + { + "AGP_ID": 27, + "AGP_NOME": "Lucas Teste", + "AGP_PRO_ID": 1, + "AGP_DT_VISITA": "2024-12-08T11:54:00.000Z", + "AGP_OBSERVACAO": "Testando ", + "AGP_STATUS": "CO", + "IS_DELETED": false + }, + {"AGP_ID": 84, "AGP_NOME": "dsfsaf", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-11-14T17:28:00.000Z", "AGP_OBSERVACAO": "sdfgds", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 107, "AGP_NOME": "twsre", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-11-12T19:20:00.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "AT", "IS_DELETED": false}, + {"AGP_ID": 86, "AGP_NOME": "AOBA", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-11-09T16:18:36.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false}, + {"AGP_ID": 85, "AGP_NOME": "alibaba", "AGP_PRO_ID": 1, "AGP_DT_VISITA": "2024-11-09T16:14:59.000Z", "AGP_OBSERVACAO": "", "AGP_STATUS": "CO", "IS_DELETED": false} + ] + } + }; + final Map headers = {'Content-Type': 'application/json'}; + final int statusCode = 200; + return ApiCallResponse(jsonBody, headers, statusCode); + } +} + class GetResidentsByProperty { Future call(final String page) async { final String baseUrl = PhpGroup.getBaseUrl(); @@ -192,7 +226,6 @@ class GetVehiclesByProperty { static GetLicense getLicense = GetLicense(); } - class GetLicense { Future call() async { final String baseUrl = PhpGroup.getBaseUrl(); @@ -933,25 +966,27 @@ class GetLocalsCall { final String devUUID = await StorageHelper().get(KeychainStorageKey.devUUID.value) ?? ''; final String userUUID = await StorageHelper().get(KeychainStorageKey.userUUID.value) ?? ''; - return await ApiManager.instance.makeApiCall( - callName: 'getLocals', - apiUrl: '$baseUrl/getLocais.php', - callType: ApiCallType.POST, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - params: { - 'devUUID': devUUID, - 'userUUID': userUUID, - }, - bodyType: BodyType.X_WWW_FORM_URL_ENCODED, - returnBody: true, - encodeBodyUtf8: false, - decodeUtf8: false, - cache: false, - isStreamingApi: false, - alwaysAllowBody: false, - ).timeout(const Duration(seconds: 30)); + return await ApiManager.instance + .makeApiCall( + callName: 'getLocals', + apiUrl: '$baseUrl/getLocais.php', + callType: ApiCallType.POST, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + params: { + 'devUUID': devUUID, + 'userUUID': userUUID, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + isStreamingApi: false, + alwaysAllowBody: false, + ) + .timeout(const Duration(seconds: 30)); } List? locais(dynamic response) => getJsonField( @@ -2637,8 +2672,7 @@ class ApiPagingParams { }); @override - String toString() => - 'PagingParams(nextPageNumber: $nextPageNumber, numItems: $numItems, lastResponse: $lastResponse,)'; + String toString() => 'PagingParams(nextPageNumber: $nextPageNumber, numItems: $numItems, lastResponse: $lastResponse,)'; } String _toEncodable(dynamic item) { diff --git a/lib/components/molecular_components/message_opt_modal/opt_modal_model.dart b/lib/components/molecular_components/message_opt_modal/opt_modal_model.dart deleted file mode 100644 index e2b90125..00000000 --- a/lib/components/molecular_components/message_opt_modal/opt_modal_model.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/form_field_controller.dart'; -import 'opt_modal_widget.dart' show OptModalWidget; - -class OptModalModel extends FlutterFlowModel { - /// State fields for stateful widgets in this component. - - // State field(s) for TextField widget. - FocusNode? textFieldFocusNode; - TextEditingController? textController; - String? Function(BuildContext, String?)? textControllerValidator; - // State field(s) for Checkbox widget. - bool? checkboxValue1; - // State field(s) for Checkbox widget. - bool? checkboxValue2; - // State field(s) for CheckboxGroup widget. - FormFieldController>? checkboxGroupValueController; - List? get checkboxGroupValues => checkboxGroupValueController?.value; - set checkboxGroupValues(List? v) => checkboxGroupValueController?.value = v; - - @override - void initState(BuildContext context) {} - - @override - void dispose() { - textFieldFocusNode?.dispose(); - textController?.dispose(); - } -} diff --git a/lib/components/molecular_components/opt_modal/opt_modal_model.dart b/lib/components/molecular_components/opt_modal/opt_modal_model.dart deleted file mode 100644 index 1f2e3693..00000000 --- a/lib/components/molecular_components/opt_modal/opt_modal_model.dart +++ /dev/null @@ -1,30 +0,0 @@ -import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/form_field_controller.dart'; -import 'opt_modal_widget.dart' show OptModalWidget; -import 'package:flutter/material.dart'; - -class OptModalModel extends FlutterFlowModel { - /// State fields for stateful widgets in this component. - - // State field(s) for TextField widget. - FocusNode? textFieldFocusNode; - TextEditingController? textController; - String? Function(BuildContext, String?)? textControllerValidator; - // State field(s) for Checkbox widget. - bool? checkboxValue1; - // State field(s) for Checkbox widget. - bool? checkboxValue2; - // State field(s) for CheckboxGroup widget. - FormFieldController>? checkboxGroupValueController; - List? get checkboxGroupValues => checkboxGroupValueController?.value; - set checkboxGroupValues(List? v) => checkboxGroupValueController?.value = v; - - @override - void initState(BuildContext context) {} - - @override - void dispose() { - textFieldFocusNode?.dispose(); - textController?.dispose(); - } -} diff --git a/lib/components/molecular_components/opt_modal/opt_modal_widget.dart b/lib/components/molecular_components/opt_modal/opt_modal_widget.dart deleted file mode 100644 index a4914b22..00000000 --- a/lib/components/molecular_components/opt_modal/opt_modal_widget.dart +++ /dev/null @@ -1,302 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_model.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/flutter_flow/nav/nav.dart'; - -class OptModalWidget extends StatefulWidget { - final String defaultPersonType; - final String defaultAccessType; - - const OptModalWidget({ - super.key, - this.defaultPersonType = '.*', - this.defaultAccessType = '.*', - }); - - @override - _OptModalWidgetState createState() => _OptModalWidgetState(); -} - -class _OptModalWidgetState extends State { - late OptModalModel _model; - - late Map selected; - final List> personTypeOptions = [ - {'title': 'zok7lu4w', 'value': 'E'}, - {'title': 'oonqk812', 'value': 'O'}, - ]; - final List> accessTypeOptions = [ - {'title': '580z80ct', 'value': '0'}, - {'title': '1nbwqtzs', 'value': '1'}, - ]; - - @override - void setState(VoidCallback callback) { - super.setState(callback); - _model.onUpdate(); - } - - @override - void initState() { - super.initState(); - - _model = createModel(context, () => OptModalModel()); - - _model.textController ??= TextEditingController(); - _model.textFieldFocusNode ??= FocusNode(); - - selected = { - 'personType': widget.defaultPersonType == '.*' ? ['E', 'O'] : [widget.defaultPersonType], - 'accessType': widget.defaultAccessType == '.*' ? ['0', '1'] : [widget.defaultAccessType], - 'search': '.*', - }; - } - - void _applyFilter() { - Map filterResult = { - 'personType': '', - 'accessType': '', - 'search': _model.textController?.text == '' ? '.*' : _model.textController!.text.toLowerCase(), - }; - - if (selected['personType']!.isEmpty) { - filterResult['personType'] = '.*'; - } else if (selected['personType']!.length > 1) { - filterResult['personType'] = '.*'; - } else { - filterResult['personType'] = selected['personType']!.first; - } - - if (selected['accessType']!.isEmpty) { - filterResult['accessType'] = '.*'; - } else if (selected['accessType']!.length > 1) { - filterResult['accessType'] = '.*'; - } else { - filterResult['accessType'] = selected['accessType']!.first; - } - - // Navigator.pop(context, filterResult); - context.pop(filterResult); - } - - Widget _buildCheckboxListTile(String key, List> options) { - return Column( - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), - child: Text( - FFLocalizations.of(context).getText('l7tw8b92'), - textAlign: TextAlign.left, // Adiciona esta linha para alinhar o texto à esquerda - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), - color: FlutterFlowTheme.of(context).primaryText, - ), - ), - ), - ], - ), - ListView.builder( - shrinkWrap: true, - itemCount: options.length, - itemBuilder: (context, index) { - final option = options[index]; - return CheckboxListTile( - title: Text( - FFLocalizations.of(context).getText(option['title']!), - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), - color: FlutterFlowTheme.of(context).primaryText, - ), - ), - dense: true, - value: selected[key]!.contains(option['value']), - onChanged: (bool? value) { - setState(() { - if (value == true) { - if (!selected[key]!.contains(option['value'])) { - selected[key]!.add(option['value']); - } - } else { - selected[key]!.remove(option['value']); - } - }); - }, - activeColor: FlutterFlowTheme.of(context).primary, - checkColor: FlutterFlowTheme.of(context).info, - checkboxShape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100), - ), - enableFeedback: true, - side: BorderSide( - width: 10, - color: FlutterFlowTheme.of(context).secondaryText, - ), - controlAffinity: ListTileControlAffinity.leading, // Adiciona esta linha - ); - }, - ), - ], - ); - } - - void _updateSelection(String? value, String key) { - setState(() { - if (value == '.') { - selected[key] = []; - } else if (value != null) { - if (selected[key]!.contains(value)) { - selected[key]!.remove(value); - } else { - selected[key]!.add(value); - } - } - }); - } - - @override - Widget build(BuildContext context) { - return SafeArea( - child: Align( - alignment: const AlignmentDirectional(1.0, -1.0), - child: Padding( - padding: const EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 50.0, 0.0), - child: Container( - width: 300.0, - height: 450.0, - decoration: BoxDecoration( - color: FlutterFlowTheme.of(context).primaryBackground, - borderRadius: BorderRadius.circular(24.0), - ), - child: Padding( - padding: const EdgeInsets.all(4.0), - child: Column( - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 0.0, 10.0), - child: Text( - FFLocalizations.of(context).getText('yfj9pd6k'), // Filtros - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, - color: FlutterFlowTheme.of(context).primaryText, - fontSize: 16.0, - letterSpacing: 0.0, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily), - ), - ), - ), - ], - ), - Padding( - padding: const EdgeInsetsDirectional.fromSTEB(8.0, 0.0, 8.0, 0.0), - child: TextFormField( - controller: _model.textController, - focusNode: _model.textFieldFocusNode, - autofocus: false, - obscureText: false, - decoration: InputDecoration( - isDense: true, - labelText: FFLocalizations.of(context).getText( - '0enrtljz' /* Pesquise aqui..... */, - ), - labelStyle: FlutterFlowTheme.of(context).labelMedium.override( - fontFamily: FlutterFlowTheme.of(context).labelMediumFamily, - color: FlutterFlowTheme.of(context).primaryText, - letterSpacing: 0.0, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).labelMediumFamily), - ), - hintStyle: FlutterFlowTheme.of(context).labelMedium.override( - fontFamily: FlutterFlowTheme.of(context).labelMediumFamily, - color: FlutterFlowTheme.of(context).primaryText, - letterSpacing: 0.0, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).labelMediumFamily), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).alternate, - width: 1, - ), - borderRadius: BorderRadius.circular(8.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primary, - width: 1, - ), - borderRadius: BorderRadius.circular(8.0), - ), - errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).error, - width: 1, - ), - borderRadius: BorderRadius.circular(8.0), - ), - focusedErrorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).error, - width: 1, - ), - borderRadius: BorderRadius.circular(8.0), - ), - filled: true, - fillColor: FlutterFlowTheme.of(context).alternate, - suffixIcon: const Icon( - Icons.search_outlined, - ), - ), - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, - letterSpacing: 0.0, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), - ), - validator: _model.textControllerValidator.asValidator(context), - ), - ), - SingleChildScrollView( - child: Container( - padding: const EdgeInsets.all(20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - _buildCheckboxListTile('personType', personTypeOptions), - _buildCheckboxListTile('accessType', accessTypeOptions), - ], - ), - ), - ), - ElevatedButton( - onPressed: _applyFilter, - style: ElevatedButton.styleFrom( - foregroundColor: FlutterFlowTheme.of(context).info, - backgroundColor: FlutterFlowTheme.of(context).primary, - ), - child: Text(FFLocalizations.of(context).getText('88kshkph')), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/pages/acess_history_page/acess_history_page_model.dart b/lib/features/history/presentation/blocs/access_history_bloc.dart similarity index 66% rename from lib/pages/acess_history_page/acess_history_page_model.dart rename to lib/features/history/presentation/blocs/access_history_bloc.dart index 429ae806..dd513e6b 100644 --- a/lib/pages/acess_history_page/acess_history_page_model.dart +++ b/lib/features/history/presentation/blocs/access_history_bloc.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; import 'package:hub/backend/api_requests/api_manager.dart'; -import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart'; +import 'package:hub/features/history/index.dart'; import 'package:hub/flutter_flow/flutter_flow_model.dart'; import 'package:hub/flutter_flow/request_manager.dart'; -import 'package:hub/pages/acess_history_page/acess_history_page_widget.dart'; import 'package:hub/shared/helpers/storage/base_storage.dart'; import 'package:hub/shared/helpers/storage/storage_helper.dart'; @@ -44,24 +43,4 @@ class AcessHistoryPageModel extends FlutterFlowModel { clearAccessHistoryCache(); } - - Future toggleOptionsAction(BuildContext context) async { - await showModalBottomSheet( - isScrollControlled: true, - backgroundColor: Colors.transparent, - useSafeArea: true, - context: context, - builder: (context) { - return GestureDetector( - onTap: () => unfocusNode.canRequestFocus - ? FocusScope.of(context).requestFocus(unfocusNode) - : FocusScope.of(context).unfocus(), - child: Padding( - padding: MediaQuery.viewInsetsOf(context), - child: const OptModalWidget(), - ), - ); - }, - ); - } } diff --git a/lib/features/history/presentation/blocs/history_bloc_template.dart b/lib/features/history/presentation/blocs/history_bloc_template.dart deleted file mode 100644 index 60dfe00f..00000000 --- a/lib/features/history/presentation/blocs/history_bloc_template.dart +++ /dev/null @@ -1,117 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:hub/backend/api_requests/api_manager.dart'; -import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/shared/utils/dialog_util.dart'; -import 'package:hub/shared/utils/log_util.dart'; - -class HistoryBloc extends Bloc { - final ScrollController scrollController = ScrollController(); - final Future Function(int pageSize, int pageNumber, Map opt) fetchHistoryService; - final bool Function(dynamic item, Map opt)? filterLogic; - - HistoryBloc(Map opt, this.fetchHistoryService, {this.filterLogic}) : super(HistoryState(opt: opt)) { - scrollController.addListener(_onScroll); - on(_onUpdateHistory); - on(_onFetchHistory); - add(FetchHistoryEvent()); - } - - void _onScroll() { - if (scrollController.position.atEdge && scrollController.position.pixels != 0) { - add(FetchHistoryEvent()); - } - } - - Future _onUpdateHistory(UpdateHistoryEvent event, Emitter emit) async { - emit(state.copyWith(opt: event.newOpt, historyWrap: [], pageNumber: 1)); - add(FetchHistoryEvent()); - } - - Future _onFetchHistory(FetchHistoryEvent event, Emitter emit) async { - if (state.loading) return; - emit(state.copyWith(loading: true)); - try { - var response = await fetchHistoryService(state.pageSize, state.pageNumber, state.opt); - - final List history = response.jsonBody['acessos'] ?? []; - List filteredHistory = history.where((item) { - if (filterLogic != null) { - return filterLogic!(item, state.opt); - } else { - return true; // Default to no filtering if no logic is provided - } - }).toList(); - - if (filteredHistory.isNotEmpty) { - emit(state.copyWith( - historyWrap: [...state.historyWrap, ...filteredHistory], - hasData: true, - loading: false, - pageNumber: state.pageNumber + 1, - )); - } else { - emit(state.copyWith(hasData: false, loading: false)); - } - } catch (e, s) { - await DialogUtil.errorDefault(navigatorKey.currentContext!); - LogUtil.requestAPIFailed('processRequest', "", "Fetch History", e, s); - emit(state.copyWith(hasData: false, loading: false, error: e.toString())); - } - } - - @override -Future close() { - scrollController.dispose(); - return super.close(); - } -} - -class HistoryState { - final Map opt; - final List historyWrap; - final bool hasData; - final bool loading; - final int pageNumber; - final int pageSize; - final String? error; - - HistoryState({ - required this.opt, - this.historyWrap = const [], - this.hasData = false, - this.loading = false, - this.pageNumber = 1, - this.pageSize = 10, - this.error, - }); - - HistoryState copyWith({ - Map? opt, - List? historyWrap, - bool? hasData, - bool? loading, - int? pageNumber, - int? pageSize, - String? error, - }) { - return HistoryState( - opt: opt ?? this.opt, - historyWrap: historyWrap ?? this.historyWrap, - hasData: hasData ?? this.hasData, - loading: loading ?? this.loading, - pageNumber: pageNumber ?? this.pageNumber, - pageSize: pageSize ?? this.pageSize, - error: error ?? this.error, - ); - } -} - -abstract class HistoryEvent {} - -class UpdateHistoryEvent extends HistoryEvent { - final Map newOpt; - UpdateHistoryEvent(this.newOpt); -} - -class FetchHistoryEvent extends HistoryEvent {} \ No newline at end of file diff --git a/lib/features/history/presentation/blocs/index.dart b/lib/features/history/presentation/blocs/index.dart index 83ccc77f..b189300a 100644 --- a/lib/features/history/presentation/blocs/index.dart +++ b/lib/features/history/presentation/blocs/index.dart @@ -1,2 +1,2 @@ -export 'history_bloc_template.dart'; +export 'access_history_bloc.dart'; export 'provisional_history_bloc.dart'; diff --git a/lib/features/history/presentation/blocs/provisional_history_bloc.dart b/lib/features/history/presentation/blocs/provisional_history_bloc.dart index e69de29b..2601bb51 100644 --- a/lib/features/history/presentation/blocs/provisional_history_bloc.dart +++ b/lib/features/history/presentation/blocs/provisional_history_bloc.dart @@ -0,0 +1,52 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hub/shared/helpers/storage/base_storage.dart'; +import 'package:hub/shared/helpers/storage/storage_helper.dart'; + +class ProvisionalHistoryEvent {} + +class LoadProvisionalHistory extends ProvisionalHistoryEvent {} + +class ProvisionalHistoryStateBloc { + final String devUUID; + final String userUUID; + final String cliUUID; + final bool isLoading; + + ProvisionalHistoryStateBloc({ + required this.devUUID, + required this.userUUID, + required this.cliUUID, + this.isLoading = false, + }); + + ProvisionalHistoryStateBloc copyWith({ + String? devUUID, + String? userUUID, + String? cliUUID, + bool? isLoading, + }) { + return ProvisionalHistoryStateBloc( + devUUID: devUUID ?? this.devUUID, + userUUID: userUUID ?? this.userUUID, + cliUUID: cliUUID ?? this.cliUUID, + isLoading: isLoading ?? this.isLoading, + ); + } +} + +class ProvisionalHistoryBloc extends Bloc { + ProvisionalHistoryBloc() : super(ProvisionalHistoryStateBloc(devUUID: '', userUUID: '', cliUUID: '')) { + on(_onLoadProvisionalHistory); + } + + Future _onLoadProvisionalHistory( + LoadProvisionalHistory event, + Emitter emit, + ) async { + emit(state.copyWith(isLoading: true)); + final devUUID = (await StorageHelper().get(KeychainStorageKey.devUUID.value)) ?? ''; + final userUUID = (await StorageHelper().get(KeychainStorageKey.userUUID.value)) ?? ''; + final cliUUID = (await StorageHelper().get(KeychainStorageKey.clientUUID.value)) ?? ''; + emit(state.copyWith(devUUID: devUUID, userUUID: userUUID, cliUUID: cliUUID, isLoading: false)); + } +} diff --git a/lib/features/history/presentation/index.dart b/lib/features/history/presentation/index.dart index 48b6447a..9a3f70b7 100644 --- a/lib/features/history/presentation/index.dart +++ b/lib/features/history/presentation/index.dart @@ -1,3 +1,4 @@ export 'blocs/index.dart'; -export 'pages/index.dart'; + export 'widgets/index.dart'; +export 'pages/index.dart'; diff --git a/lib/features/history/presentation/pages/a/access_history_page.dart b/lib/features/history/presentation/pages/a/access_history_page.dart new file mode 100644 index 00000000..61dafaf6 --- /dev/null +++ b/lib/features/history/presentation/pages/a/access_history_page.dart @@ -0,0 +1,106 @@ +// import 'package:flutter/material.dart'; +// import 'package:flutter_bloc/flutter_bloc.dart'; +// import 'package:hub/backend/api_requests/api_calls.dart'; +// import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart'; +// import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +// import 'package:hub/features/history/index.dart'; +// import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +// import 'package:hub/flutter_flow/internationalization.dart'; +// import 'package:hub/shared/helpers/storage/base_storage.dart'; +// import 'package:hub/shared/helpers/storage/storage_helper.dart'; + +// class AcessCubit extends Cubit { +// AcessCubit() : super('Provisional'); + +// Future fetchCliUUID() async { +// final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value); +// emit(cliUUID); +// } + +// Future fetchHistoryService(int pageSize, int pageNumber, Map opt) async { +// return await PhpGroup.getAccessCall.call( +// pageSize: pageSize.toString(), +// pageNumber: pageNumber.toString(), +// pesTipo: opt['personType'] != 'E' && opt['personType'] != 'O' ? 'T' : opt['personType'], +// ); +// } + +// bool filterLogic(dynamic item, Map opt) { +// final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType']; +// return personTypeMatches; +// } +// } + +// class AccessHistoryPage extends StatelessWidget { +// final Map opt = { +// 'personType': '.*', +// 'accessType': '.*', +// 'search': '.*', +// }; + +// final String appBarTitle = 'Histórico Provisório'; +// final String noHistoryMessage = 'Nenhum histórico encontrado!'; +// final String errorMessage = 'Falha ao realizar operação!'; + +// @override +// Widget build(BuildContext context) { +// return BlocProvider( +// create: (context) => AcessCubit()..fetchCliUUID(), +// child: HistoryPageTemplate( +// opt: opt, +// fetchHistoryService: (pageSize, pageNumber, opt) => context.read().fetchHistoryService(pageSize, pageNumber, opt), +// cardBuilder: cardBuilder, +// appBarTitle: appBarTitle, +// noHistoryMessage: noHistoryMessage, +// errorMessage: errorMessage, +// isLeading: true, +// isFilter: true, +// filterLogic: (item, opt) => context.read().filterLogic(item, opt), +// ), +// ); +// } + +// Widget cardBuilder(BuildContext context, dynamic historyItem) { +// final cliUUID = context.watch().state; +// final String imagePath = 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}'; +// final Map labelsHashMap = { +// FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['PES_NOME'] ?? '', +// FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['ACE_DATAHORA'] ?? '', +// FFLocalizations.of(context).getVariableText(ptText: 'Setor', enText: 'Sector'): historyItem['SET_DESCRICAO'] ?? '', +// }; + +// final statusHashMap = [ +// _getPersonTypeStatus(context, historyItem['PES_TIPO']), +// _getAccessTypeStatus(context, historyItem['ACE_TIPO']), +// ]; + +// return CardItemTemplateComponentWidget( +// imagePath: imagePath, +// labelsHashMap: labelsHashMap, +// statusHashMap: statusHashMap, +// onTapCardItemAction: () async {}, +// ); +// } + +// Map _getPersonTypeStatus(BuildContext context, String? personType) { +// switch (personType) { +// case 'O': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'): FlutterFlowTheme.of(context).alternate2}; +// case 'E': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'): FlutterFlowTheme.of(context).alternate2}; +// default: +// return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).alternate2}; +// } +// } + +// Map _getAccessTypeStatus(BuildContext context, String? accessType) { +// switch (accessType) { +// case '0': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success}; +// case '1': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error}; +// default: +// return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning}; +// } +// } +// } \ No newline at end of file diff --git a/lib/features/history/presentation/pages/a/history_bloc_template.dart b/lib/features/history/presentation/pages/a/history_bloc_template.dart new file mode 100644 index 00000000..84949a6d --- /dev/null +++ b/lib/features/history/presentation/pages/a/history_bloc_template.dart @@ -0,0 +1,117 @@ +// import 'package:flutter/material.dart'; +// import 'package:flutter_bloc/flutter_bloc.dart'; +// import 'package:hub/backend/api_requests/api_manager.dart'; +// import 'package:hub/flutter_flow/nav/nav.dart'; +// import 'package:hub/shared/utils/dialog_util.dart'; +// import 'package:hub/shared/utils/log_util.dart'; + +// class HistoryBloc extends Bloc { +// final ScrollController scrollController = ScrollController(); +// final Future Function(int pageSize, int pageNumber, Map opt) fetchHistoryService; +// final bool Function(dynamic item, Map opt)? filterLogic; + +// HistoryBloc(Map opt, this.fetchHistoryService, {this.filterLogic}) : super(HistoryState(opt: opt)) { +// scrollController.addListener(_onScroll); +// on(_onUpdateHistory); +// on(_onFetchHistory); +// add(FetchHistoryEvent()); +// } + +// void _onScroll() { +// if (scrollController.position.atEdge && scrollController.position.pixels != 0) { +// add(FetchHistoryEvent()); +// } +// } + +// Future _onUpdateHistory(UpdateHistoryEvent event, Emitter emit) async { +// emit(state.copyWith(opt: event.newOpt, historyWrap: [], pageNumber: 1)); +// add(FetchHistoryEvent()); +// } + +// Future _onFetchHistory(FetchHistoryEvent event, Emitter emit) async { +// if (state.loading) return; +// emit(state.copyWith(loading: true)); +// try { +// var response = await fetchHistoryService(state.pageSize, state.pageNumber, state.opt); + +// final List history = response.jsonBody['acessos'] ?? []; +// List filteredHistory = history.where((item) { +// if (filterLogic != null) { +// return filterLogic!(item, state.opt); +// } else { +// return true; +// } +// }).toList(); + +// if (filteredHistory.isNotEmpty) { +// emit(state.copyWith( +// historyWrap: [...state.historyWrap, ...filteredHistory], +// hasData: true, +// loading: false, +// pageNumber: state.pageNumber + 1, +// )); +// } else { +// emit(state.copyWith(hasData: false, loading: false)); +// } +// } catch (e, s) { +// await DialogUtil.errorDefault(navigatorKey.currentContext!); +// LogUtil.requestAPIFailed('processRequest', "", "Fetch History", e, s); +// emit(state.copyWith(hasData: false, loading: false, error: e.toString())); +// } +// } + +// @override +// Future close() { +// scrollController.dispose(); +// return super.close(); +// } +// } + +// class HistoryState { +// final Map opt; +// final List historyWrap; +// final bool hasData; +// final bool loading; +// final int pageNumber; +// final int pageSize; +// final String? error; + +// HistoryState({ +// required this.opt, +// this.historyWrap = const [], +// this.hasData = false, +// this.loading = false, +// this.pageNumber = 1, +// this.pageSize = 10, +// this.error, +// }); + +// HistoryState copyWith({ +// Map? opt, +// List? historyWrap, +// bool? hasData, +// bool? loading, +// int? pageNumber, +// int? pageSize, +// String? error, +// }) { +// return HistoryState( +// opt: opt ?? this.opt, +// historyWrap: historyWrap ?? this.historyWrap, +// hasData: hasData ?? this.hasData, +// loading: loading ?? this.loading, +// pageNumber: pageNumber ?? this.pageNumber, +// pageSize: pageSize ?? this.pageSize, +// error: error ?? this.error, +// ); +// } +// } + +// abstract class HistoryEvent {} + +// class UpdateHistoryEvent extends HistoryEvent { +// final Map newOpt; +// UpdateHistoryEvent(this.newOpt); +// } + +// class FetchHistoryEvent extends HistoryEvent {} diff --git a/lib/features/history/presentation/pages/a/history_page_template.dart b/lib/features/history/presentation/pages/a/history_page_template.dart new file mode 100644 index 00000000..09fba0f6 --- /dev/null +++ b/lib/features/history/presentation/pages/a/history_page_template.dart @@ -0,0 +1,218 @@ +// import 'dart:developer'; + +// import 'package:flutter/material.dart'; +// import 'package:flutter_bloc/flutter_bloc.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// import 'package:hub/features/history/index.dart'; +// import 'package:hub/flutter_flow/internationalization.dart'; +// import 'package:hub/flutter_flow/nav/nav.dart'; +// import 'package:hub/backend/api_requests/api_manager.dart'; +// import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +// import 'package:hub/shared/utils/dialog_util.dart'; +// import 'package:hub/shared/utils/log_util.dart'; +// import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; + +// class HistoryPageTemplate extends StatelessWidget { +// final Map opt; +// final Future Function(int pageSize, int pageNumber, Map opt) fetchHistoryService; +// final Widget Function(BuildContext context, dynamic historyItem) cardBuilder; +// final String appBarTitle; +// final String noHistoryMessage; +// final String errorMessage; +// final bool isLeading; +// final bool isFilter; +// final bool Function(dynamic item, Map opt)? filterLogic; + +// const HistoryPageTemplate({ +// Key? key, +// required this.opt, +// required this.fetchHistoryService, +// required this.cardBuilder, +// this.appBarTitle = 'History', +// this.noHistoryMessage = 'No history found!', +// this.errorMessage = 'Failed to perform operation!', +// this.isLeading = true, +// this.isFilter = false, +// this.filterLogic, +// }) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// return BlocProvider( +// create: (context) => HistoryBloc(opt, fetchHistoryService, filterLogic: filterLogic), +// child: HistoryPageView( +// cardBuilder: cardBuilder, +// appBarTitle: appBarTitle, +// noHistoryMessage: noHistoryMessage, +// errorMessage: errorMessage, +// isLeading: isLeading, +// isFilter: isFilter, +// ), +// ); +// } +// } + +// class HistoryPageView extends StatelessWidget { +// final Widget Function(BuildContext context, dynamic historyItem) cardBuilder; +// final String appBarTitle; +// final String noHistoryMessage; +// final String errorMessage; +// final bool isLeading; +// final bool isFilter; + +// const HistoryPageView({ +// Key? key, +// required this.cardBuilder, +// required this.appBarTitle, +// required this.noHistoryMessage, +// required this.errorMessage, +// this.isLeading = false, +// this.isFilter = false, +// }) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// final theme = FlutterFlowTheme.of(context); +// return Scaffold( +// key: GlobalKey(), +// backgroundColor: theme.primaryBackground, +// appBar: _buildAppBar(context, theme), +// body: _buildBody(context), +// ); +// } + +// PreferredSizeWidget _buildAppBar(BuildContext context, FlutterFlowTheme theme) { +// return AppBar( +// backgroundColor: theme.primaryBackground, +// automaticallyImplyLeading: false, +// leading: isLeading ? _buildBackButton(context, theme) : null, +// title: _buildTitle(context, theme), +// centerTitle: true, +// elevation: 0.0, +// actions: [ +// if (isFilter) _buildFilterButton(context), +// ], +// ); +// } + +// Widget _buildBackButton(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(), +// ); +// } + +// Widget _buildTitle(BuildContext context, FlutterFlowTheme theme) { +// return Text( +// appBarTitle, +// style: theme.headlineMedium.override( +// fontFamily: theme.headlineMediumFamily, +// color: theme.primaryText, +// fontSize: 16.0, +// letterSpacing: 0.0, +// useGoogleFonts: GoogleFonts.asMap().containsKey(theme.headlineMediumFamily), +// ), +// ); +// } + +// Widget _buildFilterButton(BuildContext context) { +// return Row( +// mainAxisAlignment: MainAxisAlignment.end, +// children: [ +// Padding( +// padding: const EdgeInsets.fromLTRB(0, 0, 10, 0), +// child: IconButton( +// icon: const Icon(Icons.filter_list), +// onPressed: () async { +// final Map? selectedFilter = await showModalBottomSheet>( +// isScrollControlled: true, +// backgroundColor: Colors.transparent, +// context: context, +// builder: (BuildContext bottomSheetContext) { +// return GestureDetector( +// onTap: () => Navigator.of(bottomSheetContext).pop(), +// child: Container( +// color: Colors.transparent, +// child: GestureDetector( +// onTap: () {}, +// child: FilterModalWidget( +// defaultSelections: { +// 'personType': context.read().state.opt['personType'] == '.*' ? ['E', 'O'] : [context.read().state.opt['personType']], +// 'search': '.*', +// }, +// filterOptions: { +// 'personType': [ +// { +// 'title': FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'), +// 'value': 'E', +// }, +// { +// 'title': FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'), +// 'value': 'O', +// }, +// ], +// }, +// filterTitles: { +// 'personType': 'Person Type', +// }, +// ), +// ), +// ), +// ); +// }, +// ); + +// if (selectedFilter != null) { +// context.read().add(UpdateHistoryEvent(selectedFilter)); +// } +// }, +// ), +// ), +// ], +// ); +// } + +// Widget _buildBody(BuildContext context) { +// return BlocBuilder( +// builder: (context, state) { +// log('state: ${state.historyWrap}'); +// if (state.loading && state.historyWrap.isEmpty) { +// return Center( +// child: CircularProgressIndicator( +// valueColor: AlwaysStoppedAnimation( +// FlutterFlowTheme.of(context).primary, +// ), +// ), +// ); +// } else if (state.error != null) { +// return Center( +// child: Text(errorMessage), +// ); +// } else if (state.historyWrap.isEmpty) { +// return Center( +// child: Text(noHistoryMessage), +// ); +// } else { +// return ListView.builder( +// shrinkWrap: true, +// physics: const BouncingScrollPhysics(), +// controller: context.read().scrollController, +// itemCount: state.historyWrap.length, +// itemBuilder: (context, index) { +// final historyItem = state.historyWrap[index]; +// return cardBuilder(context, historyItem); +// }, +// ); +// } +// }, +// ); +// } +// } diff --git a/lib/features/history/presentation/pages/a/index.dart b/lib/features/history/presentation/pages/a/index.dart new file mode 100644 index 00000000..41cbf609 --- /dev/null +++ b/lib/features/history/presentation/pages/a/index.dart @@ -0,0 +1,3 @@ +export 'access_history_page.dart'; +export 'history_page_template.dart'; +export 'provisional_history_page copy.dart'; diff --git a/lib/features/history/presentation/pages/a/provisional_history_page copy.dart b/lib/features/history/presentation/pages/a/provisional_history_page copy.dart new file mode 100644 index 00000000..81f60ba5 --- /dev/null +++ b/lib/features/history/presentation/pages/a/provisional_history_page copy.dart @@ -0,0 +1,100 @@ +// import 'dart:developer'; + +// import 'package:flutter/material.dart'; +// import 'package:flutter_bloc/flutter_bloc.dart'; +// import 'package:hub/backend/api_requests/api_calls.dart'; +// import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart'; +// import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +// import 'package:hub/features/history/index.dart'; +// import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +// import 'package:hub/flutter_flow/internationalization.dart'; +// import 'package:hub/shared/helpers/storage/base_storage.dart'; +// import 'package:hub/shared/helpers/storage/storage_helper.dart'; + +// class ProvisionalCubit extends Cubit { +// ProvisionalCubit() : super('Provisional'); + +// Future fetchCliUUID() async { +// final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value); +// emit(cliUUID); +// } + +// Future fetchHistoryService(int pageSize, int pageNumber, Map status) async { +// log('fetchHistoryService: $pageSize, $pageNumber, $status'); +// return await PhpGroup.getProvSchedules(pageNumber.toString(), ''); +// } + +// bool filterLogic(dynamic item, Map opt) { +// final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType']; +// return personTypeMatches; +// } +// } + +// class ProvisionalHistoryPage extends StatelessWidget { +// ProvisionalHistoryPage({super.key}); + +// final Map opt = { +// 'personType': '.*', +// 'accessType': '.*', +// 'search': '.*', +// }; + +// final String appBarTitle = 'Histórico Provisório'; +// final String noHistoryMessage = 'Nenhum histórico encontrado!'; +// final String errorMessage = 'Falha ao realizar operação!'; + +// @override +// Widget build(BuildContext context) { +// return BlocProvider( +// create: (context) => HistoryBloc( +// opt, +// (pageSize, pageNumber, opt) => context.read().fetchHistoryService(pageSize, pageNumber, opt), +// filterLogic: (item, opt) => context.read().filterLogic(item, opt), +// ), +// child: HistoryPageTemplate( +// opt: opt, +// fetchHistoryService: (pageSize, pageNumber, opt) => context.read().fetchHistoryService(pageSize, pageNumber, opt), +// cardBuilder: cardBuilder, +// appBarTitle: appBarTitle, +// noHistoryMessage: noHistoryMessage, +// errorMessage: errorMessage, +// isLeading: true, +// isFilter: false, +// filterLogic: (item, opt) => context.read().filterLogic(item, opt), +// ), +// ); +// } + +// Widget cardBuilder(BuildContext context, dynamic historyItem) { +// log('historyItem: $historyItem'); +// final cliUUID = context.watch().state; +// final String imagePath = +// 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}'; +// final Map labelsHashMap = { +// FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['AGP_NOME'] ?? '', +// FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['AGP_DT_VISITA'] ?? '', +// }; + +// final statusHashMap = [ +// _getTypeStatus(context, historyItem['AGP_STATUS']), +// ]; + +// return CardItemTemplateComponentWidget( +// imagePath: imagePath, +// labelsHashMap: labelsHashMap, +// statusHashMap: statusHashMap, +// onTapCardItemAction: () async {}, +// ); +// } + +// Map _getTypeStatus(BuildContext context, String? accessType) { +// switch (accessType) { +// case '0': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success}; +// case '1': +// return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error}; +// default: +// return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning}; +// } +// } +// } diff --git a/lib/features/history/presentation/pages/access_history_page.dart b/lib/features/history/presentation/pages/access_history_page.dart deleted file mode 100644 index ac031632..00000000 --- a/lib/features/history/presentation/pages/access_history_page.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:hub/backend/api_requests/api_calls.dart'; -import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart'; -import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; -import 'package:hub/features/history/index.dart'; -import 'package:hub/flutter_flow/flutter_flow_theme.dart'; -import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/shared/helpers/storage/base_storage.dart'; -import 'package:hub/shared/helpers/storage/storage_helper.dart'; - -class AcessCubit extends Cubit { - AcessCubit() : super('Provisional'); - - Future fetchCliUUID() async { - final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value); - emit(cliUUID); - } - - Future fetchHistoryService(int pageSize, int pageNumber, Map opt) async { - return await PhpGroup.getAccessCall.call( - pageSize: pageSize.toString(), - pageNumber: pageNumber.toString(), - pesTipo: opt['personType'] != 'E' && opt['personType'] != 'O' ? 'T' : opt['personType'], - ); - } - - bool filterLogic(dynamic item, Map opt) { - final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType']; - return personTypeMatches; - } -} - -class AccessHistoryPage extends StatelessWidget { - final Map opt = { - 'personType': '.*', - 'accessType': '.*', - 'search': '.*', - }; - - final String appBarTitle = 'Histórico Provisório'; - final String noHistoryMessage = 'Nenhum histórico encontrado!'; - final String errorMessage = 'Falha ao realizar operação!'; - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => AcessCubit()..fetchCliUUID(), - child: HistoryPageTemplate( - opt: opt, - fetchHistoryService: (pageSize, pageNumber, opt) => context.read().fetchHistoryService(pageSize, pageNumber, opt), - cardBuilder: cardBuilder, - appBarTitle: appBarTitle, - noHistoryMessage: noHistoryMessage, - errorMessage: errorMessage, - isLeading: true, - isFilter: true, - filterLogic: (item, opt) => context.read().filterLogic(item, opt), - ), - ); - } - - Widget cardBuilder(BuildContext context, dynamic historyItem) { - final cliUUID = context.watch().state; - final String imagePath = 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}'; - final Map labelsHashMap = { - FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['PES_NOME'] ?? '', - FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['ACE_DATAHORA'] ?? '', - FFLocalizations.of(context).getVariableText(ptText: 'Setor', enText: 'Sector'): historyItem['SET_DESCRICAO'] ?? '', - }; - - final statusHashMap = [ - _getPersonTypeStatus(context, historyItem['PES_TIPO']), - _getAccessTypeStatus(context, historyItem['ACE_TIPO']), - ]; - - return CardItemTemplateComponentWidget( - imagePath: imagePath, - labelsHashMap: labelsHashMap, - statusHashMap: statusHashMap, - onTapCardItemAction: () async {}, - ); - } - - Map _getPersonTypeStatus(BuildContext context, String? personType) { - switch (personType) { - case 'O': - return {FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'): FlutterFlowTheme.of(context).alternate2}; - case 'E': - return {FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'): FlutterFlowTheme.of(context).alternate2}; - default: - return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).alternate2}; - } - } - - Map _getAccessTypeStatus(BuildContext context, String? accessType) { - switch (accessType) { - case '0': - return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success}; - case '1': - return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error}; - default: - return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning}; - } - } -} \ No newline at end of file diff --git a/lib/pages/acess_history_page/acess_history_page_widget.dart b/lib/features/history/presentation/pages/acess_history_page_widget.dart similarity index 90% rename from lib/pages/acess_history_page/acess_history_page_widget.dart rename to lib/features/history/presentation/pages/acess_history_page_widget.dart index 1f239f26..81501e99 100644 --- a/lib/pages/acess_history_page/acess_history_page_widget.dart +++ b/lib/features/history/presentation/pages/acess_history_page_widget.dart @@ -4,12 +4,11 @@ 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/molecular_components/message_opt_modal/opt_modal_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; +import 'package:hub/features/history/index.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/acess_history_page/acess_history_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'; @@ -18,11 +17,8 @@ import 'package:rxdart/rxdart.dart'; @immutable // ignore: must_be_immutable class AccessHistoryScreen extends StatefulWidget { - late Map opt = { - 'personType': '.*', - 'accessType': '.*', - 'search': '.*', - }; + late Map opt = {'personType': '.*'}; + AccessHistoryScreen({super.key, required this.opt}); @override State createState() => _AccessHistoryState(opt); @@ -75,10 +71,11 @@ class _AccessHistoryState extends State { final theme = FlutterFlowTheme.of(context); return Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: _appBar(context, theme), - body: _body(context)); + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: _appBar(context, theme), + body: _body(context), + ); } PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) { @@ -141,8 +138,21 @@ class _AccessHistoryState extends State { color: Colors.transparent, child: GestureDetector( onTap: () {}, - child: OptModalWidget( - defaultPersonType: selectedTypeSubject.value['personType'] ?? '.*', + child: FilterWidget( + defaultSelections: selectedTypeSubject.value, + filterOptions: { + 'personType': [ + { + 'title': FFLocalizations.of(context).getText('zok7lu4w'), + 'value': 'E', + }, + { + 'title': FFLocalizations.of(context).getText('oonqk812'), + 'value': 'O', + }, + ], + }, + filterTitles: {'personType': ''}, ), ), ), @@ -247,8 +257,7 @@ class _AccessHistoryState extends State { children: [ Center( child: Text( - FFLocalizations.of(context) - .getVariableText(ptText: "Nenhum histórico encontrado!", enText: "No history found!"), + FFLocalizations.of(context).getVariableText(ptText: "Nenhum histórico encontrado!", enText: "No history found!"), )), ], ), @@ -301,8 +310,7 @@ class _AccessHistoryState extends State { ); } else if (snapshot.hasError) { return Center( - child: Text(FFLocalizations.of(context) - .getVariableText(ptText: "Falha ao efetuar operação!", enText: "Failed to perform operation!")), + child: Text(FFLocalizations.of(context).getVariableText(ptText: "Falha ao efetuar operação!", enText: "Failed to perform operation!")), ); } diff --git a/lib/features/history/presentation/pages/history_page_template.dart b/lib/features/history/presentation/pages/history_page_template.dart deleted file mode 100644 index 884d6bc9..00000000 --- a/lib/features/history/presentation/pages/history_page_template.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:hub/features/history/index.dart'; -import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/backend/api_requests/api_manager.dart'; -import 'package:hub/features/history/presentation/widgets/filter_modal.dart'; -import 'package:hub/flutter_flow/flutter_flow_theme.dart'; -import 'package:hub/shared/utils/dialog_util.dart'; -import 'package:hub/shared/utils/log_util.dart'; -import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; - -class HistoryPageTemplate extends StatelessWidget { - final Map opt; - final Future Function(int pageSize, int pageNumber, Map opt) fetchHistoryService; - final Widget Function(BuildContext context, dynamic historyItem) cardBuilder; - final String appBarTitle; - final String noHistoryMessage; - final String errorMessage; - final bool isLeading; - final bool isFilter; - final bool Function(dynamic item, Map opt)? filterLogic; - - const HistoryPageTemplate({ - Key? key, - required this.opt, - required this.fetchHistoryService, - required this.cardBuilder, - this.appBarTitle = 'History', - this.noHistoryMessage = 'No history found!', - this.errorMessage = 'Failed to perform operation!', - this.isLeading = true, - this.isFilter = false, - this.filterLogic, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => HistoryBloc(opt, fetchHistoryService, filterLogic: filterLogic), - child: HistoryPageView( - cardBuilder: cardBuilder, - appBarTitle: appBarTitle, - noHistoryMessage: noHistoryMessage, - errorMessage: errorMessage, - isLeading: isLeading, - isFilter: isFilter, - ), - ); - } -} - -class HistoryPageView extends StatelessWidget { - final Widget Function(BuildContext context, dynamic historyItem) cardBuilder; - final String appBarTitle; - final String noHistoryMessage; - final String errorMessage; - final bool isLeading; - final bool isFilter; - - const HistoryPageView({ - Key? key, - required this.cardBuilder, - required this.appBarTitle, - required this.noHistoryMessage, - required this.errorMessage, - this.isLeading = false, - this.isFilter = false, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = FlutterFlowTheme.of(context); - return Scaffold( - key: GlobalKey(), - backgroundColor: theme.primaryBackground, - appBar: _buildAppBar(context, theme), - body: _buildBody(context), - ); - } - - PreferredSizeWidget _buildAppBar(BuildContext context, FlutterFlowTheme theme) { - return AppBar( - backgroundColor: theme.primaryBackground, - automaticallyImplyLeading: false, - leading: isLeading ? _buildBackButton(context, theme) : null, - title: _buildTitle(context, theme), - centerTitle: true, - elevation: 0.0, - actions: [ - if (isFilter) _buildFilterButton(context), - ], - ); - } - - Widget _buildBackButton(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(), - ); - } - - Widget _buildTitle(BuildContext context, FlutterFlowTheme theme) { - return Text( - appBarTitle, - style: theme.headlineMedium.override( - fontFamily: theme.headlineMediumFamily, - color: theme.primaryText, - fontSize: 16.0, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey(theme.headlineMediumFamily), - ), - ); - } - - Widget _buildFilterButton(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 10, 0), - child: IconButton( - icon: const Icon(Icons.filter_list), - onPressed: () async { - final Map? selectedFilter = await showModalBottomSheet>( - isScrollControlled: true, - backgroundColor: Colors.transparent, - context: context, - builder: (BuildContext bottomSheetContext) { - return GestureDetector( - onTap: () => Navigator.of(bottomSheetContext).pop(), - child: Container( - color: Colors.transparent, - child: GestureDetector( - onTap: () {}, - child: FilterModalWidget( - defaultSelections: { - 'personType': context.read().state.opt['personType'] == '.*' ? ['E', 'O'] : [context.read().state.opt['personType']], - 'search': '.*', - }, - filterOptions: { - 'personType': [ - {'title': FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'), 'value': 'E',}, - {'title': FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'), 'value': 'O',}, - - ], - }, - filterTitles: { - 'personType': 'Person Type', - }, - ), - ), - ), - ); - }, - ); - - if (selectedFilter != null) { - context.read().add(UpdateHistoryEvent(selectedFilter)); - } - }, - ), - ), - ], - ); - } - - Widget _buildBody(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state.loading && state.historyWrap.isEmpty) { - return Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - FlutterFlowTheme.of(context).primary, - ), - ), - ); - } else if (state.error != null) { - return Center( - child: Text(errorMessage), - ); - } else if (state.historyWrap.isEmpty) { - return Center( - child: Text(noHistoryMessage), - ); - } else { - return ListView.builder( - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - controller: context.read().scrollController, - itemCount: state.historyWrap.length, - itemBuilder: (context, index) { - final historyItem = state.historyWrap[index]; - return cardBuilder(context, historyItem); - }, - ); - } - }, - ); - } -} \ No newline at end of file diff --git a/lib/features/history/presentation/pages/index.dart b/lib/features/history/presentation/pages/index.dart index 5b174ec8..0b731c13 100644 --- a/lib/features/history/presentation/pages/index.dart +++ b/lib/features/history/presentation/pages/index.dart @@ -1,2 +1,2 @@ -export 'history_page_template.dart'; +export 'acess_history_page_widget.dart'; export 'provisional_history_page.dart'; diff --git a/lib/features/history/presentation/pages/provisional_history_page.dart b/lib/features/history/presentation/pages/provisional_history_page.dart index 9df73420..3f6b23d2 100644 --- a/lib/features/history/presentation/pages/provisional_history_page.dart +++ b/lib/features/history/presentation/pages/provisional_history_page.dart @@ -1,105 +1,429 @@ +import 'dart:async'; import 'dart:developer'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.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/molecular_components/message_opt_modal/opt_modal_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/features/history/index.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/internationalization.dart'; -import 'package:hub/shared/helpers/storage/base_storage.dart'; -import 'package:hub/shared/helpers/storage/storage_helper.dart'; +import 'package:hub/flutter_flow/flutter_flow_util.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 'package:rxdart/rxdart.dart'; -class ProvisionalCubit extends Cubit { - ProvisionalCubit() : super('Provisional'); - - Future fetchCliUUID() async { - final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value); - emit(cliUUID); - } - - Future fetchHistoryService(int pageSize, int pageNumber, Map status) async { - return await PhpGroup.getProvSchedules(pageNumber.toString(), ''); - } - - bool filterLogic(dynamic item, Map opt) { - final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType']; - return personTypeMatches; - } +@immutable +// ignore: must_be_immutable +class ProvisionalHistoryPage extends StatefulWidget { + Map opt; + ProvisionalHistoryPage({super.key, Map? opt}) : opt = opt ?? const {'AGP_STATUS': '.*'}; + @override + State createState() => ProvisionalHistoryState(opt); } -class ProvisionalHistoryPage extends StatelessWidget { - final Map opt = { - 'personType': '.*', - 'accessType': '.*', - 'search': '.*', - }; +class ProvisionalHistoryState extends State { + final BehaviorSubject> selectedTypeSubject; + late ScrollController _scrollController; + final scaffoldKey = GlobalKey(); - final String appBarTitle = 'Histórico Provisório'; - final String noHistoryMessage = 'Nenhum histórico encontrado!'; - final String errorMessage = 'Falha ao realizar operação!'; + bool _isSubjectClosed = false; + int _pageNumber = 1; + bool hasData = false; + bool _loading = false; + + String status = '.*'; + + late Future future; + List wrap = []; + + ProvisionalHistoryState(Map opt) : selectedTypeSubject = BehaviorSubject.seeded(opt) { + selectedTypeSubject.listen((value) {}); + } + + @override + void initState() { + super.initState(); + future = fetchHistoryService(); + _scrollController = ScrollController() + ..addListener(() { + if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { + _loadMore(); + } + }); + } + + @override + void dispose() { + selectedTypeSubject.close(); + _isSubjectClosed = true; + super.dispose(); + } @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => ProvisionalCubit()..fetchCliUUID(), - child: HistoryPageTemplate( - opt: opt, - fetchHistoryService: (pageSize, pageNumber, opt) => context.read().fetchHistoryService(pageSize, pageNumber, opt), - cardBuilder: cardBuilder, - appBarTitle: appBarTitle, - noHistoryMessage: noHistoryMessage, - errorMessage: errorMessage, - isLeading: true, - isFilter: false, - filterLogic: (item, opt) => context.read().filterLogic(item, opt), + final theme = FlutterFlowTheme.of(context); + return Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: _appBar(context, theme), + body: _body(context), + ); + } + + PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) { + return AppBar( + backgroundColor: theme.primaryBackground, + automaticallyImplyLeading: false, + leading: _backButton(context, theme), + title: _title(context, theme), + centerTitle: true, + elevation: 0.0, + actions: [_filterButton(context)], + ); + } + + 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(), + ); + } + + Widget _title(BuildContext context, FlutterFlowTheme theme) { + return Text( + FFLocalizations.of(context).getVariableText( + ptText: 'Histórico Provisório', + enText: 'Provisional History', + ), + style: theme.headlineMedium.override( + fontFamily: theme.headlineMediumFamily, + color: theme.primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey(theme.headlineMediumFamily), ), ); } - Widget cardBuilder(BuildContext context, dynamic historyItem) { - log('historyItem: $historyItem'); - final cliUUID = context.watch().state; - final String imagePath = 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}'; - final Map labelsHashMap = { - FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['PES_NOME'] ?? '', - FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['ACE_DATAHORA'] ?? '', - FFLocalizations.of(context).getVariableText(ptText: 'Setor', enText: 'Sector'): historyItem['SET_DESCRICAO'] ?? '', - }; + Widget _filterButton(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 10, 0), + child: IconButton( + icon: const Icon(Icons.filter_list), + onPressed: () async { + final Map? selectedFilter = await showModalBottomSheet>( + isScrollControlled: true, + backgroundColor: Colors.transparent, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Container( + color: Colors.transparent, + child: GestureDetector( + onTap: () {}, + child: FilterWidget( + defaultSelections: selectedTypeSubject.value, + filterOptions: { + 'AGP_STATUS': [ + { + 'title': FFLocalizations.of(context).getVariableText( + ptText: 'Ativo', + enText: 'Active', + ), + 'value': 'AT', + }, + { + 'title': FFLocalizations.of(context).getVariableText( + ptText: 'Convidado', + enText: 'Guest', + ), + 'value': 'CO', + }, + { + 'title': FFLocalizations.of(context).getVariableText( + ptText: 'Inativo', + enText: 'Inactive', + ), + 'value': 'IN', + }, + { + 'title': FFLocalizations.of(context).getVariableText( + ptText: 'Aguardando Aprovação', + enText: 'Awaiting Approval', + ), + 'value': 'AA', + }, + ], + }, + filterTitles: {'AGP_STATUS': ''}, + ), + ), + ), + ); + }); - final statusHashMap = [ - _getPersonTypeStatus(context, historyItem['PES_TIPO']), - _getAccessTypeStatus(context, historyItem['ACE_TIPO']), - ]; + if (selectedFilter != null) { + _updateHistoryAction(selectedFilter); + } + }, + ), + ), + ], + ); + } + void _updateHistoryAction(Map newType) { + if (!_isSubjectClosed) { + final currentType = selectedTypeSubject.value; + final updatedType = Map.from(currentType); + bool needsUpdate = false; + newType.forEach((key, newValue) { + if (currentType[key] != newValue) { + updatedType[key] = newValue; + needsUpdate = true; + } + }); + if (needsUpdate) { + selectedTypeSubject.add(updatedType); + fetchCardListViewService(updatedType); + safeSetState(() {}); + } + } + } + + Future fetchHistoryService() async { + try { + setState(() => _loading = true); + var response = await PhpGroup.getProvSchedules(_pageNumber.toString(), status); + + final List history = response.jsonBody['agendamento']['value'] ?? []; + + List filtered = history.where((item) { + bool statusMatches = status == '.*'; + if (statusMatches) return statusMatches; + statusMatches = item["AGP_STATUS"].toString() == status; + return statusMatches; + }).toList(); + // List filtered = history; + + if (filtered.isNotEmpty) { + setState(() { + wrap.addAll(filtered); + hasData = true; + _loading = false; + }); + return response; + } + _showNoMoreDataSnackbar(context); + setState(() { + hasData = false; + _loading = false; + }); + return null; + } catch (e, s) { + await DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed('processRequest', "", "Busca Acesso", e, s); + setState(() { + hasData = false; + _loading = false; + }); + } + return null; + } + + 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 _body(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + 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 histórico encontrado!", enText: "No history found!"), + )), + ], + ), + ) + else if (hasData || _pageNumber >= 1) + Expanded(child: _cardListViewOrganismWidget()), + if (hasData == true && _loading) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ], + ); + } + + void _loadMore() { + if (hasData == true) { + _pageNumber++; + future = fetchHistoryService(); + } + } + + void fetchCardListViewService(Map select) { + status = select['AGP_STATUS']!; + wrap = []; + _pageNumber = 1; + future = fetchHistoryService(); + } + + Widget _cardListViewOrganismWidget() { + return FutureBuilder( + future: future, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting && wrap.isEmpty) { + return Center( + child: SizedBox( + width: 50.0, + height: 50.0, + child: SpinKitCircle( + color: FlutterFlowTheme.of(context).primary, + size: 50.0, + ), + ), + ); + } else if (snapshot.hasError) { + return Center( + child: Text(FFLocalizations.of(context).getVariableText(ptText: "Falha ao efetuar operação!", enText: "Failed to perform operation!")), + ); + } + + return ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + controller: _scrollController, + itemCount: wrap.length, + itemBuilder: (context, index) { + final historyItem = wrap[index]; + return _historyCardMoleculeWidget(context, historyItem); + }, + ); + }, + ); + } + + Widget _historyCardMoleculeWidget(BuildContext context, dynamic historyItem) { return CardItemTemplateComponentWidget( - imagePath: imagePath, - labelsHashMap: labelsHashMap, - statusHashMap: statusHashMap, + imagePath: _imageUrlAtomWidget(historyItem['AGP_NOME'], 'P'), + labelsHashMap: _buildLabelsHashMap(context, historyItem), + statusHashMap: _buildStatusHashMap(context, historyItem), onTapCardItemAction: () async {}, ); } - Map _getPersonTypeStatus(BuildContext context, String? personType) { - switch (personType) { - case 'O': - return {FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'): FlutterFlowTheme.of(context).alternate2}; - case 'E': - return {FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'): FlutterFlowTheme.of(context).alternate2}; - default: - return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).alternate2}; - } + String _imageUrlAtomWidget(String document, String type) { + return valueOrDefault( + "https://freaccess.com.br/freaccess/getImage.php?&cliID=&atividade=getFoto&Documento=$document&tipo=$type", + "https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg", + ); } - Map _getAccessTypeStatus(BuildContext context, String? accessType) { - switch (accessType) { - case '0': - return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success}; - case '1': - return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error}; + Map _buildLabelsHashMap(BuildContext context, dynamic historyItem) { + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Nome:', + enText: 'Name:', + ): historyItem['AGP_NOME'] ?? '', + FFLocalizations.of(context).getVariableText( + ptText: 'Data:', + enText: 'Data:', + ): historyItem['AGP_DT_VISITA'] ?? '', + }; + } + + List> _buildStatusHashMap(BuildContext context, dynamic historyItem) { + return [ + { + FFLocalizations.of(context).getVariableText( + ptText: 'Visitante', + enText: 'Visitor', + ): FlutterFlowTheme.of(context).alternate2, + }, + _getStatusMap(context, historyItem['AGP_STATUS']) + ]; + } + + Map _getStatusMap(BuildContext context, String status) { + log('status: $status'); + switch (status) { + case 'AT': + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Ativo', + enText: 'Active', + ): FlutterFlowTheme.of(context).success, + }; + case 'CO': + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Convidado', + enText: 'Guest', + ): FlutterFlowTheme.of(context).tertiary, + }; + case 'IN': + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Inativo', + enText: 'Inactive', + ): FlutterFlowTheme.of(context).error, + }; + case 'AA': + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Aguardando Aprovação', + enText: 'Awaiting Approval', + ): FlutterFlowTheme.of(context).warning, + }; default: - return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning}; + return { + FFLocalizations.of(context).getVariableText( + ptText: 'Desconhecido', + enText: 'Unknown', + ): FlutterFlowTheme.of(context).alternate2, + }; } } -} \ No newline at end of file +} diff --git a/lib/components/molecular_components/message_opt_modal/opt_modal_widget.dart b/lib/features/history/presentation/widgets/access_filter_modal.dart similarity index 84% rename from lib/components/molecular_components/message_opt_modal/opt_modal_widget.dart rename to lib/features/history/presentation/widgets/access_filter_modal.dart index bba2ea01..85a5ecbb 100644 --- a/lib/components/molecular_components/message_opt_modal/opt_modal_widget.dart +++ b/lib/features/history/presentation/widgets/access_filter_modal.dart @@ -1,27 +1,53 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_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/form_field_controller.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; -class OptModalWidget extends StatefulWidget { +class AccessFilterModel extends FlutterFlowModel { + /// State fields for stateful widgets in this component. + + // State field(s) for TextField widget. + FocusNode? textFieldFocusNode; + TextEditingController? textController; + String? Function(BuildContext, String?)? textControllerValidator; + // State field(s) for Checkbox widget. + bool? checkboxValue1; + // State field(s) for Checkbox widget. + bool? checkboxValue2; + // State field(s) for CheckboxGroup widget. + FormFieldController>? checkboxGroupValueController; + List? get checkboxGroupValues => checkboxGroupValueController?.value; + set checkboxGroupValues(List? v) => checkboxGroupValueController?.value = v; + + @override + void initState(BuildContext context) {} + + @override + void dispose() { + textFieldFocusNode?.dispose(); + textController?.dispose(); + } +} + +class AccessFilter extends StatefulWidget { final String defaultPersonType; final String defaultAccessType; - const OptModalWidget({ + const AccessFilter({ super.key, this.defaultPersonType = '.*', this.defaultAccessType = '.*', }); @override - _OptModalWidgetState createState() => _OptModalWidgetState(); + _AccessFilterState createState() => _AccessFilterState(); } -class _OptModalWidgetState extends State { - late OptModalModel _model; +class _AccessFilterState extends State { + late AccessFilterModel _model; late Map selected; final List> personTypeOptions = [ @@ -39,7 +65,7 @@ class _OptModalWidgetState extends State { void initState() { super.initState(); - _model = createModel(context, () => OptModalModel()); + _model = createModel(context, () => AccessFilterModel()); _model.textController ??= TextEditingController(); _model.textFieldFocusNode ??= FocusNode(); @@ -194,8 +220,7 @@ class _OptModalWidgetState extends State { fontSize: LimitedFontSizeUtil.getHeaderFontSize(context), letterSpacing: 0.0, fontWeight: FontWeight.bold, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily), + useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily), ), ), ), @@ -227,8 +252,7 @@ class _OptModalWidgetState extends State { fontSize: LimitedFontSizeUtil.getInputFontSize(context), letterSpacing: 0.0, fontWeight: FontWeight.bold, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), + useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), )), ), ], diff --git a/lib/features/history/presentation/widgets/index.dart b/lib/features/history/presentation/widgets/index.dart index 2191ab0c..d48e5262 100644 --- a/lib/features/history/presentation/widgets/index.dart +++ b/lib/features/history/presentation/widgets/index.dart @@ -1 +1,2 @@ -export 'filter_modal.dart'; +export 'access_filter_modal.dart'; +export 'provisional_filter_modal.dart'; diff --git a/lib/features/history/presentation/widgets/filter_modal.dart b/lib/features/history/presentation/widgets/provisional_filter_modal.dart similarity index 83% rename from lib/features/history/presentation/widgets/filter_modal.dart rename to lib/features/history/presentation/widgets/provisional_filter_modal.dart index c44a545b..5ef83145 100644 --- a/lib/features/history/presentation/widgets/filter_modal.dart +++ b/lib/features/history/presentation/widgets/provisional_filter_modal.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -7,9 +9,7 @@ import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; - - -class FilterModal extends FlutterFlowModel { +class FilterModel extends FlutterFlowModel { FocusNode? textFieldFocusNode; TextEditingController? textController; String? Function(BuildContext, String?)? textControllerValidator; @@ -29,12 +29,12 @@ class FilterModal extends FlutterFlowModel { } } -class FilterModalWidget extends StatefulWidget { +class FilterWidget extends StatefulWidget { final Map defaultSelections; final Map>> filterOptions; final Map filterTitles; - const FilterModalWidget({ + const FilterWidget({ super.key, required this.defaultSelections, required this.filterOptions, @@ -42,11 +42,11 @@ class FilterModalWidget extends StatefulWidget { }); @override - _FilterModalWidgetState createState() => _FilterModalWidgetState(); + _FilterWidgetState createState() => _FilterWidgetState(); } -class _FilterModalWidgetState extends State { - late FilterModal _model; +class _FilterWidgetState extends State { + late FilterModel _model; late Map selected; @override @@ -59,12 +59,12 @@ class _FilterModalWidgetState extends State { void initState() { super.initState(); - _model = createModel(context, () => FilterModal()); + _model = createModel(context, () => FilterModel()); _model.textController ??= TextEditingController(); _model.textFieldFocusNode ??= FocusNode(); - selected = widget.defaultSelections; + selected = Map.from(widget.defaultSelections); } void _applyFilter() { @@ -73,11 +73,15 @@ class _FilterModalWidgetState extends State { }; widget.filterOptions.forEach((key, options) { - filterResult[key] = selected[key]!.isEmpty || selected[key]!.length > 1 - ? '.*' - : selected[key]!.first; + log('key: $key' + ' selected: ${selected[key]}'); + log('options: $options'); + filterResult[key] = selected[key]!.isEmpty || selected[key]!.length < 1 ? '.*' : selected[key]!; + }); + log('filterResult: $filterResult'); + setState(() { + // Update the state with the new filter result + selected = filterResult; }); - context.pop(filterResult); } @@ -126,12 +130,14 @@ class _FilterModalWidgetState extends State { value: selected[key]!.contains(option['value']), onChanged: (bool? value) { setState(() { + log('value: $value'); if (value == true) { if (!selected[key]!.contains(option['value'])) { - selected[key]!.add(option['value']); + log('selected[key]: ${selected[key]}'); + selected[key] = option['value']; } } else { - selected[key]!.remove(option['value']); + selected[key] = ''; } }); }, @@ -176,15 +182,17 @@ class _FilterModalWidgetState extends State { Padding( padding: const EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 0.0, 10.0), child: Text( - FFLocalizations.of(context).getText('yfj9pd6k'), + FFLocalizations.of(context).getVariableText( + ptText: 'Filtros', + enText: 'Filters', + ), style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).primaryText, fontSize: LimitedFontSizeUtil.getHeaderFontSize(context), letterSpacing: 0.0, fontWeight: FontWeight.bold, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily), + useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily), ), ), ), @@ -209,15 +217,18 @@ class _FilterModalWidgetState extends State { foregroundColor: FlutterFlowTheme.of(context).info, backgroundColor: FlutterFlowTheme.of(context).primary, ), - child: Text(FFLocalizations.of(context).getText('88kshkph'), + child: Text( + FFLocalizations.of(context).getVariableText( + ptText: 'Aplicar', + enText: 'Apply', + ), style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, color: FlutterFlowTheme.of(context).info, fontSize: LimitedFontSizeUtil.getInputFontSize(context), letterSpacing: 0.0, fontWeight: FontWeight.bold, - useGoogleFonts: - GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), + useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily), )), ), ], diff --git a/lib/features/home/presentation/pages/home_page.dart b/lib/features/home/presentation/pages/home_page.dart index 350ae9a2..48742d97 100644 --- a/lib/features/home/presentation/pages/home_page.dart +++ b/lib/features/home/presentation/pages/home_page.dart @@ -1,4 +1,3 @@ - import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -10,7 +9,6 @@ import 'package:hub/shared/components/molecules/drawer/index.dart'; import 'package:hub/shared/components/molecules/locals/index.dart'; import 'package:hub/shared/components/molecules/menu/index.dart'; - class HomePageWidget extends StatefulWidget { const HomePageWidget(this.update, {super.key}); final Future Function(BuildContext context)? update; @@ -29,8 +27,8 @@ class _HomePageWidgetState extends State with WidgetsBindingObse WidgetsBinding.instance.addPostFrameCallback((_) async { await LocalsRepositoryImpl().check(context); if (widget.update != null) { - await widget.update!(context); - } + await widget.update!(context); + } }); } @@ -40,7 +38,6 @@ class _HomePageWidgetState extends State with WidgetsBindingObse super.dispose(); } - @override Widget build(BuildContext context) { return Builder( @@ -49,7 +46,7 @@ class _HomePageWidgetState extends State with WidgetsBindingObse // context.read().add(LocalProfileEvent()); // context.read().add(MenuEvent()); LocalsRepositoryImpl.license.add(true); - + return Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 25209384..44104d7a 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -3,17 +3,17 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hub/backend/schema/util/schema_util.dart'; +import 'package:hub/features/history/index.dart'; import 'package:hub/features/home/index.dart'; import 'package:hub/features/property/index.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/pages/acess_history_page/acess_history_page_widget.dart'; import 'package:hub/pages/delivery_schedule_page/delivery_schedule_widget.dart'; import 'package:hub/pages/fast_pass_page/fast_pass_page_widget.dart'; import 'package:hub/pages/forgot_password_page/forgot_password_screen.dart'; import 'package:hub/pages/liberation_history/liberation_history_widget.dart'; -import 'package:hub/pages/message_history_page/message_history_page_widget.dart'; import 'package:hub/pages/package_order_page/package_order_page.dart'; import 'package:hub/pages/people_on_the_property_page/people_on_the_property_page_widget.dart'; import 'package:hub/pages/pets_on_the_property_page/pets_history_screen.dart'; @@ -31,7 +31,11 @@ import 'package:hub/pages/sign_up_page/sign_up_page_widget.dart'; import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart'; import 'package:hub/pages/visits_on_the_property/visits_on_the_property_screen.dart'; import 'package:hub/pages/welcome_page/welcome_page_widget.dart'; -import 'package:hub/shared/components/molecules/locals/data/repositories/locals_repository_impl.dart'; +import 'package:hub/shared/components/molecules/locals/presentation/blocs/local_profile_bloc.dart'; +import 'package:hub/shared/components/molecules/menu/domain/entities/menu_item.dart'; +import 'package:hub/shared/components/molecules/menu/presentation/blocs/menu_bloc.dart'; +import 'package:hub/shared/components/molecules/menu/presentation/mappers/menu_entry.dart'; +import 'package:hub/shared/components/molecules/menu/presentation/widgets/menu_view/menu_list_view.dart'; import 'package:hub/shared/helpers/storage/base_storage.dart'; import 'package:hub/shared/helpers/storage/storage_helper.dart'; import 'package:hub/shared/utils/dialog_util.dart'; @@ -92,7 +96,26 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { final bool haveDevUUID = (await StorageHelper().get(KeychainStorageKey.devUUID.value))?.isNotEmpty ?? false; if (isLogged && haveDevUUID && haveUserUUID) { - return haveLocal ? HomePageWidget(LocalsRepositoryImpl().update) : const ReceptionPageWidget(); + return haveLocal + ? MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => MenuBloc( + style: MenuView.list_grid, + item: EnumMenuItem.button, + entries: MenuEntry.getEntriesByType(MenuEntryType.Home), + )..add(MenuEvent()), + ), + BlocProvider( + create: (context) => HomeBloc()..add(HomeEvent()), + ), + BlocProvider( + create: (context) => LocalProfileBloc()..add(LocalProfileEvent()), + ), + ], + child: ProvisionalHistoryPage(), + ) + : const ReceptionPageWidget(); } else { return const WelcomePageWidget(); } @@ -123,20 +146,43 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { token: token, ); }), - FFRoute(name: 'homePage', path: '/homePage', builder: (context, params) { - final Future Function(BuildContext context)? update = params.getParam('update', ParamType.Function); - return HomePageWidget(key: UniqueKey(), update); - - }), + FFRoute( + name: 'homePage', + path: '/homePage', + builder: (context, params) { + final Future Function(BuildContext context)? update = params.getParam('update', ParamType.Function); + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => MenuBloc( + style: MenuView.list_grid, + item: EnumMenuItem.button, + entries: MenuEntry.getEntriesByType(MenuEntryType.Home), + )..add(MenuEvent()), + ), + BlocProvider( + create: (context) => HomeBloc()..add(HomeEvent()), + ), + BlocProvider( + create: (context) => LocalProfileBloc()..add(LocalProfileEvent()), + ), + ], + child: HomePageWidget(key: UniqueKey(), update), + ); + }), FFRoute(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: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()), - FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()), + FFRoute( + name: 'messageHistoryPage', + path: '/messageHistoryPage', + builder: (context, params) => ProvisionalHistoryPage(opt: {'filterType': '.*'}), + ), FFRoute(name: 'registerVisitorPage', path: '/registerVisitorPage', builder: (context, params) => const RegisterVisitorPageWidget()), FFRoute(name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', builder: (context, params) => const ScheduleCompleteVisitPageWidget()), FFRoute(name: 'deliverySchedule', path: '/deliverySchedule', builder: (context, params) => const DeliverySchedule()), FFRoute(name: 'provisionalSchedule', path: '/provisionalSchedule', builder: (context, params) => const ProvisionalSchedule()), - FFRoute(name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => /*const*/ FastPassPageWidget()), + FFRoute(name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => FastPassPageWidget()), FFRoute(name: 'preferencesSettings', path: '/preferencesSettings', builder: (context, params) => PreferencesPageWidget()), FFRoute(name: 'aboutProperty', path: '/aboutProperty', builder: (context, params) => AboutPropertyPage()), FFRoute(name: 'residentsOnThePropertyPage', path: '/residentsOnThePropertyPage', builder: (context, params) => ResidentsOnTheProperty()), @@ -146,6 +192,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { name: 'acessHistoryPage', path: '/acessHistoryPage', builder: (context, params) => AccessHistoryScreen(opt: const {'personType': '.*', 'accessType': '.*', 'search': '.*'})), + FFRoute(name: 'provisionalHistoryPage', path: '/provisionalHistoryPage', builder: (context, params) => ProvisionalHistoryPage()), 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()), diff --git a/lib/main.dart b/lib/main.dart index 7ada3253..00c6e724 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,25 +5,18 @@ import 'dart:io'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:hub/backend/notifications/notification_service.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/shared/components/molecules/locals/index.dart'; import 'package:hub/shared/helpers/storage/base_storage.dart'; import 'package:hub/shared/helpers/storage/storage_helper.dart'; import 'package:hub/shared/services/deeplink/deep_link_service.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:hub/shared/extensions/string_extensions.dart'; -import 'backend/notifications/firebase_messaging_service.dart'; -import 'features/home/index.dart'; import 'initialization.dart'; -import 'shared/components/molecules/menu/index.dart'; -import 'shared/components/molecules/modules/index.dart'; final GlobalKey navigatorKey = GlobalKey(); @@ -60,7 +53,7 @@ class App extends StatefulWidget { static _AppState of(BuildContext context) => context.findAncestorStateOfType<_AppState>()!; } -class _AppState extends State { +class _AppState extends State { Locale? _locale = FFLocalizations.getStoredLocale(); ThemeMode _themeMode = FlutterFlowTheme.themeMode; late AppStateNotifier _appStateNotifier; @@ -169,7 +162,7 @@ class _AppState extends State { @override void initState() { super.initState(); - + FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); _appStateNotifier = AppStateNotifier.instance; _router = createRouter(_appStateNotifier); @@ -187,38 +180,19 @@ class _AppState extends State { super.dispose(); } - @override Widget build(BuildContext context) { - return MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => MenuBloc( - style: MenuView.list_grid, - item: EnumMenuItem.button, - entries: MenuEntry.getEntriesByType(MenuEntryType.Home), - )..add(MenuEvent()), - ), - BlocProvider( - create: (context) => HomeBloc()..add(HomeEvent()), - ), - BlocProvider( - create: (context) => LocalProfileBloc()..add(LocalProfileEvent()), - ), - ], - child: MaterialApp.router( - key: navigatorKey, - title: 'FRE ACCESS HUB', - builder: builder, - localizationsDelegates: localizationsDelegates, - locale: _locale, - supportedLocales: supportedLocales, - theme: _theme, - darkTheme: _darkTheme, - themeMode: _themeMode, - routerConfig: _router, - ), + return MaterialApp.router( + key: navigatorKey, + title: 'FRE ACCESS HUB', + builder: builder, + localizationsDelegates: localizationsDelegates, + locale: _locale, + supportedLocales: supportedLocales, + theme: _theme, + darkTheme: _darkTheme, + themeMode: _themeMode, + routerConfig: _router, ); } - } diff --git a/lib/shared/components/molecules/menu/presentation/mappers/menu_entry.dart b/lib/shared/components/molecules/menu/presentation/mappers/menu_entry.dart index 02b59717..3b00c98d 100644 --- a/lib/shared/components/molecules/menu/presentation/mappers/menu_entry.dart +++ b/lib/shared/components/molecules/menu/presentation/mappers/menu_entry.dart @@ -61,6 +61,16 @@ class MenuEntry implements BaseModule { route: '/scheduleCompleteVisitPage', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), + MenuEntry( + key: 'FRE-HUB-PROVISIONAL-HISTORY', + icon: Icons.person_search_outlined, + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( + ptText: 'Histórico Provisório', + enText: 'Provisional History', + ), + route: '/provisionalHistoryPage', + types: [MenuEntryType.Home, MenuEntryType.Drawer], + ), MenuEntry( key: 'FRE-HUB-RESIDENTS', icon: Icons.groups, @@ -144,10 +154,7 @@ class MenuEntry implements BaseModule { MenuEntry( key: 'FRE-HUB-PETS', icon: Icons.pets, - name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( - ptText: 'Cadastrar Pets', - enText: 'Pets Register' - ), + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(ptText: 'Cadastrar Pets', enText: 'Pets Register'), route: '/petsPage', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), @@ -162,14 +169,14 @@ class MenuEntry implements BaseModule { types: [MenuEntryType.Home, MenuEntryType.Drawer], ), MenuEntry( - key: 'FRE-HUB-LIBERATIONS', - icon: Icons.how_to_reg_outlined, - name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( - ptText: 'Consultar Liberações', - enText: 'Liberations History', - ), - route: '/liberationHistory', - types: [MenuEntryType.Home, MenuEntryType.Drawer], + key: 'FRE-HUB-LIBERATIONS', + icon: Icons.how_to_reg_outlined, + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( + ptText: 'Consultar Liberações', + enText: 'Liberations History', + ), + route: '/liberationHistory', + types: [MenuEntryType.Home, MenuEntryType.Drawer], ), MenuEntry( key: 'FRE-HUB-MESSAGES', @@ -191,7 +198,6 @@ class MenuEntry implements BaseModule { route: '/aboutProperty', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), - MenuEntry( key: 'FRE-HUB-PEOPLE', icon: Icons.groups, @@ -227,7 +233,4 @@ class MenuEntry implements BaseModule { static List getEntriesByType(MenuEntryType type) { return entries.where((entry) => entry.types.contains(type)).toList(); } - } - - diff --git a/lib/shared/components/molecules/modules/domain/entities/license.dart b/lib/shared/components/molecules/modules/domain/entities/license.dart index d643e322..bd90d50d 100644 --- a/lib/shared/components/molecules/modules/domain/entities/license.dart +++ b/lib/shared/components/molecules/modules/domain/entities/license.dart @@ -1,12 +1,9 @@ - - import 'package:hub/shared/extensions/string_extensions.dart'; import 'package:hub/shared/helpers/storage/base_storage.dart'; import 'package:hub/shared/helpers/storage/storage_helper.dart'; import 'module.dart'; - enum LicenseKeys { messages('FRE-HUB-MESSAGES'), liberations('FRE-HUB-LIBERATIONS'), @@ -20,6 +17,7 @@ enum LicenseKeys { completeSchedule('FRE-HUB-COMPLETE-SCHEDULE'), providerSchedule('FRE-HUB-AGE-PROV-PREST'), deliverySchedule('FRE-HUB-AGE-PROV-DELIVERY'), + provisionalHistory('FRE-HUB-PROVISIONAL-HISTORY'), property('FRE-HUB-ABOUT-PROPERTY'), fastPass('FRE-HUB-FASTPASS'), visitors('FRE-HUB-VISITORS'), @@ -29,14 +27,10 @@ enum LicenseKeys { settings('FRE-HUB-SETTINGS'), logout('FRE-HUB-LOGOUT'); - final String value; const LicenseKeys(this.value); } - - - class License { final List modules; @@ -44,10 +38,9 @@ class License { this.modules, ); - static Future _processWithoutModule(LicenseKeys key) async { - switch(key) { - case LicenseKeys.reservations: + switch (key) { + case LicenseKeys.reservations: return await _precessWpp(); case LicenseKeys.orders: return await _precessWpp(); @@ -68,171 +61,188 @@ class License { static Future _precessWpp() async { final bool whatsapp = await StorageHelper().get(KeychainStorageKey.whatsapp.value).then((v) => v.toBoolean()); - if (whatsapp) return ModuleStatus.active.key; - else return ModuleStatus.inactive.key; + if (whatsapp) + return ModuleStatus.active.key; + else + return ModuleStatus.inactive.key; } + static Future _processProvisional() async { final bool provisional = await StorageHelper().get(KeychainStorageKey.provisional.value).then((v) => v.toBoolean()); - if (provisional) return ModuleStatus.active.key; - else return ModuleStatus.inactive.key; + if (provisional) + return ModuleStatus.active.key; + else + return ModuleStatus.inactive.key; } static Future _processPets() async { final bool pets = await StorageHelper().get(KeychainStorageKey.pets.value).then((v) => v.toBoolean()); - if (pets) return ModuleStatus.active.key; - else return ModuleStatus.inactive.key; + if (pets) + return ModuleStatus.active.key; + else + return ModuleStatus.inactive.key; } - static getKeyByModule(String s) { + static getKeyByModule(String s) {} - } - /// Returns a [License] object with the modules and their status. /// @param isNewVersion: Indica que é sistema novo que possui modularização. static Future getLicense(bool isNewVersionWithModule) async { return License([ - Module( - key: LicenseKeys.messages.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.liberations.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.reservations.value, - display: await _processWithoutModule(LicenseKeys.reservations), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.access.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.openedVisits.value, - display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.vehicles.value, - display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.residents.value, - display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.pets.value, - display: await _processWithoutModule(LicenseKeys.pets), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.orders.value, - display: await _processWithoutModule(LicenseKeys.orders), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.completeSchedule.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.providerSchedule.value, - display: await _processWithoutModule(LicenseKeys.providerSchedule), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.deliverySchedule.value, - display: await _processWithoutModule(LicenseKeys.deliverySchedule), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.fastPass.value, - display: await _processWithoutModule(LicenseKeys.fastPass), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.qrCode.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.visitors.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.property.value, - display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.people.value, - display: isNewVersionWithModule ? ModuleStatus.inactive.key : ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.petsHistory.value, - display: await _processWithoutModule(LicenseKeys.pets), - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.settings.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - Module( - key: LicenseKeys.logout.value, - display: ModuleStatus.active.key, - expirationDate: '', - startDate: '', - quantity: 0, - ), - + Module( + key: LicenseKeys.messages.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.provisionalHistory.value, + display: ModuleStatus.inactive.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.liberations.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.reservations.value, + display: await _processWithoutModule(LicenseKeys.reservations), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.access.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.access.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.openedVisits.value, + display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.vehicles.value, + display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.residents.value, + display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.pets.value, + display: await _processWithoutModule(LicenseKeys.pets), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.orders.value, + display: await _processWithoutModule(LicenseKeys.orders), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.completeSchedule.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.providerSchedule.value, + display: await _processWithoutModule(LicenseKeys.providerSchedule), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.deliverySchedule.value, + display: await _processWithoutModule(LicenseKeys.deliverySchedule), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.fastPass.value, + display: await _processWithoutModule(LicenseKeys.fastPass), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.qrCode.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.visitors.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.property.value, + display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.people.value, + display: isNewVersionWithModule ? ModuleStatus.inactive.key : ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.petsHistory.value, + display: await _processWithoutModule(LicenseKeys.pets), + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.settings.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), + Module( + key: LicenseKeys.logout.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), ]); } } - diff --git a/pubspec.lock b/pubspec.lock index 3dc25f42..db0188e7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.0" file_picker: dependency: "direct main" description: @@ -555,6 +555,11 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_inappwebview: dependency: "direct main" description: @@ -786,6 +791,11 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" glob: dependency: transitive description: @@ -938,6 +948,11 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.1+1" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" intl: dependency: "direct main" description: @@ -1138,6 +1153,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" nested: dependency: transitive description: @@ -1310,10 +1333,10 @@ packages: dependency: transitive description: name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.6" + version: "3.1.5" plugin_platform_interface: dependency: "direct main" description: @@ -1330,6 +1353,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + url: "https://pub.dev" + source: hosted + version: "5.0.2" provider: dependency: "direct main" description: @@ -1607,6 +1638,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" synchronized: dependency: "direct main" description: @@ -1799,6 +1838,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + url: "https://pub.dev" + source: hosted + version: "3.0.3" webview_flutter: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9d2540c4..0448cb01 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -114,11 +114,10 @@ dev_dependencies: flutter_lints: ^5.0.0 image: ^4.3.0 lints: ^5.0.0 - # build_runner: ^2.4.13 - # mockito: ^5.4.4 - # integration_test: - # sdk: flutter - + # build_runner: ^2.4.13 + mockito: ^5.4.4 + integration_test: + sdk: flutter flutter_test: sdk: flutter build_runner: ^2.4.13 diff --git a/test/app_test.dart b/test/app_test.dart new file mode 100644 index 00000000..28e5df89 --- /dev/null +++ b/test/app_test.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:hub/flutter_flow/random_data_util.dart'; +import 'package:hub/initialization.dart'; +import 'package:hub/main.dart'; +import 'package:hub/shared/helpers/storage/base_storage.dart'; +import 'package:hub/shared/helpers/storage/storage_helper.dart'; +import 'package:integration_test/integration_test.dart'; + +late WidgetTester widget; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group( + 'Initialization', + () { + group('Navigation', () { + setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false'))); + testWidgets('Test Welcome', (WidgetTester tester) async { + widget = tester; + await _testWelcome(); + }); + }); + + group('Terms of Use', () { + // Add tests for Terms of Use here + }); + }, + ); + + group('Authentication', () { + group('Sign in', () { + setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false'))); + testWidgets('Test Sign In', (WidgetTester tester) async { + widget = tester; + await _testSignIn(); + }); + }); + group('Sign up', () { + setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false'))); + testWidgets('Test Sign Up', (WidgetTester tester) async { + widget = tester; + await _testSignUp(); + }); + }); + group('Sign Out', () { + // Add tests for Sign Out here + }); + group('Forgot Password', () { + // setUpAll(() async => await initializeApp().then((_) => StorageUtil().isLogged = false)); + // testWidgets('Test Forgot Password', (WidgetTester tester) async { + // widget = tester; + // await _testForgotPassword(); + // }); + }); + }); + group('Localization', () { + // Add tests for Localization here + }); + group('Networking', () { + // Add tests for Networking here + }); + group('Functionality', () { + // Add tests for Functionality here + }); + group('Usability', () { + // Add tests for Usability here + }); + group('Performance', () { + // Add tests for Performance here + }); + group('Security', () { + // Add tests for Security here + }); + group('Accessibility', () { + // Add tests for Accessibility here + }); + group('Compatibility', () { + // Add tests for Compatibility here + }); + group('Internationalization', () { + // Add tests for Internationalization here + }); +} + +Future _testWelcome() async { + await widget.pumpWidget(const App()); + await widget.pumpAndSettle(); + await _navigateToSignIn(); + await _navigateToSignUp(); + await widget.pumpAndSettle(); + await widget.pumpWidget(const App()); + await widget.pumpAndSettle(); + await _navigateToSignUp(); + await _navigateToSignIn(); + await widget.pumpAndSettle(); +} + +Future _testSignIn() async { + await widget.pumpWidget(const App()); + await _navigateToSignIn(); + await _auth({'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678'}); + await _auth({'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'}); +} + +Future _testSignUp() async { + await widget.pumpWidget(const App()); + await _navigateToSignUp(); + + var credentials = {'nameTextFormField': 'app', 'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'}; + await _auth(credentials); + + var name = randomString(7, 7, true, true, true); + var email = '$name@example.com'; + var password = '12345678'; + credentials = {'nameTextFormField': name, 'emailTextFormField': email, 'passwordTextFormField': password}; + await _navigateToSignUp(); + await _auth(credentials); + credentials = {'emailTextFormField': email, 'passwordTextFormField': password}; + await _auth(credentials); +} + +Future _testForgotPassword() async { + await widget.pumpWidget(const App()); + await _navigateToSignIn(); + await _recoveryPassword(); + + var addr = randomString(5, 5, true, true, true); + var credentials = {'recoveryTextFormField': '$addr@exemple.com'}; + await _send(credentials); + + await Future.delayed(const Duration(seconds: 2)); + + await _recoveryPassword(); + credentials = {'recoveryTextFormField': 'email_app@exemple.com'}; + await _send(credentials); +} + +Future _recoveryPassword() async { + await widget.pumpAndSettle(); + final Finder forgotPassword = find.byKey(const ValueKey('ForgotPassword')); + if (forgotPassword.evaluate().isNotEmpty) await widget.tap(forgotPassword); + await widget.ensureVisible(forgotPassword); + await widget.pumpAndSettle(); +} + +Future _navigateBackUsingSystemGesture() async => IntegrationTestWidgetsFlutterBinding.instance.keyboard.isLogicalKeyPressed(LogicalKeyboardKey.escape); +Future _navigateToSignUp() async { + await widget.pumpAndSettle(); + final Finder navToSignUp = find.byKey(const ValueKey('toggleSignUpPage')); + if (navToSignUp.evaluate().isNotEmpty) { + await widget.tap(navToSignUp); + await widget.pumpAndSettle(); + } +} + +Future _navigateToSignIn() async { + await widget.pumpAndSettle(); + final Finder navToSignIn = find.byKey(const ValueKey('toggleSignInPage')); + expect(navToSignIn, findsOneWidget); + if (navToSignIn.evaluate().isNotEmpty) { + await widget.tap(navToSignIn); + await widget.pumpAndSettle(); + } +} + +Future _auth(Map credentials) async { + await _enterCredentials(credentials); + await _submit('SubmitButtonWidget'); +} + +Future _send(Map credentials) async { + await _enterCredentials(credentials); + await _submit('SendButtonWidget'); +} + +Future _enterCredentials(Map credentials) async { + await widget.pumpAndSettle(); + for (var entry in credentials.entries) { + final Finder field = find.byKey(ValueKey(entry.key)); + await widget.pumpAndSettle(); + expect(field, findsOneWidget); + await widget.enterText(field, entry.value); + await widget.pumpAndSettle(); + } + await widget.pumpAndSettle(); +} + +Future _submit(String key) async { + await widget.pumpAndSettle(); + final Finder submitButton = find.byKey(ValueKey(key)); + await widget.pumpAndSettle(); + if (submitButton.evaluate().isNotEmpty) { + await widget.tap(submitButton); + await widget.pumpAndSettle(); + } + + final Finder throwExceptionWidget = find.byKey(const ValueKey('ThrowExceptionWidget')); + await widget.pumpAndSettle(); + if (throwExceptionWidget.evaluate().isNotEmpty) { + await widget.ensureVisible(throwExceptionWidget); + await widget.tap(throwExceptionWidget); + await widget.pumpAndSettle(); + } else { + await _navigateBackUsingSystemGesture(); + } +} diff --git a/test/features/provisional_history_test.dart b/test/features/provisional_history_test.dart new file mode 100644 index 00000000..ab73b3a2 --- /dev/null +++ b/test/features/provisional_history_test.dart @@ -0,0 +1 @@ +void main() {} diff --git a/test/integration_test/app_test.dart b/test/integration_test/app_test.dart deleted file mode 100644 index f5a03e8c..00000000 --- a/test/integration_test/app_test.dart +++ /dev/null @@ -1,210 +0,0 @@ -// import 'package:flutter/material.dart'; -// import 'package:flutter/services.dart'; -// import 'package:flutter_test/flutter_test.dart'; -// import 'package:hub/flutter_flow/random_data_util.dart'; -// import 'package:hub/main.dart'; -// import 'package:hub/shared/helpers/storage/base_storage.dart'; -// import 'package:hub/shared/helpers/storage/storage_helper.dart'; -// import 'package:integration_test/integration_test.dart'; - -// late WidgetTester widget; - -// void main() { -// IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - -// group('Initialization', () { -// group('Navigation', () { -// setUpAll(() async => -// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false'))); -// testWidgets('Test Welcome', (WidgetTester tester) async { -// widget = tester; -// await _testWelcome(); -// }); -// }); - -// group('Terms of Use', () {}); -// }); -// group('Authentication', () { -// group('Sign in', () { -// setUpAll(() async => -// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false'))); -// testWidgets('Test Sign In', (WidgetTester tester) async { -// widget = tester; -// await _testSignIn(); -// }); -// }); -// group('Sign up', () { -// setUpAll(() async => -// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false'))); -// testWidgets('Test Sign Up', (WidgetTester tester) async { -// widget = tester; -// await _testSignUp(); -// }); -// }); -// group('Sign Out', () { -// // Add tests for Sign Out here -// }); -// group('Forgot Password', () { -// // setUpAll(() async => await initializeApp().then((_) => StorageUtil().isLogged = false)); -// // testWidgets('Test Forgot Password', (WidgetTester tester) async { -// // widget = tester; -// // await _testForgotPassword(); -// // }); -// }); -// }); -// group('Localization', () { -// // Add tests for Localization here -// }); -// group('Networking', () { -// // Add tests for Networking here -// }); -// group('Functionality', () { -// // Add tests for Functionality here -// }); -// group('Usability', () { -// // Add tests for Usability here -// }); -// group('Performance', () { -// // Add tests for Performance here -// }); -// group('Security', () { -// // Add tests for Security here -// }); -// group('Accessibility', () { -// // Add tests for Accessibility here -// }); -// group('Compatibility', () { -// // Add tests for Compatibility here -// }); -// group('Internationalization', () { -// // Add tests for Internationalization here -// }); -// } - -// Future _testWelcome() async { -// await widget.pumpWidget(const App()); -// await widget.pumpAndSettle(); -// await _navigateToSignIn(); -// await _navigateToSignUp(); -// await widget.pumpAndSettle(); -// await widget.pumpWidget(const App()); -// await widget.pumpAndSettle(); -// await _navigateToSignUp(); -// await _navigateToSignIn(); -// await widget.pumpAndSettle(); -// } - -// Future _testSignIn() async { -// await widget.pumpWidget(const App()); -// await _navigateToSignIn(); -// await _auth({'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678'}); -// await _auth({'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'}); -// } - -// Future _testSignUp() async { -// await widget.pumpWidget(const App()); -// await _navigateToSignUp(); - -// var credentials = { -// 'nameTextFormField': 'app', -// 'emailTextFormField': 'email_app@exemplo.com', -// 'passwordTextFormField': '12345678' -// }; -// await _auth(credentials); - -// var name = randomString(7, 7, true, true, true); -// var email = '$name@example.com'; -// var password = '12345678'; -// credentials = {'nameTextFormField': name, 'emailTextFormField': email, 'passwordTextFormField': password}; -// await _navigateToSignUp(); -// await _auth(credentials); -// credentials = {'emailTextFormField': email, 'passwordTextFormField': password}; -// await _auth(credentials); -// } - -// Future _testForgotPassword() async { -// await widget.pumpWidget(const App()); -// await _navigateToSignIn(); -// await _recoveryPassword(); - -// var addr = randomString(5, 5, true, true, true); -// var credentials = {'recoveryTextFormField': '$addr@exemple.com'}; -// await _send(credentials); - -// await Future.delayed(const Duration(seconds: 2)); - -// await _recoveryPassword(); -// credentials = {'recoveryTextFormField': 'email_app@exemple.com'}; -// await _send(credentials); -// } - -// Future _recoveryPassword() async { -// await widget.pumpAndSettle(); -// final Finder forgotPassword = find.byKey(const ValueKey('ForgotPassword')); -// if (forgotPassword.evaluate().isNotEmpty) await widget.tap(forgotPassword); -// await widget.ensureVisible(forgotPassword); -// await widget.pumpAndSettle(); -// } - -// Future _navigateBackUsingSystemGesture() async => -// IntegrationTestWidgetsFlutterBinding.instance.keyboard.isLogicalKeyPressed(LogicalKeyboardKey.escape); -// Future _navigateToSignUp() async { -// await widget.pumpAndSettle(); -// final Finder navToSignUp = find.byKey(const ValueKey('toggleSignUpPage')); -// if (navToSignUp.evaluate().isNotEmpty) { -// await widget.tap(navToSignUp); -// await widget.pumpAndSettle(); -// } -// } - -// Future _navigateToSignIn() async { -// await widget.pumpAndSettle(); -// final Finder navToSignIn = find.byKey(const ValueKey('toggleSignInPage')); -// expect(navToSignIn, findsOneWidget); -// if (navToSignIn.evaluate().isNotEmpty) { -// await widget.tap(navToSignIn); -// await widget.pumpAndSettle(); -// } -// } - -// Future _auth(Map credentials) async { -// await _enterCredentials(credentials); -// await _submit('SubmitButtonWidget'); -// } - -// Future _send(Map credentials) async { -// await _enterCredentials(credentials); -// await _submit('SendButtonWidget'); -// } - -// Future _enterCredentials(Map credentials) async { -// await widget.pumpAndSettle(); -// for (var entry in credentials.entries) { -// final Finder field = find.byKey(ValueKey(entry.key)); -// await widget.pumpAndSettle(); -// expect(field, findsOneWidget); -// await widget.enterText(field, entry.value); -// await widget.pumpAndSettle(); -// } -// await widget.pumpAndSettle(); -// } - -// Future _submit(String key) async { -// await widget.pumpAndSettle(); -// final Finder submitButton = find.byKey(ValueKey(key)); -// await widget.pumpAndSettle(); -// if (submitButton.evaluate().isNotEmpty) { -// await widget.tap(submitButton); -// await widget.pumpAndSettle(); -// } - -// final Finder throwExceptionWidget = find.byKey(const ValueKey('ThrowExceptionWidget')); -// await widget.pumpAndSettle(); -// if (throwExceptionWidget.evaluate().isNotEmpty) { -// await widget.ensureVisible(throwExceptionWidget); -// await widget.tap(throwExceptionWidget); -// await widget.pumpAndSettle(); -// } else { -// await _navigateBackUsingSystemGesture(); -// } -// }