From d41a16256284532820f51f044813f443686a799e Mon Sep 17 00:00:00 2001 From: jantunesmesias Date: Mon, 15 Jul 2024 12:24:48 -0300 Subject: [PATCH] feat: Add QR code functionality and route --- lib/actions/actions.dart | 181 ++++- lib/app_state.dart | 30 +- lib/backend/schema/util/schema_util.dart | 1 + .../menu_component/menu_component_widget.dart | 15 + .../menu_list_view_component_widget.dart | 9 +- lib/custom_code/actions/get_dev_u_u_i_d.dart | 25 + lib/flutter_flow/custom_functions.dart | 14 +- .../qr_code_page/qr_code_page_widget.dart | 667 ++++++++++-------- .../schedule_complete_visit_page_model.dart | 21 +- .../schedule_complete_visit_page_widget.dart | 35 +- pubspec.lock | 40 ++ pubspec.yaml | 1 + 12 files changed, 681 insertions(+), 358 deletions(-) diff --git a/lib/actions/actions.dart b/lib/actions/actions.dart index 40c9ce33..e5f67a2a 100644 --- a/lib/actions/actions.dart +++ b/lib/actions/actions.dart @@ -1,6 +1,11 @@ +import 'dart:convert'; + import 'package:f_r_e_hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; +import 'package:f_r_e_hub/custom_code/actions/get_dev_u_u_i_d.dart'; import 'package:f_r_e_hub/pages/home_page/home_page_widget.dart'; import 'package:flutter/material.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'dart:developer' as developer; import '/actions/actions.dart' as action_blocks; import '/backend/api_requests/api_calls.dart'; @@ -8,8 +13,6 @@ import '/components/molecular_components/throw_exception/throw_exception_widget. import '/custom_code/actions/index.dart' as actions; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; -import '/flutter_flow/flutter_flow_util.dart'; - import '/flutter_flow/random_data_util.dart' as random_data; Future repeatVisitScheduleAction( @@ -136,9 +139,13 @@ Future singInLoginAction( FFAppState().status = PhpGroup.loginCall.userStatus( (loginCall.jsonBody ?? ''), )!; + FFAppState().userDevUUID = PhpGroup.loginCall.userDeviceId( + (loginCall.jsonBody ?? ''), + )!; FFAppState().name = PhpGroup.loginCall.userName( (loginCall.jsonBody ?? ''), )!; + FFAppState().serialNumber = await getSerialNumber() ?? ''; FFAppState().isLogged = true; await action_blocks.toggleHomePage(context); return; @@ -495,3 +502,173 @@ Future changeStatusAction( } + + +/// QR Code + + +Uint8List assembleQRPacket(int direction, String identifier, String password) { + Uint8List packet = Uint8List(20); + int position = 0; + int check = 0; + + // Direction + packet[position++] = direction; + + // Identifier + Uint8List ide = hexStringToByteArray(("000000000000000000000000000000" + identifier).substring(identifier.length)); + for (int i = 0; i < ide.length; i++) { + packet[position++] = ide[i]; + } + + // Date and time + DateTime now = DateTime.now(); + int day = int.parse(DateFormat('dd').format(now)); + int month = int.parse(DateFormat('MM').format(now)); + int year = int.parse(DateFormat('yy').format(now)); + int hour = int.parse(DateFormat('HH').format(now)); + int minute = int.parse(DateFormat('mm').format(now)); + + int sumDate = year + month + day + hour + minute; + packet[position++] = (sumDate == 0x0D || sumDate == 0x0A) ? 0xFF : sumDate; + + // Log the sumDate + developer.log("Soma Data: $sumDate", name: "ROTINAS"); + + // Password + Uint8List passBytes = hexStringToByteArray(password); + packet[position++] = passBytes[0]; + packet[position++] = passBytes[1]; + + // Checksum + for (int i = 0; i < packet.length - 1; i++) { + check ^= packet[i]; + } + packet[position] = (check == 0x0D || check == 0x0A) ? 0xFF : check; + + // Log the checksum + developer.log("Checksum: $check", name: "ROTINAS"); + + // Convert packet to hex string and log it + String hexPacket = byteToHexa(packet); + developer.log("Pacote final: $hexPacket", name: "ROTINAS"); + + return packet; +} + +Uint8List hexStringToByteArray(String s) { + int len = s.length; + Uint8List data = Uint8List(len ~/ 2); + for (int i = 0; i < len; i += 2) { + data[i ~/ 2] = ((int.parse(s[i], radix: 16) << 4) + int.parse(s[i + 1], radix: 16)); + } + return data; +} + +String byteToHexa(List pDados) { + return pDados.map((byte) => byte.toRadixString(16).padLeft(2, '0').toUpperCase()).join(); +} + + + + + +String byteToString(Uint8List bytes) { + return utf8.decode(bytes); +} + +Widget buildQrCode( +{ + required String data, + required String type, + required double dimension, + required int errorCorrectLevel, + required int version, + required int maskPattern, + required String identifier, + required String pass, + required int direction + } + ) { + debugPrint('remoteID: ${FFAppState().userDevUUID}'); + debugPrint('androidId: ${FFAppState().devUUID}'); + debugPrint('Serial Number: ${FFAppState().serialNumber}'); + + try { + // Verifica se os dados estão de acordo com as regras de negócio + if (data.isEmpty) { + throw Exception("Dados do QR Code estão vazios."); + } + // Aqui você pode adicionar mais lógica de validação conforme necessário + + // Geração do QR Code com a biblioteca qr_flutter + const Color backgroundColor = Colors.white; + const Color foregroundColor = Colors.black; + return QrImageView( + data: byteToString(assembleQRPacket(direction, identifier, pass)), + version: version, //QrVersions.auto + size: dimension, + // errorCorrectionLevel: errorCorrectLevel, + backgroundColor: backgroundColor, + foregroundColor: foregroundColor, + gapless: false, // Ajuste conforme necessário + // Adicione mais customizações aqui conforme os arquivos Java + ); + } catch (e) { + // Tratamento de erros + return Text("Erro ao gerar QR Code: ${e.toString()}"); + } +} + + + // // Retorna o conteúdo a ser codificado no QR Code. + // String getContents() { + // return data; + // } + + // // Retorna uma versão do conteúdo otimizada para exibição. + // String getDisplayContents() { + // return data.trim(); + // } + + // // Retorna o título baseado no tipo de conteúdo. + // String getTitle() { + // return type; + // } + + // // Codifica o conteúdo em uma string adequada para o QR Code. + // Future encodeContents() async { + // // Implementação específica para codificar o conteúdo. + // return data; // Exemplo simplificado. + // } + + // // Codifica o conteúdo específico do QR Code. + // Future encodeQRCodeContents() async { + // return getQrCode(); + // } + + // // Gera o QR Code como um widget. + + + // // Codifica o conteúdo como um bitmap (pode ser útil para operações de baixo nível). + // // Future encodeAsBitmap() async { + // // // Implementação para codificar como bitmap. + // // return Image(image); // Exemplo simplificado. + // // } + + // // Adivinha a codificação apropriada para o conteúdo. + // String guessAppropriateEncoding(String content) { + // // Implementação para adivinhar a codificação. + // return "UTF-8"; // Exemplo simplificado. + // } + + // // Remove espaços em branco do início e do fim do conteúdo. + // String trim(String content) { + // return content.trim(); + // } + + // // Escapa caracteres especiais para o formato MECARD. + // String escapeMECARD(String content) { + // // Implementação para escapar caracteres. + // return content.replaceAll(':', '\\:'); // Exemplo simplificado. + // } \ No newline at end of file diff --git a/lib/app_state.dart b/lib/app_state.dart index 36fb9dd7..bfc93a71 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -61,7 +61,13 @@ class FFAppState extends ChangeNotifier { _name = await secureStorage.getString('ff_name') ?? _name; }); await _safeInitAsync(() async { - _name = await secureStorage.getString('ff_tokenAPNS') ?? _name; + _tokenAPNS = await secureStorage.getString('ff_tokenAPNS') ?? _tokenAPNS; + }); + await _safeInitAsync(() async { + _userDevUUID = await secureStorage.getString('ff_user_dev_id') ?? _userDevUUID; + }); + await _safeInitAsync(() async { + _serialNumber = await secureStorage.getString('ff_serialNumber') ?? _serialNumber; }); } @@ -72,6 +78,17 @@ class FFAppState extends ChangeNotifier { late FlutterSecureStorage secureStorage; + String _serialNumber = ''; + String get serialNumber => _serialNumber; + set serialNumber(String value) { + _serialNumber = value; + secureStorage.setString('ff_serialNumber', value); + } + + void deleteSerialNumber() { + secureStorage.delete(key: 'ff_serialNumber'); + } + String _cliUUID = ''; String get cliUUID => _cliUUID; set cliUUID(String value) { @@ -83,6 +100,17 @@ class FFAppState extends ChangeNotifier { secureStorage.delete(key: 'ff_cliUUID'); } + String _userDevUUID = ''; + String get userDevUUID => _userDevUUID; + set userDevUUID(String value) { + _userDevUUID = value; + secureStorage.setString('ff_user_dev_id', value); + } + + void deleteRemoteId() { + secureStorage.delete(key: 'ff_user_dev_id'); + } + String? _tokenAPNS = ''; String? get tokenAPNS => _tokenAPNS; diff --git a/lib/backend/schema/util/schema_util.dart b/lib/backend/schema/util/schema_util.dart index b2cd6af6..f1ad8a3f 100644 --- a/lib/backend/schema/util/schema_util.dart +++ b/lib/backend/schema/util/schema_util.dart @@ -10,6 +10,7 @@ export 'package:collection/collection.dart' show ListEquality; export 'package:flutter/material.dart' show Color, Colors; export 'package:from_css_color/from_css_color.dart'; + typedef StructBuilder = T Function(Map data); abstract class BaseStruct { diff --git a/lib/components/organism_components/menu_component/menu_component_widget.dart b/lib/components/organism_components/menu_component/menu_component_widget.dart index 79afe54b..d85510d7 100644 --- a/lib/components/organism_components/menu_component/menu_component_widget.dart +++ b/lib/components/organism_components/menu_component/menu_component_widget.dart @@ -117,4 +117,19 @@ class _MenuComponentWidgetState extends State { ), ); } + + Future accessQRCodeOptAction(BuildContext context) async { + context.pushNamed( + 'qrCodePage', + extra: { + kTransitionInfoKey: const TransitionInfo( + hasTransition: true, + transitionType: PageTransitionType.scale, + alignment: Alignment.bottomCenter, + ), + }, + ); + } + + } diff --git a/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart b/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart index b1a30341..2c929518 100644 --- a/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart +++ b/lib/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart @@ -842,9 +842,8 @@ Propriedade */ child: Text( FFLocalizations.of(context) .getVariableText( - ptText: 'Consultar\nConsultar -Históricos */ - , + ptText: 'Consultar\nConsultar', + enText: 'Consult\nHistories', ), style: FlutterFlowTheme.of(context) .titleLarge @@ -953,9 +952,9 @@ Históricos */ Align( alignment: const AlignmentDirectional(0.0, 0.0), child: Text( - FFLocalizations.of(context).getText( - '589qufkw' /* Históricos', + FFLocalizations.of(context).getVariableText( enText: 'Consult\nHistories', + ptText: 'Consultar\nHistóricos', ), style: FlutterFlowTheme.of(context) .titleLarge diff --git a/lib/custom_code/actions/get_dev_u_u_i_d.dart b/lib/custom_code/actions/get_dev_u_u_i_d.dart index 84519e07..356c7ec5 100644 --- a/lib/custom_code/actions/get_dev_u_u_i_d.dart +++ b/lib/custom_code/actions/get_dev_u_u_i_d.dart @@ -38,3 +38,28 @@ Future getDevUUID() async { return androidDeviceInfo.id; // unique ID on Android } } + +Future getSerialNumber() async { + var deviceInfo = DeviceInfoPlugin(); + if (Platform.isIOS) { + // import 'dart:io' + var iosDeviceInfo = await deviceInfo.iosInfo; + debugPrint('DeviceInfoPlugin => iosDeviceInfo.utsname.machine: ${iosDeviceInfo.utsname.machine}'); // e.g. "iPod7,1" + debugPrint('DeviceInfoPlugin => iosDeviceInfo.systemName: ${iosDeviceInfo.systemName}'); // e.g. "iOS" + debugPrint('DeviceInfoPlugin => iosDeviceInfo.systemVersion: ${iosDeviceInfo.systemVersion}'); // e.g. "13.3" + debugPrint('DeviceInfoPlugin => iosDeviceInfo.model: ${iosDeviceInfo.model}'); // e.g. "iPhone" + debugPrint('DeviceInfoPlugin => iosDeviceInfo.localizedModel: ${iosDeviceInfo.localizedModel}'); // e.g. "iPhone" + debugPrint('DeviceInfoPlugin => iosDeviceInfo.identifierForVendor: ${iosDeviceInfo.identifierForVendor}'); // e.g. "A8E9F7C8-4D1F-4D97-9C3B-3A3D0F0F3E9E" + return iosDeviceInfo.identifierForVendor; // unique ID on iOS + } else if (Platform.isAndroid) { + var androidDeviceInfo = await deviceInfo.androidInfo; + print(AndroidDeviceInfo); + // debugPrint('Running on ${androidDeviceInfo.androidId}'); // e.g. "A8E9F7C8-4D1F-4D97-9C3B-3A3D0F0F3E9E" + debugPrint('DeviceInfoPLugin => androidDeviceInfo.model: ${androidDeviceInfo.model}'); // e.g. "iPhone" + debugPrint('DeviceInfoPLugin => androidDeviceInfo.manufacturer: ${androidDeviceInfo.manufacturer}'); // e.g. "iPhone" + debugPrint('DeviceInfoPLugin => androidDeviceInfo.product: ${androidDeviceInfo.product}'); // e.g. "iPhone" + debugPrint('DeviceInfoPLugin => androidDeviceInfo.device: ${androidDeviceInfo.device}'); // e.g. "iPhone" + debugPrint('DeviceInfoPLugin => androidDeviceInfo.id: ${androidDeviceInfo.id}'); // e.g. "iPhone" + return androidDeviceInfo.serialNumber; // unique ID on Android +} +} diff --git a/lib/flutter_flow/custom_functions.dart b/lib/flutter_flow/custom_functions.dart index 39cba244..e14fb884 100644 --- a/lib/flutter_flow/custom_functions.dart +++ b/lib/flutter_flow/custom_functions.dart @@ -106,6 +106,14 @@ String jsonToStr(dynamic json) { return jsonString; } -double getProgressValue(int percentage) { - return percentage / 100; -} +Stream getProgressValue() { + final startTime = DateTime.now().millisecondsSinceEpoch; + final endTime = startTime + 20000; + final duration = Duration(milliseconds: 100); + return Stream.periodic(duration, (int count) { + final currentTime = DateTime.now().millisecondsSinceEpoch; + final elapsedTime = currentTime - startTime; + final progress = math.min(1.0, elapsedTime / (endTime - startTime)); + return progress; + }); +} \ No newline at end of file diff --git a/lib/pages/qr_code_page/qr_code_page_widget.dart b/lib/pages/qr_code_page/qr_code_page_widget.dart index 3d37a4c5..d5a5f0ec 100644 --- a/lib/pages/qr_code_page/qr_code_page_widget.dart +++ b/lib/pages/qr_code_page/qr_code_page_widget.dart @@ -1,3 +1,8 @@ +import 'package:barcode_widget/barcode_widget.dart'; +import 'package:f_r_e_hub/actions/actions.dart'; +import 'package:f_r_e_hub/flutter_flow/custom_functions.dart'; +import 'package:percent_indicator/circular_percent_indicator.dart'; + import '/components/templates_components/qr_code_pass_key_template_component/qr_code_pass_key_template_component_widget.dart'; import '/flutter_flow/flutter_flow_animations.dart'; import '/flutter_flow/flutter_flow_icon_button.dart'; @@ -6,72 +11,91 @@ import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_widgets.dart'; import 'dart:async'; import '/flutter_flow/custom_functions.dart' as functions; -import 'package:barcode_widget/barcode_widget.dart'; +// import 'package:barcode_widget/barcode_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:percent_indicator/percent_indicator.dart'; +// import 'package:percent_indicator/percent_indicator.dart'; import 'qr_code_page_model.dart'; export 'qr_code_page_model.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + + + class QrCodePageWidget extends StatefulWidget { const QrCodePageWidget({super.key}); + @override State createState() => _QrCodePageWidgetState(); } + + class _QrCodePageWidgetState extends State with TickerProviderStateMixin { late QrCodePageModel _model; + final scaffoldKey = GlobalKey(); final animationsMap = {}; - @override - void initState() { - super.initState(); - _model = createModel(context, () => QrCodePageModel()); +@override +void initState() { + super.initState(); + _model = createModel(context, () => QrCodePageModel()); - // On page load action. - SchedulerBinding.instance.addPostFrameCallback((_) async { - if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { - animationsMap['barcodeOnActionTriggerAnimation']!.controller.repeat(); - } - }); + // On page load action. + SchedulerBinding.instance.addPostFrameCallback((_) async { + if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { + animationsMap['barcodeOnActionTriggerAnimation']!.controller.fling(); + } + }); - animationsMap.addAll({ - 'barcodeOnActionTriggerAnimation': AnimationInfo( - trigger: AnimationTrigger.onActionTrigger, - applyInitialState: true, - effectsBuilder: () => [ - VisibilityEffect(duration: 1.ms), - BlurEffect( - curve: Curves.linear, - delay: 0.0.ms, - duration: 600.0.ms, - begin: const Offset(0.0, 0.0), - end: const Offset(4.0, 4.0), - ), - ], - ), - }); - setupAnimations( - animationsMap.values.where((anim) => - anim.trigger == AnimationTrigger.onActionTrigger || - !anim.applyInitialState), - this, - ); - } - - @override - void dispose() { - _model.dispose(); - - super.dispose(); + animationsMap.addAll({ + 'barcodeOnActionTriggerAnimation': AnimationInfo( + trigger: AnimationTrigger.onActionTrigger, + applyInitialState: true, + effectsBuilder: () => [ + VisibilityEffect(duration: 1.ms), + BlurEffect( + curve: Curves.linear, + delay: 0.0.ms, + duration: 600.0.ms, + begin: const Offset(0.0, 0.0), + end: const Offset(10.0, 10.0), + ), + ], + ), + }); + setupAnimations( + animationsMap.values.where((anim) => + anim.trigger == AnimationTrigger.onActionTrigger || + !anim.applyInitialState), + this, + ); + + // // Adicionando um ouvinte de status à animação para reiniciá-la após a conclusão + // animationsMap['barcodeOnActionTriggerAnimation']?.controller.addStatusListener((status) { + // if (status == AnimationStatus.completed) { + // animationsMap['barcodeOnActionTriggerAnimation']!.controller.reset(); + // animationsMap['barcodeOnActionTriggerAnimation']!.controller.forward(); + // } + // }); +} + +@override +void dispose() { + // Removendo o ouvinte antes de chamar super.dispose para evitar vazamentos de memória + if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { + animationsMap['barcodeOnActionTriggerAnimation']!.controller.removeStatusListener((status) {}); } + + super.dispose(); +} @override Widget build(BuildContext context) { @@ -82,66 +106,65 @@ class _QrCodePageWidgetState extends State child: Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - appBar: AppBar( - backgroundColor: FlutterFlowTheme.of(context).primaryBackground, - automaticallyImplyLeading: false, - leading: FlutterFlowIconButton( - borderColor: Colors.transparent, - borderRadius: 30.0, - borderWidth: 1.0, - buttonSize: 60.0, - icon: Icon( - Icons.keyboard_arrow_left, - color: FlutterFlowTheme.of(context).primaryText, - size: 30.0, - ), - onPressed: () async { - context.pop(); - }, - ), - title: Text( - FFLocalizations.of(context).getText( - 'ku7jqe53' /* QR Code de Acesso */, - ), - 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), + appBar: buildAppBar(context), + body: buildBody(context), + ), + ); + } + + Widget buildBody(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + double screenHeight = MediaQuery.of(context).size.height; + double smallerDimension = screenWidth < screenHeight ? screenWidth : screenHeight; + double dimension = smallerDimension * 0.75; + + double totalTimeInSeconds = 100.0; + return SafeArea( + top: true, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (_model.isAccess == true) + Text( + FFLocalizations.of(context).getVariableText( + ptText: 'QR Code de Acesso', + enText: 'Access QR Code', ), - ), - actions: const [], - centerTitle: true, - elevation: 0.0, - ), - body: SafeArea( - top: true, - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (_model.isAccess == true) - Text( - FFLocalizations.of(context).getText( - 'vd84zgfe' /* Use esse QR Code para acesso */, + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + fontSize: 20.0, + letterSpacing: 0.0, + fontWeight: FontWeight.bold, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), + ), + Stack( + children: [ + if (_model.isAccess == true) + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + // this.errorCorrectLevel = 3, + // this.version = 10, + // this.maskPattern = -1, + child: buildQrCode( + data: 'example.com', + type: 'URl', + dimension: dimension, + errorCorrectLevel: QrErrorCorrectLevel.H, + maskPattern: -1, + version: QrVersions.auto, + identifier: FFAppState().userDevUUID, + pass: '12313123', + direction: 5, ), - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: - FlutterFlowTheme.of(context).bodyMediumFamily, - fontSize: 20.0, - letterSpacing: 0.0, - fontWeight: FontWeight.bold, - useGoogleFonts: GoogleFonts.asMap().containsKey( - FlutterFlowTheme.of(context).bodyMediumFamily), - ), ), - Stack( - children: [ - Align( - alignment: const AlignmentDirectional(0.0, 0.0), - child: BarcodeWidget( + if(_model.isAccess == false) + Align( + alignment: const AlignmentDirectional(0, 0), + child: BarcodeWidget( data: 'Barcode', barcode: Barcode.qrCode(), width: 300.0, @@ -156,219 +179,273 @@ class _QrCodePageWidgetState extends State ).animateOnActionTrigger( animationsMap['barcodeOnActionTriggerAnimation']!, ), - ), - if (_model.isAccess == true) - Align( - alignment: const AlignmentDirectional(0.0, 0.0), - child: InkWell( - splashColor: Colors.transparent, - focusColor: Colors.transparent, - hoverColor: Colors.transparent, - highlightColor: Colors.transparent, - onLongPress: () async { - await _model.qrCodeEncoder( - context, - key: _model.key, - ); - setState(() {}); - }, - child: Container( - width: 200.0, - height: 200.0, - decoration: const BoxDecoration(), - child: Align( - alignment: const AlignmentDirectional(0.0, 0.0), - child: FFButtonWidget( - onPressed: () async { - await showModalBottomSheet( - isScrollControlled: true, - backgroundColor: Colors.transparent, - useSafeArea: true, - context: context, - builder: (context) { - return GestureDetector( - onTap: () => _model - .unfocusNode.canRequestFocus - ? FocusScope.of(context) - .requestFocus(_model.unfocusNode) - : FocusScope.of(context).unfocus(), - child: Padding( - padding: - MediaQuery.viewInsetsOf(context), - child: - QrCodePassKeyTemplateComponentWidget( - toggleActionStatus: (key) async { - _model.key = key; - setState(() {}); - }, - ), - ), - ); - }, - ).then((value) => safeSetState(() {})); - - unawaited( - () async { - await _model.qrCodeEncoder( - context, - key: _model.key, - ); - setState(() {}); - }(), - ); - if (animationsMap[ - 'barcodeOnActionTriggerAnimation'] != - null) { - animationsMap[ - 'barcodeOnActionTriggerAnimation']! - .controller - .reverse(); - } - if (animationsMap[ - 'barcodeOnActionTriggerAnimation'] != - null) { - animationsMap[ - 'barcodeOnActionTriggerAnimation']! - .controller - .stop(); - } - _model.isAccess = !_model.isAccess; - setState(() {}); - }, - text: FFLocalizations.of(context).getText( - 'mxdrsbmy' /* Liberar QR Code */, - ), - options: FFButtonOptions( - height: 40.0, - padding: const EdgeInsetsDirectional.fromSTEB( - 24.0, 0.0, 24.0, 0.0), - iconPadding: const EdgeInsetsDirectional.fromSTEB( - 0.0, 0.0, 0.0, 0.0), - color: FlutterFlowTheme.of(context).primary, - textStyle: FlutterFlowTheme.of(context) - .titleSmall - .override( - fontFamily: FlutterFlowTheme.of(context) - .titleSmallFamily, - color: Colors.white, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap() - .containsKey( - FlutterFlowTheme.of(context) - .titleSmallFamily), - ), - elevation: 3.0, - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - ), - ), - ], - ), - if (_model.isAccess == true) - Container( - width: 300.0, - decoration: const BoxDecoration(), - child: Visibility( - visible: _model.isAccess == true, - child: Text( - FFLocalizations.of(context).getText( - '6z6kvmhl' /* Certifique-se de que o QRCode ... */, - ), - style: FlutterFlowTheme.of(context).bodyMedium.override( - fontFamily: - FlutterFlowTheme.of(context).bodyMediumFamily, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey( - FlutterFlowTheme.of(context).bodyMediumFamily), - ), - ), - ), ), - if (_model.isAccess == true) - Container( - width: 250.0, - height: 80.0, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100.0), - border: Border.all( - color: FlutterFlowTheme.of(context).primary, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsetsDirectional.fromSTEB( - 10.0, 0.0, 0.0, 0.0), - child: Text( - FFLocalizations.of(context).getText( - 'wkjkxd2e' /* Trocando QR code em */, + if (_model.isAccess == false) + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: InkWell( + splashColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + highlightColor: Colors.transparent, + onLongPress: () async { + await _model.qrCodeEncoder( + context, + key: _model.key, + ); + setState(() {}); + }, + child: Container( + width: 200.0, + height: 200.0, + decoration: const BoxDecoration(), + child: Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: FFButtonWidget( + onPressed: () async { + await _showQrCodeBottomSheet(context); + _toggleQrCodeAccess(); + }, + text: FFLocalizations.of(context).getText( + 'mxdrsbmy' /* Liberar QR Code */, ), - textAlign: TextAlign.center, - style: FlutterFlowTheme.of(context) - .bodyMedium - .override( - fontFamily: FlutterFlowTheme.of(context) - .bodyMediumFamily, - letterSpacing: 0.0, - fontWeight: FontWeight.w600, - useGoogleFonts: GoogleFonts.asMap() - .containsKey(FlutterFlowTheme.of(context) - .bodyMediumFamily), - ), - ), - ), - ), - Align( - alignment: const AlignmentDirectional(0.0, 0.0), - child: Padding( - padding: const EdgeInsetsDirectional.fromSTEB( - 0.0, 0.0, 20.0, 0.0), - child: CircularPercentIndicator( - percent: functions.getProgressValue(1), - radius: 30.0, - lineWidth: 7.0, - animation: true, - animateFromLastPercent: true, - progressColor: FlutterFlowTheme.of(context).primary, - backgroundColor: - FlutterFlowTheme.of(context).primaryText, - center: Text( - FFLocalizations.of(context).getText( - '3bfr2tjr' /* 20 */, - ), - style: FlutterFlowTheme.of(context) - .headlineSmall + options: FFButtonOptions( + height: 40.0, + padding: const EdgeInsetsDirectional.fromSTEB( + 24.0, 0.0, 24.0, 0.0), + iconPadding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 0.0, 0.0), + color: FlutterFlowTheme.of(context).primary, + textStyle: FlutterFlowTheme.of(context) + .titleSmall .override( fontFamily: FlutterFlowTheme.of(context) - .headlineSmallFamily, - fontSize: 14.0, + .titleSmallFamily, + color: Colors.white, letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap() .containsKey( FlutterFlowTheme.of(context) - .headlineSmallFamily), + .titleSmallFamily), ), + elevation: 3.0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1.0, + ), + borderRadius: BorderRadius.circular(8.0), ), - startAngle: 20.0, ), ), ), - ], + ), + ), + ], + ), + if (_model.isAccess == true) + Container( + width: 300.0, + decoration: const BoxDecoration(), + child: Visibility( + visible: _model.isAccess == false, + child: Text( + FFLocalizations.of(context).getVariableText( + ptText: 'Certifique-se de que o QRCode está visivel para o leitor', + enText: 'Make sure the QRCode is visible to the reader', + // '6z6kvmhl' /* Certifique-se de que o QRCode ... */, + ), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + FlutterFlowTheme.of(context).bodyMediumFamily, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).bodyMediumFamily), + ), ), ), - ], - ), + ), + if (_model.isAccess == true) + Container( + width: 250.0, + height: 80.0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100.0), + border: Border.all( + color: FlutterFlowTheme.of(context).primary, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 10.0, 0.0, 0.0, 0.0), + child: Text( + FFLocalizations.of(context).getVariableText( + enText: 'Changing QR code in', + ptText: 'Trocando QR code em', + // 'wkjkxd2e' /* Trocando QR code em */, + ), + textAlign: TextAlign.center, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .bodyMediumFamily, + letterSpacing: 0.0, + fontWeight: FontWeight.w600, + useGoogleFonts: GoogleFonts.asMap() + .containsKey(FlutterFlowTheme.of(context) + .bodyMediumFamily), + ), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(0.0, 0.0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0.0, 0.0, 20.0, 0.0), + child: StreamBuilder( + stream: functions.getProgressValue(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return CircularProgressIndicator(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else if (!snapshot.hasData) { + return Text('No data'); + } else { + final progress = snapshot.data!; + return CircularPercentIndicator( + percent: progress, + radius: 30.0, + lineWidth: 7.0, + animation: true, + animateFromLastPercent: true, + onAnimationEnd: () { + _resetAnimationAndToggleAccess(); + }, + progressColor: FlutterFlowTheme.of(context).primary, + backgroundColor: FlutterFlowTheme.of(context).primaryText, + center: Text( + '${(progress * totalTimeInSeconds / 5).toStringAsFixed(1)}s', + style: FlutterFlowTheme.of(context).headlineSmall.override( + fontFamily: FlutterFlowTheme.of(context).headlineSmallFamily, + fontSize: 14.0, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineSmallFamily), + ), + ), + startAngle: 20.0, + ); + } + }, + ), + ), + ), + ], + ), + ), + ], ), - ), + ); + } + + void _toggleQrCodeAccess() { + if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { + animationsMap['barcodeOnActionTriggerAnimation']!.controller.stop(); + animationsMap['barcodeOnActionTriggerAnimation']!.controller.reverse(); + } + _model.isAccess = !_model.isAccess; + setState(() {}); +} + + Future _showQrCodeBottomSheet(BuildContext context) async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + useSafeArea: true, + context: context, + builder: (context) { + return GestureDetector( + onTap: () => _model + .unfocusNode.canRequestFocus + ? FocusScope.of(context) + .requestFocus(_model.unfocusNode) + : FocusScope.of(context).unfocus(), + child: Padding( + padding: + MediaQuery.viewInsetsOf(context), + child: + QrCodePassKeyTemplateComponentWidget( + toggleActionStatus: (key) async { + _model.key = key; + setState(() {}); + }, + ), + ), + ); + }, + ).then((value) => safeSetState(() {})); + + unawaited( + () async { + await _model.qrCodeEncoder( + context, + key: _model.key, + ); + setState(() {}); + }(), ); } + + void _resetAnimationAndToggleAccess() { + setState(() { + // Reinicia a animação + animationsMap['barcodeOnActionTriggerAnimation']!.controller.reset(); + animationsMap['barcodeOnActionTriggerAnimation']!.controller.forward(); + // Alterna o estado de acesso + _model.isAccess = !_model.isAccess; + }); +} + + AppBar buildAppBar(BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + leading: FlutterFlowIconButton( + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: FlutterFlowTheme.of(context).primaryText, + size: 30.0, + ), + onPressed: () async { + context.pop(); + }, + ), + title: Text( + FFLocalizations.of(context).getText( + 'ku7jqe53' /* QR Code de Acesso */, + ), + 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), + ), + ), + actions: const [], + centerTitle: true, + elevation: 0.0, + ); + } } 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 55ea5ed2..155fc82c 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 @@ -3,8 +3,6 @@ import 'package:f_r_e_hub/flutter_flow/request_manager.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/form_field_controller.dart'; -import '/flutter_flow/request_manager.dart'; - import 'schedule_complete_visit_page_widget.dart' show ScheduleCompleteVisitPageWidget; import 'package:flutter/material.dart'; @@ -71,23 +69,6 @@ class ScheduleCompleteVisitPageModel TextEditingController? textController3; String? Function(BuildContext, String?)? textController3Validator; - /// Query cache managers for this widget. - - final _visitHistoryManager = FutureRequestManager(); - Future visitHistory({ - String? uniqueQueryKey, - bool? overrideCache, - required Future Function() requestFn, - }) => - _visitHistoryManager.performRequest( - uniqueQueryKey: uniqueQueryKey, - overrideCache: overrideCache, - requestFn: requestFn, - ); - void clearVisitHistoryCache() => _visitHistoryManager.clear(); - void clearVisitHistoryCacheKey(String? uniqueKey) => - _visitHistoryManager.clearRequest(uniqueKey); - @override void initState(BuildContext context) {} @@ -125,4 +106,4 @@ class ScheduleCompleteVisitPageModel return false; } -} +} \ No newline at end of file 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 7b837b20..c5e5385d 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 @@ -100,35 +100,6 @@ class _ScheduleCompleteVisitPageWidgetState _model.switchValue = true; _model.textController3 ??= TextEditingController(); _model.textFieldFocusNode3 ??= FocusNode(); - - - debugPrint('widget.visitStartDateStr: ${DateTime.parse(widget.visitStartDateStr!)}'); - debugPrint('widget.visitEndDateStr: ${DateTime.parse(widget.visitEndDateStr!)}'); - if (widget.visitEndDateStr != null && widget.visitStartDateStr != null) { - _model.datePicked1 = DateTime.parse(widget.visitStartDateStr!); - _model.datePicked2 = DateTime.parse(widget.visitEndDateStr!); - _model.textController1?.text = DateFormat('dd-MM-yyyy HH:mm:ss').format(DateFormat('yyyy-MM-dd HH:mm:ss').parse(widget.visitStartDateStr!)); - _model.textController2?.text = DateFormat('dd-MM-yyyy HH:mm:ss').format(DateFormat('yyyy-MM-dd HH:mm:ss').parse(widget.visitEndDateStr!));; - // _model.textController1?.selection = TextSelection.collapsed( - - // _model.textController1?.text = - // dateTimeFormat( - // 'd/M/y H:mm:ss', - // _model.datePicked1, - // locale: - // FFLocalizations.of(context) - // .languageCode, - // ); - // _model.textController1 - // ?.selection = - // TextSelection.collapsed( - // offset: _model - // .textController1! - // .text - // .length); - // }); - } - } void _loadMoreVisitHistory() async { @@ -406,10 +377,10 @@ Widget scheduleVisit( fadeOutDuration: const Duration( milliseconds: 500), imageUrl: valueOrDefault( - 'https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( + "https://freaccess.com.br/freaccess/getImage.php?devUUID=${FFAppState().devUUID}&userUUID=${FFAppState().userUUID}&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=${getJsonField( visitorListViewItem, r'''$.VTE_DOCUMENTO''', - ).toString()}&tipo=E', + ).toString()}&tipo=E", 'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg', ), fit: BoxFit.cover, @@ -2510,4 +2481,4 @@ Widget visitHistory( ); -} +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 8cfc5a20..799ff761 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + barcode: + dependency: transitive + description: + name: barcode + sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003 + url: "https://pub.dev" + source: hosted + version: "2.2.8" + barcode_widget: + dependency: "direct main" + description: + name: barcode_widget + sha256: ea0c0578b5db3ca3a583d80e05eb47bfb70419e3a23b920d93ae7968c45c20ce + url: "https://pub.dev" + source: hosted + version: "2.0.3" bloc: dependency: transitive description: @@ -949,6 +965,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.1" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + sha256: cec41f67181fbd5322aa68b355621d1a4eea827426b8eeb613f6cbe195ff7b4a + url: "https://pub.dev" + source: hosted + version: "4.2.2" petitparser: dependency: transitive description: @@ -981,6 +1005,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.2" + qr: + dependency: transitive + description: + name: qr + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" responsive_framework: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d22c8f95..48f62948 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -102,6 +102,7 @@ dependencies: cupertino_icons: ^1.0.0 flutter_bloc: ^8.1.6 flutter_riverpod: ^2.5.1 + qr_flutter: ^4.1.0 dependency_overrides: http: 1.2.1