diff --git a/lib/actions/actions.dart b/lib/actions/actions.dart index 1d454af9..657dbcb2 100644 --- a/lib/actions/actions.dart +++ b/lib/actions/actions.dart @@ -416,25 +416,47 @@ Future checkLocals({ } } -Future answersRequest(BuildContext context, String? ref, String? task, +Future answersRequest(BuildContext context, String? ref, String? task, String? response, String? id) async { - ApiCallResponse? respondeSolicitacaoCall; + try { + ApiCallResponse? respondeSolicitacaoCall; - respondeSolicitacaoCall = await PhpGroup.respondeSolicitacaoCall.call( - userUUID: AppState().userUUID, - devUUID: AppState().devUUID, - cliUUID: AppState().cliUUID, - atividade: 'respondeSolicitacao', - referencia: ref, - tarefa: task, - resposta: response, - idVisitante: id, - ); + respondeSolicitacaoCall = await PhpGroup.respondeSolicitacaoCall.call( + userUUID: AppState().userUUID, + devUUID: AppState().devUUID, + cliUUID: AppState().cliUUID, + atividade: 'respondeSolicitacao', + referencia: ref, + tarefa: task, + resposta: response, + idVisitante: id, + ); + respondeSolicitacaoCall = await PhpGroup.respondeSolicitacaoCall.call( + userUUID: FFAppState().userUUID, + devUUID: FFAppState().devUUID, + cliUUID: FFAppState().cliUUID, + atividade: 'respondeSolicitacao', + referencia: ref, + tarefa: task, + resposta: response, + idVisitante: id, + ); - if (respondeSolicitacaoCall.statusCode == 200) { - return !respondeSolicitacaoCall.jsonBody['error']; - } else { - return false; + if (respondeSolicitacaoCall.statusCode == 200) { + if (!respondeSolicitacaoCall.jsonBody['error']) { + return ''; + } else { + return respondeSolicitacaoCall.jsonBody['error_msg'].toString(); + } + } else { + return FFLocalizations.of(context).getVariableText( + ptText: 'Falha ao Responder Solicitação', + enText: 'Failed to Response Request'); + } + } catch (e, s) { + return FFLocalizations.of(context).getVariableText( + ptText: 'Falha ao Responder Solicitação', + enText: 'Failed to Response Request'); } } diff --git a/lib/components/atomic_components/shared_components_atoms/toast.dart b/lib/components/atomic_components/shared_components_atoms/toast.dart new file mode 100644 index 00000000..aad47149 --- /dev/null +++ b/lib/components/atomic_components/shared_components_atoms/toast.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class ToastUtil { + static void showToast({ + required String message, + ToastGravity gravity = ToastGravity.BOTTOM, + Toast toastLength = Toast.LENGTH_SHORT, + Color backgroundColor = Colors.black, + Color textColor = Colors.white, + double fontSize = 16.0, + }) { + Fluttertoast.showToast( + msg: message, + toastLength: toastLength, + gravity: gravity, + backgroundColor: backgroundColor, + textColor: textColor, + fontSize: fontSize, + ); + } +} diff --git a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart index fef66fd1..dbc1d87e 100644 --- a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart +++ b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart @@ -102,8 +102,8 @@ class _CardItemTemplateComponentWidgetState borderRadius: BorderRadius.circular(8.0), ), child: Container( - width: 350.0, - height: 115.0, + width: 350, + height: 125, decoration: BoxDecoration( color: FlutterFlowTheme.of(context).primaryBackground, ), @@ -147,7 +147,6 @@ class _CardItemTemplateComponentWidgetState fontFamily: FlutterFlowTheme.of(context) .bodyMediumFamily, - fontSize: screenWidth * 0.025, letterSpacing: 0.0, fontWeight: FontWeight.bold, useGoogleFonts: GoogleFonts @@ -158,12 +157,10 @@ class _CardItemTemplateComponentWidgetState .bodyMediumFamily), color: FlutterFlowTheme.of(context) - .customColor6, + .primaryText, ), ), - const SizedBox( - width: - 5.0), // Espaçamento entre o label e o valor + const SizedBox(width: 3.0), // Espaçamento entre o label e o valor Flexible( child: Text( value, diff --git a/lib/components/templates_components/details_component/details_component_action.dart b/lib/components/templates_components/details_component/details_component_action.dart index c03d2bb6..8fb007f2 100644 --- a/lib/components/templates_components/details_component/details_component_action.dart +++ b/lib/components/templates_components/details_component/details_component_action.dart @@ -11,18 +11,14 @@ import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart'; +import 'package:hub/shared/utils/validator_util.dart'; import 'package:rxdart/rxdart.dart'; import 'package:share_plus/share_plus.dart'; -Widget buildDetails( - dynamic visitaWrapItem, - BuildContext context, - Future Function(BuildContext, int, int, String, String)? - changeStatusAction) { +Widget buildDetails(dynamic visitaWrapItem, BuildContext context, Future Function(BuildContext, int, int, String, String)? changeStatusAction) { return DetailsComponentWidget( buttons: [ - if (getStatus(visitaWrapItem['VAW_STATUS']) == - status.active) // REJECT ACTION + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.active) // REJECT ACTION FFButtonWidget( text: FFLocalizations.of(context).getVariableText( ptText: 'Cancelar', @@ -171,9 +167,9 @@ URL do Convite: https://visita.freaccess.com.br/${visitaWrapItem['VAW_ID']}/${vi ), ], labelsHashMap: Map.from({ - 'Nome': visitaWrapItem['VTE_NOME'] ?? '', - 'Inicio': visitaWrapItem['VAW_DTINICIO'] ?? '', - 'Fim': visitaWrapItem['VAW_DTFIM'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Nome", enText: "Name")}:': visitaWrapItem['VTE_NOME'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Inicio", enText: "Start")}:': visitaWrapItem['VAW_DTINICIO'] != '' && visitaWrapItem['VAW_DTINICIO'] != null ? ValidatorUtil.toLocalDateTime('yyyy-MM-dd HH:mm:ss', visitaWrapItem['VAW_DTINICIO']) : '', + '${FFLocalizations.of(context).getVariableText(ptText: "Fim", enText: "End")}:': visitaWrapItem['VAW_DTFIM'] != '' && visitaWrapItem['VAW_DTFIM'] != null ? ValidatorUtil.toLocalDateTime('yyyy-MM-dd HH:mm:ss', visitaWrapItem['VAW_DTFIM']) : '', }), imagePath: 'https://freaccess.com.br/freaccess/getImage.php?cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${visitaWrapItem['VTE_DOCUMENTO'] ?? ''}&tipo=E', diff --git a/lib/components/templates_components/details_component/details_component_widget.dart b/lib/components/templates_components/details_component/details_component_widget.dart index 18ea5b4e..ffaf25f6 100644 --- a/lib/components/templates_components/details_component/details_component_widget.dart +++ b/lib/components/templates_components/details_component/details_component_widget.dart @@ -265,8 +265,11 @@ class _DetailsComponentWidgetState extends State { SizedBox(height: MediaQuery.of(context).size.height * 0.02), if (widget.buttons .isNotEmpty) // Adicione este SizedBox com a altura desejada - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + OverflowBar( + overflowAlignment: OverflowBarAlignment.center, + overflowSpacing: 2, + spacing: 2, + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: widget.buttons, ), SizedBox(height: MediaQuery.of(context).size.height * 0.02), diff --git a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_model.dart b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_model.dart index 45613006..35178029 100644 --- a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_model.dart +++ b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_model.dart @@ -4,6 +4,7 @@ import 'dart:developer'; import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart'; import 'package:hub/custom_code/actions/convert_image_file_to_base64.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; +import 'package:hub/shared/utils/validator_util.dart'; import '/backend/api_requests/api_calls.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -12,15 +13,13 @@ import 'package:flutter/material.dart'; import 'regisiter_vistor_template_component_widget.dart'; -class RegisiterVistorTemplateComponentModel - extends FlutterFlowModel { +class RegisiterVistorTemplateComponentModel extends FlutterFlowModel { /// State fields for stateful widgets in this page. Timer? _debounceTimer; final unfocusNode = FocusNode(); bool isDataUploading = false; - FFUploadedFile uploadedLocalFile = - FFUploadedFile(bytes: Uint8List.fromList([])); + FFUploadedFile uploadedLocalFile = FFUploadedFile(bytes: Uint8List.fromList([])); void debounce(Function() fn, Duration time) { if (_debounceTimer != null) { @@ -98,13 +97,7 @@ class RegisiterVistorTemplateComponentModel TextEditingController? textController4; String? Function(BuildContext, String?)? textController4Validator; String? _textController4Validator(BuildContext context, String? val) { - if (val == null || val.isEmpty) { - return FFLocalizations.of(context).getVariableText( - enText: 'This field is required', - ptText: 'Este campo é obrigatório', - ); - } - if (!val.contains('@') || !val.contains('.')) { + if (val != null && val.isNotEmpty && ValidatorUtil.isValidEmail(val) == false) { return FFLocalizations.of(context).getVariableText( enText: 'Invalid email', ptText: 'Email inválido', diff --git a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart index eb96c68f..5eaab5ad 100644 --- a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart +++ b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart @@ -1,7 +1,9 @@ import 'dart:developer'; +import 'package:easy_debounce/easy_debounce.dart'; import 'package:flutter/services.dart'; import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/validator_util.dart'; import 'package:json_path/fun_sdk.dart'; import 'package:rxdart/rxdart.dart'; @@ -48,13 +50,11 @@ class _RegisiterVistorTemplateComponentWidgetState visitorAlreadyRegistered = BehaviorSubject.seeded(false); - _model = - createModel(context, () => RegisiterVistorTemplateComponentModel()); + _model = createModel(context, () => RegisiterVistorTemplateComponentModel()); _model.textController1 ??= TextEditingController(); _model.textFieldFocusNode1 ??= FocusNode(); - log('doc: ${widget.doc}'); _model.textController2 ??= TextEditingController(); _model.textFieldFocusNode2 ??= FocusNode(); _model.textController2?.addListener(_onTextChanged); @@ -87,19 +87,15 @@ class _RegisiterVistorTemplateComponentWidgetState return false; } - if (_model.textController1.text.isEmpty || - _model.textController1.text == '') { + if (_model.textController1.text.isEmpty || _model.textController1.text == '') { return false; } - if (_model.dropDownValue == null || - _model.dropDownValue!.isEmpty || - _model.dropDownValue == '') { + if (_model.dropDownValue == null || _model.dropDownValue!.isEmpty || _model.dropDownValue == '') { return false; } - if (_model.textController2.text.isEmpty || - _model.textController2.text == '') { + if (_model.textController2.text.isEmpty || _model.textController2.text == '') { return false; } @@ -107,6 +103,10 @@ class _RegisiterVistorTemplateComponentWidgetState return false; } + if (_model.textController4.text.isNotEmpty && _model.textController4.text != '' && ValidatorUtil.isValidEmail(_model.textController4.text) == false) { + return false; + } + return true; } @@ -129,7 +129,6 @@ class _RegisiterVistorTemplateComponentWidgetState ), child: SingleChildScrollView( child: Form( - // key: UniqueKey(), autovalidateMode: AutovalidateMode.onUserInteraction, child: Column( mainAxisSize: MainAxisSize.min, @@ -138,8 +137,7 @@ class _RegisiterVistorTemplateComponentWidgetState Align( alignment: const AlignmentDirectional(-1.0, 0.0), child: Padding( - padding: const EdgeInsetsDirectional.fromSTEB( - 20.0, 30.0, 0.0, 15.0), + padding: const EdgeInsetsDirectional.fromSTEB(20.0, 0.0, 0.0, 15.0), child: Text( FFLocalizations.of(context).getText( 'zazj5d8b' /* Preencha o formulário com os d... */, @@ -163,7 +161,7 @@ class _RegisiterVistorTemplateComponentWidgetState controller: _model.textController2, focusNode: _model.textFieldFocusNode2, autovalidateMode: AutovalidateMode.onUserInteraction, - autofocus: false, + autofocus: true, textCapitalization: TextCapitalization.none, autofillHints: const [AutofillHints.password], keyboardType: TextInputType.number, @@ -297,7 +295,14 @@ class _RegisiterVistorTemplateComponentWidgetState controller: _model.textController1, autovalidateMode: AutovalidateMode.onUserInteraction, focusNode: _model.textFieldFocusNode1, - autofocus: false, + onChanged: (_) => + EasyDebounce.debounce( + '_model.textFieldFocusNode1', + const Duration( + milliseconds: 500), + () => setState(() {}), + ), + autofocus: true, textInputAction: TextInputAction.next, obscureText: false, decoration: InputDecoration( @@ -368,8 +373,7 @@ class _RegisiterVistorTemplateComponentWidgetState ), maxLines: null, keyboardType: TextInputType.name, - validator: - _model.textController1Validator.asValidator(context), + validator: _model.textController1Validator.asValidator(context), ), ), Padding( @@ -455,160 +459,162 @@ class _RegisiterVistorTemplateComponentWidgetState ], ), ), - Builder( - builder: (context) { - if ((_model.uploadedLocalFile.bytes?.isNotEmpty ?? false)) { - return InkWell( - splashColor: Colors.transparent, - focusColor: Colors.transparent, - hoverColor: Colors.transparent, - highlightColor: Colors.transparent, - onTap: () async { - setState(() { - _model.isDataUploading = false; - _model.uploadedLocalFile = - FFUploadedFile(bytes: Uint8List.fromList([])); - }); - }, - child: ClipRRect( - borderRadius: BorderRadius.circular(8.0), - child: Image.memory( - _model.uploadedLocalFile.bytes ?? - Uint8List.fromList([]), - width: 300.0, - height: 200.0, - fit: BoxFit.cover, + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0), + child: Builder( + builder: (context) { + if ((_model.uploadedLocalFile.bytes?.isNotEmpty ?? false)) { + return InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () async { + setState(() { + _model.isDataUploading = false; + _model.uploadedLocalFile = + FFUploadedFile(bytes: Uint8List.fromList([])); + }); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.memory( + _model.uploadedLocalFile.bytes ?? + Uint8List.fromList([]), + width: 300.0, + height: 200.0, + fit: BoxFit.cover, + ), ), - ), - ); - } else { - return Stack( - children: [ - Align( - alignment: const AlignmentDirectional(0.01, 0.0), - child: FFButtonWidget( - onPressed: () async { - final selectedMedia = - await selectMediaWithSourceBottomSheet( - context: context, - // maxWidth: 300.00, - // maxHeight: 300.00, - imageQuality: 100, - allowPhoto: true, - includeDimensions: true, - ); - if (selectedMedia != null) { - // && - // selectedMedia.every((m) => - // validateFileFormat( - // m.storagePath, context))) { - setState(() => _model.isDataUploading = true); - var selectedUploadedFiles = - []; + ); + } else { + return Stack( + children: [ + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + final selectedMedia = + await selectMediaWithSourceBottomSheet( + context: context, + // maxWidth: 300.00, + // maxHeight: 300.00, + imageQuality: 100, + allowPhoto: true, + includeDimensions: true, + ); + if (selectedMedia != null) { + // && + // selectedMedia.every((m) => + // validateFileFormat( + // m.storagePath, context))) { + setState(() => _model.isDataUploading = true); + var selectedUploadedFiles = + []; - try { - showUploadMessage( - context, - 'Uploading file...', - showLoading: true, - ); - selectedUploadedFiles = selectedMedia - .map((m) => FFUploadedFile( - name: - m.storagePath.split('/').last, - bytes: m.bytes, - height: m.dimensions?.height, - width: m.dimensions?.width, - // blurHash: m.blurHash, - )) - .toList(); - } finally { - ScaffoldMessenger.of(context) - .hideCurrentSnackBar(); - _model.isDataUploading = false; + try { + showUploadMessage( + context, + 'Uploading file...', + showLoading: true, + ); + selectedUploadedFiles = selectedMedia + .map((m) => FFUploadedFile( + name: + m.storagePath.split('/').last, + bytes: m.bytes, + height: m.dimensions?.height, + width: m.dimensions?.width, + // blurHash: m.blurHash, + )) + .toList(); + } finally { + ScaffoldMessenger.of(context) + .hideCurrentSnackBar(); + _model.isDataUploading = false; + } + if (selectedUploadedFiles.length == + selectedMedia.length) { + setState(() { + _model.uploadedLocalFile = + selectedUploadedFiles.first; + }); + showUploadMessage(context, 'Success!'); + } else { + setState(() {}); + showUploadMessage( + context, 'Failed to upload data'); + return; + } } - if (selectedUploadedFiles.length == - selectedMedia.length) { - setState(() { - _model.uploadedLocalFile = - selectedUploadedFiles.first; - }); - showUploadMessage(context, 'Success!'); - } else { - setState(() {}); - showUploadMessage( - context, 'Failed to upload data'); - return; - } - } - }, - text: '', - icon: Icon( - Icons.photo_camera, - color: FlutterFlowTheme.of(context).accent1, - size: 30.0, - ), - options: FFButtonOptions( - width: 300.0, - height: 80.0, - padding: const EdgeInsetsDirectional.fromSTEB( - 0.0, 0.0, 0.0, 0.0), - iconPadding: - const EdgeInsetsDirectional.fromSTEB( - 14.0, 0.0, 0.0, 20.0), - color: FlutterFlowTheme.of(context) - .primaryBackground, - textStyle: FlutterFlowTheme.of(context) - .titleSmall - .override( - fontFamily: FlutterFlowTheme.of(context) - .titleSmallFamily, - color: FlutterFlowTheme.of(context) - .primaryText, - fontSize: 16.0, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap() - .containsKey( - FlutterFlowTheme.of(context) - .titleSmallFamily), - ), - borderSide: BorderSide( + }, + text: '', + icon: Icon( + Icons.photo_camera, color: FlutterFlowTheme.of(context).accent1, - width: 0.2, + size: 30.0, + ), + options: FFButtonOptions( + width: double.infinity, + height: 120.0, + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 20.0), + iconPadding: + const EdgeInsetsDirectional.fromSTEB( + 14.0, 0.0, 0.0, 20.0), + color: FlutterFlowTheme.of(context) + .primaryBackground, + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: FlutterFlowTheme.of(context) + .titleSmallFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + fontSize: 16.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .titleSmallFamily), + ), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).accent1, + width: 0.2, + ), + borderRadius: BorderRadius.circular(8.0), ), - borderRadius: BorderRadius.circular(8.0), ), ), - ), - Align( - alignment: const AlignmentDirectional(0.0, 0.0), - child: Padding( - padding: const EdgeInsetsDirectional.fromSTEB( - 0.0, 50.0, 0.0, 0.0), - child: Text( - FFLocalizations.of(context).getText( - 'p4ftwxcy' /* Clique para adicionar a foto p... */, + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 10.0, 65.0, 10.0, 0.0), + child: Text( + FFLocalizations.of(context).getText( + 'p4ftwxcy' /* Clique para adicionar a foto p... */, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + color: FlutterFlowTheme.of(context) + .primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap() + .containsKey( + FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), ), - style: FlutterFlowTheme.of(context) - .bodyMedium - .override( - fontFamily: FlutterFlowTheme.of(context) - .bodyMediumFamily, - color: FlutterFlowTheme.of(context) - .primaryText, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap() - .containsKey( - FlutterFlowTheme.of(context) - .bodyMediumFamily), - ), ), ), - ), - ], - ); - } - }, + ], + ); + } + }, + ), ), Align( alignment: const AlignmentDirectional(-1.0, 0.0), @@ -722,7 +728,14 @@ class _RegisiterVistorTemplateComponentWidgetState controller: _model.textController4, focusNode: _model.textFieldFocusNode4, autovalidateMode: AutovalidateMode.onUserInteraction, - autofocus: false, + autofocus: true, + onChanged: (_) => + EasyDebounce.debounce( + '_model.textFieldFocusNode4', + const Duration( + milliseconds: 500), + () => setState(() {}), + ), textInputAction: TextInputAction.done, obscureText: false, decoration: InputDecoration( @@ -792,13 +805,11 @@ class _RegisiterVistorTemplateComponentWidgetState FlutterFlowTheme.of(context).bodyMediumFamily), ), keyboardType: TextInputType.emailAddress, - // validator: - // _model.textController4Validator.asValidator(context), + validator: _model.textController4Validator.asValidator(context), ), ), Padding( - padding: - const EdgeInsetsDirectional.fromSTEB(0.0, 65.0, 0.0, 0.0), + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 65.0, 0.0, 0.0), child: FFButtonWidget( onPressed: _isFormValid(context) ? () async { diff --git a/lib/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_widget.dart b/lib/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_widget.dart index b661bfa8..d3be31a3 100644 --- a/lib/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_widget.dart +++ b/lib/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_widget.dart @@ -2,6 +2,7 @@ import 'dart:developer'; import 'package:flutter/services.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; +import 'package:hub/components/atomic_components/shared_components_atoms/toast.dart'; import 'package:hub/components/molecular_components/visitor_not_found_component/visitor_not_found_component_widget.dart'; import 'package:hub/components/templates_components/visitor_details_modal_template_component/visitor_details_modal_template_component_widget.dart'; import 'package:hub/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_model.dart'; @@ -64,12 +65,12 @@ class _VisitorSearchModalTemplateComponentWidgetState context.watch(); return Padding( - padding: const EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 0.0, 0.0), + padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), child: Container( width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: FlutterFlowTheme.of(context).primaryBackground, - borderRadius: const BorderRadius.only( + decoration: const BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.only( bottomLeft: Radius.circular(0.0), bottomRight: Radius.circular(0.0), topLeft: Radius.circular(15.0), @@ -78,11 +79,19 @@ class _VisitorSearchModalTemplateComponentWidgetState ), child: Column( mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, children: [ + Container( + width: 40, + height: 5, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(10), + ), + ), Padding( padding: - const EdgeInsetsDirectional.fromSTEB(16.0, 10.0, 16.0, 0.0), + const EdgeInsetsDirectional.fromSTEB(16.0, 25.0, 16.0, 0.0), child: TextFormField( controller: _model.textController, focusNode: _model.textFieldFocusNode, @@ -223,12 +232,14 @@ class _VisitorSearchModalTemplateComponentWidgetState builder: (context) { final visitor = _model.visitors.map((e) => e).toList(); + final doc = _model.docs.map((e) => e).toList(); return ListView.builder( padding: EdgeInsets.zero, scrollDirection: Axis.vertical, itemCount: visitor.length, itemBuilder: (context, visitorIndex) { final visitorItem = visitor[visitorIndex]; + final docItem = doc[visitorIndex]; return Padding( padding: const EdgeInsetsDirectional.fromSTEB( 0.0, 0.0, 0.0, 1.0), @@ -237,38 +248,6 @@ class _VisitorSearchModalTemplateComponentWidgetState focusColor: Colors.transparent, hoverColor: Colors.transparent, highlightColor: Colors.transparent, - onTap: () async { - // await showModalBottomSheet( - // isScrollControlled: true, - // enableDrag: true, - // isDismissible: true, - // context: context, - // builder: (context) { - // return Padding( - // padding: - // MediaQuery.viewInsetsOf(context), - // child: SizedBox( - // height: 610.0, - // child: - // VisitorDetailsModalTemplateComponentWidget( - // visitorImageURL: - // "https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( - // visitorItem, - // r'''$.VTE_DOCUMENTO''', - // ).toString()}&tipo=E", - // visitorEmail: '', - // visitorName: getJsonField( - // visitorItem, - // r'''$.VTE_NOME''', - // )?.toString(), - // visitorPhone: '', - // visitorType: '', - // ), - // ), - // ); - // }, - // ).then((value) => safeSetState(() {})); - }, child: Container( width: 100.0, decoration: BoxDecoration( @@ -356,6 +335,7 @@ class _VisitorSearchModalTemplateComponentWidgetState onPressed: () async { _model.removeFromVisitors( visitorItem); + _model.removeFromDocs(docItem); safeSetState(() {}); }, ), @@ -479,12 +459,21 @@ class _VisitorSearchModalTemplateComponentWidgetState PhpGroup.getVisitorByDocCall .vistanteId((_model.getVisitorByDoc?.jsonBody ?? '')) != null) { - _model.addToVisitors(PhpGroup.getVisitorByDocCall.visitante( - (_model.getVisitorByDoc?.jsonBody ?? ''), - )); - safeSetState(() {}); - _model.addToDocs(_model.textController.text); - safeSetState(() {}); + String newDoc = _model.textController.text; + bool existDoc = _model.docs.contains(newDoc); + if (existDoc == false) { + _model.addToVisitors(PhpGroup.getVisitorByDocCall.visitante( + (_model.getVisitorByDoc?.jsonBody ?? ''), + )); + safeSetState(() {}); + _model.addToDocs(_model.textController.text); + safeSetState(() {}); + } else if (existDoc == true) { + ToastUtil.showToast( + message: FFLocalizations.of(context).getVariableText( + ptText: 'Visitante já adicionado!', + enText: 'Visitor already added!')); + } } else { await showAdaptiveDialog( useSafeArea: true, diff --git a/lib/flutter_flow/flutter_flow_util.dart b/lib/flutter_flow/flutter_flow_util.dart index 5c5239b9..4aa04b61 100644 --- a/lib/flutter_flow/flutter_flow_util.dart +++ b/lib/flutter_flow/flutter_flow_util.dart @@ -184,6 +184,7 @@ Theme wrapInMaterialTimePickerTheme( required Color headerForegroundColor, required TextStyle headerTextStyle, required Color pickerBackgroundColor, + required Color pickerDialForegroundColor, required Color pickerForegroundColor, required Color selectedDateTimeBackgroundColor, required Color selectedDateTimeForegroundColor, @@ -265,7 +266,7 @@ Theme wrapInMaterialTimePickerTheme( dialTextColor: WidgetStateColor.resolveWith((states) => states.contains(WidgetState.selected) ? selectedDateTimeForegroundColor - : pickerForegroundColor), + : pickerDialForegroundColor), dayPeriodBorderSide: BorderSide( color: pickerForegroundColor, ), diff --git a/lib/pages/liberation_history/liberation_history_widget.dart b/lib/pages/liberation_history/liberation_history_widget.dart index 3ab52e15..c3070287 100644 --- a/lib/pages/liberation_history/liberation_history_widget.dart +++ b/lib/pages/liberation_history/liberation_history_widget.dart @@ -1,24 +1,21 @@ -// import 'dart:js_interop'; - import 'dart:developer'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hub/actions/actions.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; - import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/components/templates_components/details_component/details_component_widget.dart'; -import 'package:hub/flutter_flow/custom_functions.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; - -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_spinkit/flutter_spinkit.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hub/pages/liberation_history/liberation_history_model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/log_util.dart'; +import 'package:hub/shared/utils/validator_util.dart'; import 'package:provider/provider.dart'; class LiberationHistoryWidget extends StatefulWidget { @@ -30,421 +27,385 @@ class LiberationHistoryWidget extends StatefulWidget { } class _LiberationHistoryWidgetState extends State { - late LiberationHistoryModel _model; - final scaffoldKey = GlobalKey(); + bool _hasData = false; + bool _loading = false; + + late Future _requestFuture; + List _requestWrap = []; @override void initState() { - super.initState(); - _model = createModel(context, () => LiberationHistoryModel()); + _requestFuture = _fetchRequests(); - _model.textController ??= TextEditingController(); - _model.textFieldFocusNode ??= FocusNode(); + super.initState(); } @override void dispose() { - _model.dispose(); - super.dispose(); } void onUpdate(BuildContext context) { - _model.clearGetLiberationsCache(); safeSetState(() {}); } + String _imagePath(dynamic request) { + return 'https://freaccess.com.br/freaccess/getImage.php?cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${request['VTE_ID'] ?? ''}&tipo=E'; + } + + Map _labelsHashMap(dynamic request, bool details) { + return Map.from({ + '${FFLocalizations.of(context).getVariableText(ptText: 'Nome', enText: 'Name')}:': + request['VTE_NOME'], + '${FFLocalizations.of(context).getVariableText(ptText: 'Dt. Envio', enText: 'Date Send')}:': + request['NOT_DTENVIO'] != null + ? ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd HH:mm:ss', request['NOT_DTENVIO']) + : '', + '${FFLocalizations.of(context).getVariableText(ptText: 'Motivo', enText: 'Reason')}:': + request['NOT_MOTIVO'], + if (details == true) + '${FFLocalizations.of(context).getVariableText(ptText: 'Mensagem', enText: 'Message')}:': + request['NOT_MSGENVIO'], + }); + } + + Map _statusHashMap(dynamic request) { + return Map.from({ + if (request['NOT_STATUS'] == 'L') + FFLocalizations.of(context).getVariableText( + ptText: 'Finalizado', + enText: 'Finished'): FlutterFlowTheme.of(context).success + else if (request['NOT_STATUS'] == 'B') + FFLocalizations.of(context).getVariableText( + ptText: 'Bloqueado', + enText: 'Blocked'): FlutterFlowTheme.of(context).error + else + FFLocalizations.of(context).getVariableText( + ptText: 'Ativo', + enText: 'Active'): FlutterFlowTheme.of(context).warning + }); + } + @override Widget build(BuildContext context) { - context.watch(); - return GestureDetector( - onTap: () => _model.unfocusNode.canRequestFocus - ? FocusScope.of(context).requestFocus(_model.unfocusNode) - : FocusScope.of(context).unfocus(), - child: Scaffold( - key: scaffoldKey, - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: appBarLiberationHistoryPage(context), - body: bodyLiberationHistoryPage(context, _model), + context.watch(); + return Scaffold( + key: scaffoldKey, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + appBar: _appBar(context), + body: _body(context), + ); + } + + PreferredSizeWidget _appBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + forceMaterialTransparency: true, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: FlutterFlowTheme.of(context).primaryText, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + FFLocalizations.of(context).getText( + '784f83pc' /* Histórico de Liberação */, + ), + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: 'Nunito', + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 17.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'), + ), + ), + actions: const [], + centerTitle: true, + elevation: 0.0, + ); + } + + Widget _body(BuildContext context) { + return SafeArea( + top: true, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (_hasData == false && _loading == false && _requestWrap.isEmpty) + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Center( + child: Text(FFLocalizations.of(context).getVariableText( + ptText: "Nenhuma solicitação encontrada!", + enText: "No visit found")), + ) + ], + ), + ) + else if (_hasData == true && + _loading == false && + _requestWrap.isNotEmpty) + Expanded(child: _listItems(context)), + if (_loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ], ), ); } -} -PreferredSizeWidget appBarLiberationHistoryPage(BuildContext context) { - return AppBar( - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - forceMaterialTransparency: true, - leading: FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.keyboard_arrow_left, - color: FlutterFlowTheme.of(context).primaryText, - size: 30.0, - ), - onPressed: () async { - context.pop(); - }, - ), - title: Text( - FFLocalizations.of(context).getText( - '784f83pc' /* Histórico de Liberação */, - ), - style: FlutterFlowTheme.of(context).headlineMedium.override( - fontFamily: 'Nunito', - color: FlutterFlowTheme.of(context).primaryText, - fontSize: 17.0, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'), - ), - ), - actions: const [], - centerTitle: true, - elevation: 0.0, - ); -} - -Widget bodyLiberationHistoryPage( - BuildContext context, LiberationHistoryModel _model) { - return SafeArea( - top: true, - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - searchBarContainer(context, _model), - Expanded(child: liberationDynamicListView(context, _model)), - ].addToStart(const SizedBox(height: 0)), - ), - ); -} - -Widget searchBarContainer(BuildContext context, LiberationHistoryModel _model) { - return Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsetsDirectional.fromSTEB(8.0, 8.0, 8.0, 8.0), - child: SizedBox( - width: 300.0, - height: 40.0, - child: TextFormField( - controller: _model.textController, - focusNode: _model.textFieldFocusNode, - autofocus: false, - obscureText: false, - decoration: InputDecoration( - isDense: true, - labelText: FFLocalizations.of(context).getText( - 'dy0mx15f' /* 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: 2.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primary, - width: 2.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).error, - width: 2.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - focusedErrorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).error, - width: 2.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - filled: true, - fillColor: FlutterFlowTheme.of(context).alternate, - prefixIcon: Icon( - Icons.search_sharp, - color: FlutterFlowTheme.of(context).primaryText, - ), - ), - 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), - ), - ), - ), - ], - ), - ].addToStart(const SizedBox(height: 0)), - ); -} - -Widget liberationDynamicListView( - BuildContext context, - LiberationHistoryModel _model, -) { - return Container( - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration(), - child: StreamBuilder( - stream: _model.getLiberations( - requestFn: () => PhpGroup.getLiberationsCall.call( - devUUID: AppState().devUUID, - userUUID: AppState().userUUID, - cliID: AppState().cliUUID, - atividade: 'getSolicitacoes', - ), - ), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return Center( - child: SizedBox( - width: 50.0, - height: 50.0, - child: SpinKitCircle( - color: FlutterFlowTheme.of(context).primary, - size: 50.0, - ), - ), + Widget _listItems(BuildContext context) { + return Container( + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration(), + child: FutureBuilder( + future: _requestFuture, + builder: (context, snapshot) { + return ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + itemCount: _requestWrap.length, + itemBuilder: (BuildContext context, int index) { + final item = _requestWrap[index]; + return _item(context, item); + }, ); - } - final columnGetLiberationsResponse = snapshot.data!; - final liberationHistory = PhpGroup.getLiberationsCall - .rqList( - columnGetLiberationsResponse.jsonBody, - ) - ?.toList() ?? - []; - final filteredLiberationHistory = _model.textController.text.isNotEmpty - ? liberationHistory - .where((item) => jsonToStr(getJsonField( - item, - r'''$.VTE_NOME''', - )).toLowerCase().contains( - _model.textController.text.toLowerCase(), - )) - .toList() - : liberationHistory; + }, + ), + ); + } - return ListView.builder( - itemCount: filteredLiberationHistory.length, - addAutomaticKeepAlives: false, - addRepaintBoundaries: true, - cacheExtent: 1000.0, - itemBuilder: (BuildContext context, int index) { - final liberationHistoryItem = filteredLiberationHistory[index]; - return Padding( - padding: EdgeInsets.only( - top: index == 0 - ? MediaQuery.of(context).size.height * 0.075 - : 8.0, - left: 8.0, - right: 8.0, - bottom: 8.0, - ), - child: Align( - alignment: AlignmentDirectional(0.0, 0.0), - child: liberationHistoryItemCard( - context, - liberationHistoryItem, - ), - ), - ); - }, - ); - }, - ), - ); -} + Widget _item(BuildContext context, dynamic liberationHistoryItem) { + return CardItemTemplateComponentWidget( + imagePath: _imagePath(liberationHistoryItem), + labelsHashMap: _labelsHashMap(liberationHistoryItem, false), + statusHashMap: [_statusHashMap(liberationHistoryItem)], + onTapCardItemAction: () async { + showDialog( + useSafeArea: true, + context: context, + builder: (context) { + return Dialog( + alignment: Alignment.center, + child: DetailsComponentWidget( + labelsHashMap: _labelsHashMap(liberationHistoryItem, true), + buttons: [ + if (liberationHistoryItem['NOT_STATUS'] == 'S') + FFButtonWidget( + text: FFLocalizations.of(context) + .getVariableText(ptText: "Aceitar", enText: "Accept"), + options: FFButtonOptions( + width: 130, + height: 40, + color: FlutterFlowTheme.of(context).primary, + elevation: 0, + textStyle: const TextStyle(color: Colors.white), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, + ), + icon: const Icon(Icons.done), + onPressed: () async { + Navigator.pop(context); -Widget liberationHistoryItemCard( - BuildContext context, dynamic liberationHistoryItem) { - return CardItemTemplateComponentWidget( - imagePath: - 'https://freaccess.com.br/freaccess/getImage.php?cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${liberationHistoryItem['VTE_ID'] ?? ''}&tipo=E', - labelsHashMap: Map.from({ - 'Nome:': liberationHistoryItem['VTE_NOME'], - 'Data:': liberationHistoryItem['NOT_DTENVIO'], - 'Motivo:': liberationHistoryItem['NOT_MOTIVO'], - }), - statusHashMap: [ - liberationHistoryItem['NOT_STATUS'] == 'L' - ? Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Finalizado', - enText: 'Finished', - ): FlutterFlowTheme.of(context).success, - }) - : liberationHistoryItem['NOT_STATUS'] == 'B' - ? Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Bloqueado', - enText: 'Blocked', - ): FlutterFlowTheme.of(context).error, - }) - : Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Ativo', - enText: 'Active', - ): FlutterFlowTheme.of(context).warning, - }) - ], - onTapCardItemAction: () async { - showDialog( - // isScrollControlled: true, - // isDismissible: true, - // backgroundColor: Colors.transparent, - useSafeArea: true, - context: context, - builder: (context) { - return Dialog( - alignment: Alignment.center, - child: DetailsComponentWidget( - // vteName: liberationHistoryItem['VTE_NOME'], - // vteReason: liberationHistoryItem['NOT_MOTIVO'], - // vawDate: liberationHistoryItem['NOT_STATUS'] == 'S' - // ? liberationHistoryItem['NOT_DTENVIO'] - // : liberationHistoryItem['NOT_DTRESPOSTA'], - // vawStatus: liberationHistoryItem['NOT_STATUS'], - // vteMsg: liberationHistoryItem['NOT_MSGENVIO'], - // vteUUID: liberationHistoryItem['VTE_ID'], - // cliUUID: FFAppState().cliUUID, - // msgUUID: liberationHistoryItem['NOT_ID'], - // vawDestino: liberationHistoryItem['NOT_DESTINO'], - // vawUUID: liberationHistoryItem['NOT_ID'], - // vawName: liberationHistoryItem['NOT_NOME'], - // vawRef: liberationHistoryItem['NOT_ID'], - labelsHashMap: Map.from({ - 'Nome:': liberationHistoryItem['VTE_NOME'], - 'Data:': liberationHistoryItem['NOT_DTENVIO'], - 'Motivo:': liberationHistoryItem['NOT_MOTIVO'], - 'Mensagem:': liberationHistoryItem['NOT_MSGENVIO'], - // 'Resposta:': liberationHistoryItem['NOT_MSGRESPOSTA'], - }), - buttons: [ - if (liberationHistoryItem['NOT_STATUS'] == 'S') - FlutterFlowIconButton( - icon: const Icon(Icons.done), - onPressed: () async { - Navigator.pop(context); - await answersRequest - .call( - context, - liberationHistoryItem['NOT_ID'].toString(), - 'L', - 'Mensagem', - liberationHistoryItem['VTE_ID'].toString(), - ) - .then((value) { - if (value) { - return showSnackbar( + safeSetState(() { + _requestWrap = []; + _requestFuture = _fetchRequests(); + }); + + var message = await answersRequest.call( + context, + liberationHistoryItem['NOT_ID'].toString(), + 'L', + '', + liberationHistoryItem['VTE_ID'].toString(), + ); + + if (message.isEmpty) { + showSnackbar( context, FFLocalizations.of(context).getVariableText( enText: 'Successfully resolved visit', ptText: 'Visita resolvida com sucesso'), false); } else { - return showSnackbar( + showSnackbar(context, message, true); + } + }, + ), + if (liberationHistoryItem['NOT_STATUS'] == 'S') + FFButtonWidget( + text: FFLocalizations.of(context) + .getVariableText(ptText: "Bloquear", enText: "Block"), + options: FFButtonOptions( + width: 130, + height: 40, + color: FlutterFlowTheme.of(context).error, + elevation: 0, + textStyle: const TextStyle(color: Colors.white), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, + ), + icon: const Icon(Icons.close), + onPressed: () async { + Navigator.pop(context); + + safeSetState(() { + _requestWrap = []; + _requestFuture = _fetchRequests(); + }); + + var message = await answersRequest.call( + context, + liberationHistoryItem['NOT_ID'].toString(), + 'B', + '', + liberationHistoryItem['VTE_ID'].toString(), + ); + + if (message.isEmpty) { + showSnackbar( context, FFLocalizations.of(context).getVariableText( - enText: 'Error resolving visit', - ptText: 'Erro ao resolver visita'), - true); + enText: 'Successfully resolved visit', + ptText: 'Visita resolvida com sucesso'), + false); + } else { + showSnackbar(context, message, true); } - }); - }, + }, + ) + ], + statusHashMap: [_statusHashMap(liberationHistoryItem)], + imagePath: _imagePath(liberationHistoryItem), + ), + ); + }, + ).then((_) { + PushNotificationManager _pushNotificationService = + PushNotificationManager(); + + _pushNotificationService.onMessageReceived.listen((received) { + if (received.data['click_action'] == 'cancel_request') { + _pushNotificationService.dispose(); + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + enText: 'Successfully resolved visit', + ptText: 'Visita resolvida com sucesso'), + false); + context.pushReplacementNamed( + 'liberationHistory', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.scale, + alignment: Alignment.bottomCenter, ), - ], - statusHashMap: [ - liberationHistoryItem['NOT_STATUS'] == 'L' - ? Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Finalizado', - enText: 'Finished', - ): FlutterFlowTheme.of(context).success, - }) - : liberationHistoryItem['NOT_STATUS'] == 'B' - ? Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Bloqueado', - enText: 'Blocked', - ): FlutterFlowTheme.of(context).error, - }) - : Map.from({ - FFLocalizations.of(context).getVariableText( - ptText: 'Ativo', - enText: 'Active', - ): FlutterFlowTheme.of(context).warning, - }) - ], - imagePath: - 'https://freaccess.com.br/freaccess/getImage.php?cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${liberationHistoryItem['VTE_ID'] ?? ''}&tipo=E', - ), - ); - }, - ).then((_) { - // PushNotificationManager _pushNotificationService = - // PushNotificationManager(); - // - // _pushNotificationService.onMessageReceived.listen((received) { - // if (received.data['click_action'] == 'cancel_request') { - // _pushNotificationService.dispose(); - // showSnackbar( - // context, - // FFLocalizations.of(context).getVariableText( - // enText: 'Successfully resolved visit', - // ptText: 'Visita resolvida com sucesso'), - // false); - // context.pushReplacementNamed( - // 'liberationHistory', - // extra: { - // kTransitionInfoKey: const TransitionInfo( - // hasTransition: true, - // transitionType: PageTransitionType.scale, - // alignment: Alignment.bottomCenter, - // ), - // }, - // ); - // } - // }); + }, + ); + } + }); + }).whenComplete(() { + safeSetState(() { + _requestWrap = []; + _requestFuture = _fetchRequests(); + }); + }).catchError((e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed( + "proccessRequest.php", "", "Consulta de Solitiações", e, s); + safeSetState(() { + _hasData = false; + _loading = false; + }); + }); + }, + ); + } + + Future _fetchRequests() async { + try { + setState(() => _loading = true); + var response = await PhpGroup.getLiberationsCall + .call( + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, + atividade: 'getSolicitacoes', + ) + .first; + + final List requests = response.jsonBody['solicitacoes'] ?? []; + + if (requests != null && requests.isNotEmpty) { + setState(() { + _requestWrap.addAll(requests); + _hasData = true; + _loading = false; + }); + + return response; + } + + _showNoMoreDataSnackBar(context); + + setState(() { + _hasData = false; + _loading = false; }); - }, - ); + + return null; + } catch (e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed( + "proccessRequest.php", "", "Consulta de Solicitações", e, s); + setState(() { + _hasData = false; + _loading = false; + }); + } + } + + 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."), + ), + duration: const Duration(seconds: 3), + backgroundColor: FlutterFlowTheme.of(context).primary, + ), + ); + } } diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart index aa896f5d..9199a659 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart @@ -98,11 +98,11 @@ class ScheduleCompleteVisitPageModel ptText: 'Este campo é obrigatório.', ); } - if (val != null) { + if (val != '0') { try { - DateTime startDate = DateFormat('d/M/y H:mm:ss').parse(val); + DateTime startDate = DateFormat('dd/MM/yyyy HH:mm:ss').parse(val); DateTime endDate = - DateFormat('d/M/y H:mm:ss').parse(textController2!.text); + DateFormat('dd/MM/yyyy HH:mm:ss').parse(textController2!.text); if (startDate.isAfter(endDate)) { return FFLocalizations.of(context).getVariableText( ptText: 'A data de início deve ser anterior à data de término.', @@ -116,7 +116,9 @@ class ScheduleCompleteVisitPageModel ); } } catch (e) { - return '$e'; + return FFLocalizations.of(context).getVariableText( + ptText: 'Preencha corretamente o campo de término da visita!', + enText: 'Fill in the end of visit field correctly!'); } } return null; @@ -134,11 +136,12 @@ class ScheduleCompleteVisitPageModel ptText: 'Este campo é obrigatório.', ); } - if (val != null) { + if (val != '0') { try { - DateTime endDate = DateFormat('d/M/y H:mm:ss').parse(val); + DateTime endDate = DateFormat('dd/MM/yyyy HH:mm:ss').parse(val); DateTime startDate = - DateFormat('d/M/y H:mm:ss').parse(textController1!.text); + DateFormat('dd/MM/yyyy HH:mm:ss').parse(textController1!.text); + if (endDate.isBefore(startDate)) { return FFLocalizations.of(context).getVariableText( enText: 'End date must be after start date.', @@ -152,7 +155,9 @@ class ScheduleCompleteVisitPageModel ); } } catch (e) { - return '$e'; + return FFLocalizations.of(context).getVariableText( + ptText: 'Preencha corretamente o campo de início da visita!', + enText: 'Fill in the visit start field correctly!'); } } return null; diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart index 540aeaac..775160ef 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart @@ -1,22 +1,15 @@ -import 'dart:developer'; - import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:hub/actions/actions.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; -import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; -import 'package:hub/components/templates_components/details_component/details_component_action.dart'; import 'package:hub/components/templates_components/details_component/details_component_widget.dart'; -import 'package:hub/components/templates_components/visit_details_modal_template_component/visit_details_modal_template_component_widget.dart'; import 'package:hub/components/templates_components/visitor_search_modal_template_component/visitor_search_modal_template_component_widget.dart'; import 'package:hub/flutter_flow/custom_functions.dart'; import 'package:hub/flutter_flow/flutter_flow_drop_down.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; -import 'package:hub/flutter_flow/flutter_flow_model.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; @@ -395,7 +388,7 @@ Widget scheduleVisit(BuildContext context, .bodyMediumFamily), lineHeight: 1.8, ), - textAlign: TextAlign.center, + textAlign: TextAlign.start, validator: _model.textController1Validator .asValidator(context)), ), @@ -490,13 +483,15 @@ Widget scheduleVisit(BuildContext context, FlutterFlowTheme.of(context) .primaryBackground, pickerForegroundColor: - FlutterFlowTheme.of(context) - .primaryText, + FlutterFlowTheme.of(context).info, selectedDateTimeBackgroundColor: FlutterFlowTheme.of(context) .primary, selectedDateTimeForegroundColor: FlutterFlowTheme.of(context).info, + pickerDialForegroundColor: + FlutterFlowTheme.of(context) + .primaryText, actionButtonForegroundColor: FlutterFlowTheme.of(context) .primaryText, @@ -520,7 +515,7 @@ Widget scheduleVisit(BuildContext context, } safeSetState(() { _model.textController1?.text = dateTimeFormat( - 'd/M/y H:mm:ss', + 'dd/MM/yyyy HH:mm:ss', _model.datePicked1, locale: FFLocalizations.of(context) .languageCode, @@ -642,7 +637,7 @@ Widget scheduleVisit(BuildContext context, .bodyMediumFamily), lineHeight: 1.8, ), - textAlign: TextAlign.center, + textAlign: TextAlign.start, validator: _model.textController2Validator .asValidator(context), ), @@ -738,13 +733,15 @@ Widget scheduleVisit(BuildContext context, FlutterFlowTheme.of(context) .primaryBackground, pickerForegroundColor: - FlutterFlowTheme.of(context) - .primaryText, + FlutterFlowTheme.of(context).info, selectedDateTimeBackgroundColor: FlutterFlowTheme.of(context) .primary, selectedDateTimeForegroundColor: FlutterFlowTheme.of(context).info, + pickerDialForegroundColor: + FlutterFlowTheme.of(context) + .primaryText, actionButtonForegroundColor: FlutterFlowTheme.of(context) .primaryText, @@ -768,7 +765,7 @@ Widget scheduleVisit(BuildContext context, } safeSetState(() { _model.textController2?.text = dateTimeFormat( - 'd/M/y H:mm:ss', + 'dd/MM/yyyy HH:mm:ss', _model.datePicked2, locale: FFLocalizations.of(context) .languageCode, @@ -1431,12 +1428,11 @@ Widget scheduleVisit(BuildContext context, ), ), ), - Switch.adaptive( + Switch( value: _model.switchValue!, onChanged: (newValue) async { safeSetState(() => _model.switchValue = newValue); }, - applyCupertinoTheme: false, focusColor: FlutterFlowTheme.of(context).primary, trackColor: WidgetStateProperty.resolveWith( (states) { diff --git a/lib/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart b/lib/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart index 00eaf300..e0a704e3 100644 --- a/lib/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart +++ b/lib/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart @@ -1,22 +1,19 @@ -import 'dart:developer'; - -import 'package:hub/shared/utils/dialog_util.dart'; -import 'package:hub/shared/utils/log_util.dart'; - -import '/backend/api_requests/api_calls.dart'; -import '/components/molecular_components/throw_exception/throw_exception_widget.dart'; -import '/flutter_flow/flutter_flow_icon_button.dart'; -import '/flutter_flow/flutter_flow_theme.dart'; -import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_debounce/easy_debounce.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/log_util.dart'; import 'package:provider/provider.dart'; +import '/backend/api_requests/api_calls.dart'; +import '/flutter_flow/flutter_flow_icon_button.dart'; +import '/flutter_flow/flutter_flow_theme.dart'; +import '/flutter_flow/flutter_flow_util.dart'; +import '/flutter_flow/flutter_flow_widgets.dart'; + class ScheduleProvisionalVisitPageWidget extends StatefulWidget { const ScheduleProvisionalVisitPageWidget({super.key}); @@ -722,11 +719,15 @@ class _ScheduleProvisionalVisitPageWidgetState pickerForegroundColor: FlutterFlowTheme.of( context) - .primaryText, + .info, selectedDateTimeBackgroundColor: FlutterFlowTheme.of( context) .primary, + pickerDialForegroundColor: + FlutterFlowTheme.of( + context) + .primaryText, selectedDateTimeForegroundColor: FlutterFlowTheme.of( context) @@ -979,16 +980,16 @@ class _ScheduleProvisionalVisitPageWidgetState _model.provVisitSchedule = await PhpGroup .postProvVisitSchedulingCall .call( - devUUID: AppState().devUUID, - userUUID: AppState().userUUID, - cliID: AppState().cliUUID, + devUUID: FFAppState().devUUID, + userUUID: FFAppState().userUUID, + cliID: FFAppState().cliUUID, atividade: 'putAgendamentoProv', data: _model.dateTimeTextController.text, motivo: _model.notesTextController.text, nome: _model .personNameTextController.text, - proID: AppState().ownerUUID, + proID: FFAppState().ownerUUID, ); if (PhpGroup.postProvVisitSchedulingCall diff --git a/lib/pages/visit_history_page/visit_history_page_widget.dart b/lib/pages/visit_history_page/visit_history_page_widget.dart index 1ccc460f..256c0825 100644 --- a/lib/pages/visit_history_page/visit_history_page_widget.dart +++ b/lib/pages/visit_history_page/visit_history_page_widget.dart @@ -1,198 +1,263 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:hub/actions/actions.dart'; -import 'package:hub/app_state.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; -import 'package:hub/backend/api_requests/api_manager.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; import 'package:hub/components/templates_components/details_component/details_component_action.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; -import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/pages/schedule_complete_visit_page/schedule_complete_visit_page_model.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/utils/log_util.dart'; +import 'package:hub/shared/utils/validator_util.dart'; class VisitHistoryWidget extends StatefulWidget { - VisitHistoryWidget({ - Key? key, - }) : super(key: key); + VisitHistoryWidget({Key? key}) : super(key: key); @override _VisitHistoryWidgetState createState() => _VisitHistoryWidgetState(); } -class _VisitHistoryWidgetState extends State { - List visitaWrap = []; - var pageNumber = 1; - late Future visitFuture; +class _VisitHistoryWidgetState extends State + with TickerProviderStateMixin { + late ScrollController _scrollController; + int _pageNumber = 1; + final int _pageSize = 10; + bool _hasData = false; + bool _loading = false; + + late Future _visitFuture; + List _visitWrap = []; @override void initState() { super.initState(); - visitFuture = _fetchVisits(); + _visitFuture = _fetchVisits(); + + _scrollController = ScrollController() + ..addListener(() { + if (_scrollController.position.atEdge && + _scrollController.position.pixels != 0) { + _loadMore(); + } + }); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); } Future _fetchVisits() async { try { + setState(() => _loading = true); + var response = await ScheduleCompleteVisitPageModel().visitHistory( requestFn: () => PhpGroup.getVisitsCall.call( devUUID: AppState().devUUID, userUUID: AppState().userUUID, cliID: AppState().cliUUID, atividade: 'getVisitas', - pageSize: 10, - pageNumber: pageNumber, + pageSize: _pageSize, + pageNumber: _pageNumber, ), ); - var newVisits = response.jsonBody['visitas'] - as List?; // Ajuste conforme a estrutura da resposta - if (newVisits != null && newVisits.isNotEmpty) { - safeSetState(() { - visitaWrap.addAll(newVisits); + final List visits = response.jsonBody['visitas'] ?? []; + + if (visits != null && visits.isNotEmpty) { + setState(() { + _visitWrap.addAll(visits); + _hasData = true; + _loading = false; }); + return response; - } else { - log('No new visits found'); - return null; } - } catch (err) { - log('Erro ao carregar mais visitas: $err'); + + _showNoMoreDataSnackBar(context); + + setState(() { + _hasData = false; + _loading = false; + }); + + return null; + } catch (e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed( + "proccessRequest.php", "", "Consulta de Visitas", e, s); + setState(() { + _hasData = false; + _loading = false; + }); } } - void _loadMoreVisits() { - pageNumber++; - visitFuture = _fetchVisits(); + void _loadMore() { + if (_hasData == true) { + _pageNumber++; + _visitFuture = _fetchVisits(); + } + } + + void _showNoMoreDataSnackBar(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + FFLocalizations.of(context).getVariableText( + ptText: "Não há mais dados.", enText: "No more data."), + ), + duration: const Duration(seconds: 3), + backgroundColor: FlutterFlowTheme.of(context).primary, + ), + ); } @override Widget build(BuildContext context) { - return FutureBuilder( - future: visitFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting && - visitaWrap.isEmpty) { - return Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - FlutterFlowTheme.of(context).primary, - ), - ), - ); - } else if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } else if (visitaWrap.isEmpty) { - return Center( - child: Text( - FFLocalizations.of(context).getVariableText( - ptText: 'Nenhum visitante foi encontrado', - enText: 'No visitors found', - ), - ), - ); - } - - return ListView.builder( - itemCount: visitaWrap.length + 1, - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - itemBuilder: (context, index) { - if (index == visitaWrap.length) { - _loadMoreVisits(); - return Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - FlutterFlowTheme.of(context).primary, - ), - ), - ); - } - - final visitaWrapItem = visitaWrap[index]; - - return CardItemTemplateComponentWidget( - imagePath: - 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${AppState().devUUID}&userUUID=${AppState().userUUID}&cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${visitaWrapItem['VTE_DOCUMENTO'] ?? ''}&tipo=E', - labelsHashMap: { - 'Nome:': visitaWrapItem['VTE_NOME'] ?? '', - 'Inicio:': visitaWrapItem['VAW_DTINICIO'] ?? '', - 'Fim:': visitaWrapItem['VAW_DTFIM'] ?? '', - }, - statusHashMap: [ - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.active) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Ativo', - enText: 'Active', - ): FlutterFlowTheme.of(context).warning, - }, - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.finished) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Finalizado', - enText: 'Finished', - ): FlutterFlowTheme.of(context).success, - }, - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.unknown) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Desconhecido', - enText: 'Unknown', - ): FlutterFlowTheme.of(context).alternate, - }, - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.canceled) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Cancelado', - enText: 'Canceled', - ): FlutterFlowTheme.of(context).error, - }, - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.blocked) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Bloqueado', - enText: 'Blocked', - ): FlutterFlowTheme.of(context).error, - }, - if (getStatus(visitaWrapItem['VAW_STATUS']) == status.inactive) - { - FFLocalizations.of(context).getVariableText( - ptText: 'Inativo', - enText: 'Inactive', - ): FlutterFlowTheme.of(context).error, - }, + return Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (_hasData == false && _pageNumber <= 1 && _loading == false) + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Center( + child: Text(FFLocalizations.of(context).getVariableText( + ptText: "Nenhuma visita encontrada!", + enText: "No visit found")), + ) ], - onTapCardItemAction: () async { - await showDialog( - useSafeArea: true, - context: context, - builder: (context) { - return Dialog( - alignment: Alignment.center, - child: buildDetails( - visitaWrapItem, - context, - changeStatusAction, - ), - ); - }, - ).whenComplete(() { - // updateVisitFuture(); - _fetchVisits().then((response) { - safeSetState(() { - visitaWrap = PhpGroup.getVisitsCall - .visitasList(response!.jsonBody) - ?.toList() ?? - []; - visitFuture = Future.value(response); - }); + ), + ) + else if (_hasData == true || _pageNumber >= 1) + Expanded( + child: FutureBuilder( + future: _visitFuture, + builder: (context, snapshot) { + return ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + controller: _scrollController, + itemCount: _visitWrap.length, + itemBuilder: (context, index) { + final item = _visitWrap[index]; + return _item(context, item); }); - }).catchError((err, stack) {}); - }, + }, + )), + if (_hasData == true && _loading == true) + Container( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ) + ].addToStart(const SizedBox(height: 0)), + ); + } + + Widget _item(BuildContext context, dynamic visitaWrapItem) { + return CardItemTemplateComponentWidget( + imagePath: + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${visitaWrapItem['VTE_DOCUMENTO'] ?? ''}&tipo=E', + labelsHashMap: { + '${FFLocalizations.of(context).getVariableText(ptText: "Nome", enText: "Name")}:': + visitaWrapItem['VTE_NOME'] ?? '', + '${FFLocalizations.of(context).getVariableText(ptText: "Inicio", enText: "Start")}:': + visitaWrapItem['VAW_DTINICIO'] != '' && + visitaWrapItem['VAW_DTINICIO'] != null + ? ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd HH:mm:ss', visitaWrapItem['VAW_DTINICIO']) + : '', + '${FFLocalizations.of(context).getVariableText(ptText: "Fim", enText: "End")}:': + visitaWrapItem['VAW_DTFIM'] != '' && + visitaWrapItem['VAW_DTFIM'] != null + ? ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd HH:mm:ss', visitaWrapItem['VAW_DTFIM']) + : '', + }, + statusHashMap: [ + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.active) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Ativo', + enText: 'Active', + ): FlutterFlowTheme.of(context).warning, + }, + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.finished) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Finalizado', + enText: 'Finished', + ): FlutterFlowTheme.of(context).success, + }, + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.unknown) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Desconhecido', + enText: 'Unknown', + ): FlutterFlowTheme.of(context).alternate, + }, + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.canceled) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Cancelado', + enText: 'Canceled', + ): FlutterFlowTheme.of(context).error, + }, + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.blocked) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Bloqueado', + enText: 'Blocked', + ): FlutterFlowTheme.of(context).error, + }, + if (getStatus(visitaWrapItem['VAW_STATUS']) == status.inactive) + { + FFLocalizations.of(context).getVariableText( + ptText: 'Inativo', + enText: 'Inactive', + ): FlutterFlowTheme.of(context).error, + }, + ], + onTapCardItemAction: () async { + await showDialog( + useSafeArea: true, + context: context, + builder: (context) { + return Dialog( + alignment: Alignment.center, + child: buildDetails( + visitaWrapItem, + context, + changeStatusAction, + ), ); }, - ); + ).whenComplete(() { + safeSetState(() { + _pageNumber = 1; + _visitWrap = []; + _visitFuture = _fetchVisits(); + }); + }).catchError((e, s) { + DialogUtil.errorDefault(context); + LogUtil.requestAPIFailed( + "proccessRequest.php", "", "Consulta de Visitas", e, s); + safeSetState(() { + _hasData = false; + _loading = false; + }); + }); }, ); } diff --git a/lib/shared/utils/validator_util.dart b/lib/shared/utils/validator_util.dart index d0888545..926930ea 100644 --- a/lib/shared/utils/validator_util.dart +++ b/lib/shared/utils/validator_util.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:intl/intl.dart'; class ValidatorUtil { @@ -23,4 +25,11 @@ class ValidatorUtil { return dateTime.toIso8601String(); } + + static String toLocalDateTime(String format, String value) { + DateFormat dateFormat = DateFormat(format); + DateTime dateTime = dateFormat.parse(value); + + return DateFormat('dd/MM/yyyy HH:mm:ss').format(dateTime); + } } diff --git a/pubspec.lock b/pubspec.lock index e7e7760e..a6e999a5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -174,9 +174,11 @@ packages: description: name: cross_file sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.dev" source: hosted version: "0.3.4+2" + version: "0.3.4+2" crypto: dependency: transitive description: @@ -230,9 +232,11 @@ packages: description: name: device_info_plus_platform_interface sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" url: "https://pub.dev" source: hosted version: "7.0.1" + version: "7.0.1" dropdown_button2: dependency: "direct main" description: @@ -270,9 +274,11 @@ packages: description: name: ffi sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted version: "2.1.3" + version: "2.1.3" file: dependency: transitive description: @@ -318,9 +324,11 @@ packages: description: name: file_selector_windows sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" url: "https://pub.dev" source: hosted version: "0.9.3+2" + version: "0.9.3+2" firebase_analytics: dependency: "direct main" description: @@ -358,17 +366,21 @@ packages: description: name: firebase_core_platform_interface sha256: "3c3a1e92d6f4916c32deea79c4a7587aa0e9dbbe5889c7a16afcf005a485ee02" + sha256: "3c3a1e92d6f4916c32deea79c4a7587aa0e9dbbe5889c7a16afcf005a485ee02" url: "https://pub.dev" source: hosted version: "5.2.0" + version: "5.2.0" firebase_core_web: dependency: transitive description: name: firebase_core_web sha256: e8d1e22de72cb21cdcfc5eed7acddab3e99cd83f3b317f54f7a96c32f25fd11e + sha256: e8d1e22de72cb21cdcfc5eed7acddab3e99cd83f3b317f54f7a96c32f25fd11e url: "https://pub.dev" source: hosted version: "2.17.4" + version: "2.17.4" firebase_crashlytics: dependency: "direct main" description: @@ -451,9 +463,11 @@ packages: description: name: flutter_expandable_fab sha256: f4692d1949cda81e10ca0c3e75aea1e14e29ecc12d9328996321b96e9747a955 + sha256: f4692d1949cda81e10ca0c3e75aea1e14e29ecc12d9328996321b96e9747a955 url: "https://pub.dev" source: hosted version: "2.2.0" + version: "2.2.0" flutter_inappwebview: dependency: "direct main" description: @@ -637,6 +651,14 @@ packages: description: flutter source: sdk version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "95f349437aeebe524ef7d6c9bde3e6b4772717cf46a0eb6a3ceaddc740b297cc" + url: "https://pub.dev" + source: hosted + version: "8.2.8" font_awesome_flutter: dependency: "direct main" description: @@ -810,17 +832,21 @@ packages: description: name: leak_tracker sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted version: "10.0.5" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted version: "3.0.5" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -842,25 +868,31 @@ packages: description: name: local_auth sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" + sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" url: "https://pub.dev" source: hosted version: "2.3.0" + version: "2.3.0" local_auth_android: dependency: transitive description: name: local_auth_android sha256: e99c44ca0bce08f26f25e2a2e07d3b443d69986e1c3acf67c1449f7d847e3625 + sha256: e99c44ca0bce08f26f25e2a2e07d3b443d69986e1c3acf67c1449f7d847e3625 url: "https://pub.dev" source: hosted version: "1.0.43" + version: "1.0.43" local_auth_darwin: dependency: transitive description: name: local_auth_darwin sha256: "7ba5738c874ca2b910d72385d00d2bebad9d4e807612936cf5e32bc01a048c71" + sha256: "7ba5738c874ca2b910d72385d00d2bebad9d4e807612936cf5e32bc01a048c71" url: "https://pub.dev" source: hosted version: "1.4.0" + version: "1.4.0" local_auth_platform_interface: dependency: transitive description: @@ -874,9 +906,11 @@ packages: description: name: local_auth_windows sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 + sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 url: "https://pub.dev" source: hosted version: "1.0.11" + version: "1.0.11" logging: dependency: transitive description: @@ -898,9 +932,11 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted version: "0.11.1" + version: "0.11.1" maybe_just_nothing: dependency: transitive description: @@ -914,9 +950,11 @@ packages: description: name: meta sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted version: "1.15.0" + version: "1.15.0" mime: dependency: transitive description: @@ -954,9 +992,11 @@ packages: description: name: octo_image sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" url: "https://pub.dev" source: hosted version: "2.1.0" + version: "2.1.0" page_transition: dependency: "direct main" description: @@ -1026,9 +1066,11 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted version: "2.3.0" + version: "2.3.0" percent_indicator: dependency: "direct main" description: @@ -1074,9 +1116,11 @@ packages: description: name: permission_handler_platform_interface sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea + sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea url: "https://pub.dev" source: hosted version: "4.2.2" + version: "4.2.2" permission_handler_windows: dependency: transitive description: @@ -1130,9 +1174,11 @@ packages: description: name: qr sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" url: "https://pub.dev" source: hosted version: "3.0.2" + version: "3.0.2" qr_flutter: dependency: "direct main" description: @@ -1335,9 +1381,11 @@ packages: description: name: test_api sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted version: "0.7.2" + version: "0.7.2" timeago: dependency: "direct main" description: @@ -1383,9 +1431,11 @@ packages: description: name: url_launcher_linux sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af url: "https://pub.dev" source: hosted version: "3.2.0" + version: "3.2.0" url_launcher_macos: dependency: transitive description: @@ -1407,25 +1457,31 @@ packages: description: name: url_launcher_web sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted version: "2.3.3" + version: "2.3.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" url: "https://pub.dev" source: hosted version: "3.1.2" + version: "3.1.2" uuid: dependency: "direct overridden" description: name: uuid sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" + sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" url: "https://pub.dev" source: hosted version: "4.4.2" + version: "4.4.2" vector_graphics: dependency: transitive description: @@ -1503,9 +1559,11 @@ packages: description: name: vm_service sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc url: "https://pub.dev" source: hosted version: "14.2.4" + version: "14.2.4" web: dependency: transitive description: @@ -1527,9 +1585,11 @@ packages: description: name: webview_flutter_android sha256: c66651fba15f9d7ddd31daec42da8d6bce46c85610a7127e3ebcb39a4395c3c9 + sha256: c66651fba15f9d7ddd31daec42da8d6bce46c85610a7127e3ebcb39a4395c3c9 url: "https://pub.dev" source: hosted version: "3.16.6" + version: "3.16.6" webview_flutter_platform_interface: dependency: transitive description: @@ -1559,9 +1619,11 @@ packages: description: name: win32_registry sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" + sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" url: "https://pub.dev" source: hosted version: "1.1.4" + version: "1.1.4" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d8c4a49a..20691a7b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,6 +3,8 @@ description: A new Flutter project. publish_to: "none" +publish_to: "none" + version: 1.0.0+3 environment: