diff --git a/.vscode/launch.json b/.vscode/launch.json index 3bfc4b44..6635646f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,26 +4,34 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { "name": "flutter-freaccesss-hub", "request": "launch", "type": "dart", "args": [ - "--no-enable-impeller" - ] + "--no-enable-impeller", + " --enable-experiment=macros" + ] }, { "name": "flutter-freaccesss-hub (profile mode)", "request": "launch", "type": "dart", - "flutterMode": "profile" + "flutterMode": "profile", + "args": [ + "--no-enable-impeller", + " --enable-experiment=macros" + ] }, { "name": "flutter-freaccesss-hub (release mode)", "request": "launch", "type": "dart", - "flutterMode": "release" + "flutterMode": "release", + "args": [ + "--no-enable-impeller", + " --enable-experiment=macros" + ] } ] } \ No newline at end of file diff --git a/devtools_options.yaml b/devtools_options.yaml index 2bc8e05f..a18a3e2e 100644 --- a/devtools_options.yaml +++ b/devtools_options.yaml @@ -1,4 +1,5 @@ description: This file stores settings for Dart & Flutter DevTools. documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states extensions: - - provider: true \ No newline at end of file + - provider: true + - patrol: true \ No newline at end of file diff --git a/flutter_01.png b/flutter_01.png new file mode 100644 index 00000000..99ac4d5a Binary files /dev/null and b/flutter_01.png differ diff --git a/hx b/hx new file mode 100644 index 00000000..e69de29b diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart index 0d832c65..819ec78c 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -1,5 +1,5 @@ import 'dart:collection'; -import 'dart:math'; +import 'dart:developer'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -26,7 +26,6 @@ import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart import 'package:integration_test/integration_test.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; -import 'package:patrol/patrol.dart'; import 'app_test.dart'; import 'fuzzer/fuzzer.dart'; diff --git a/integration_test/auth_test.dart b/integration_test/auth_test.dart index 185ef039..b1e2ceff 100644 --- a/integration_test/auth_test.dart +++ b/integration_test/auth_test.dart @@ -48,11 +48,11 @@ class AuthenticationTest { await _navigateToSignIn($); for (var credential in credentials) { - print('Função: ${credential.functionName}'); - print('Entradas: ${credential.inputs}'); - print('Saída: ${credential.output}'); - print('Mensagem: ${credential.message}'); - print('---'); + log('Função: ${credential.functionName}'); + log('Entradas: ${credential.inputs}'); + log('Saída: ${credential.output}'); + log('Mensagem: ${credential.message}'); + log('---'); await _auth(credential.output, $, throwsException); } @@ -156,11 +156,11 @@ class AuthenticationTest { await $.pumpWidgetAndSettle(const App()); for (var credential in credentials) { - print('Função: ${credential.functionName}'); - print('Entradas: ${credential.inputs}'); - print('Saída: ${credential.output}'); - print('Mensagem: ${credential.message}'); - print('---'); + log('Função: ${credential.functionName}'); + log('Entradas: ${credential.inputs}'); + log('Saída: ${credential.output}'); + log('Mensagem: ${credential.message}'); + log('---'); await _navigateToSignUp($); await _auth(credential.output, $, throwsException); @@ -255,10 +255,3 @@ Future _submit( _navigateBackUsingSystemGesture(); } } - -String _generateRandomString(int length) { - const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; - final rand = Random(); - return List.generate(length, (index) => chars[rand.nextInt(chars.length)]) - .join(); -} diff --git a/integration_test/menu_test.dart b/integration_test/menu_test.dart index 10b0ab62..a4a5d54b 100644 --- a/integration_test/menu_test.dart +++ b/integration_test/menu_test.dart @@ -68,8 +68,8 @@ class MenuTest { route = entry.key; title = entry.value; - print('route: $route'); - print('title: $title'); + log('route: $route'); + log('title: $title'); if (route == '/petsPage') continue; if (route == '/fastPassPage') continue; @@ -326,7 +326,6 @@ class MenuTest { final Key? widgetKey = entry.key; expect(widgetKey, isNotNull); - print('WIDGETKEY = $widgetKey'); if (widgetKey == ValueKey('FRE-HUB-FASTPASS')) continue; if (widgetKey == ValueKey('FRE-HUB-QRCODE')) continue; if (widgetKey == ValueKey('FRE-HUB-RESERVATIONS')) continue; diff --git a/integration_test/utils_test.dart b/integration_test/utils_test.dart index cce351a2..1fb39e07 100644 --- a/integration_test/utils_test.dart +++ b/integration_test/utils_test.dart @@ -25,7 +25,7 @@ Future _loggedWithMultiLocalsAccount( .set(ProfileStorageKey.ownerUUID.key, '7'); await StorageHelper() // .set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO'); - await PhpGroup // + await FreAccessWSGlobal // .resopndeVinculo .call(tarefa: 'A'); await LicenseRepositoryImpl() // @@ -58,7 +58,7 @@ Future _loggedWithSomeoneLocalAccount( .set(ProfileStorageKey.ownerUUID.key, '7'); await StorageHelper() // .set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO'); - await PhpGroup // + await FreAccessWSGlobal // .resopndeVinculo .call(tarefa: 'A'); await LicenseRepositoryImpl() // diff --git a/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart b/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart index ec1c5af3..c2424e70 100644 --- a/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart +++ b/lib/components/atomic_components/shared_components_atoms/media_upload_button.dart @@ -33,7 +33,7 @@ class _MediaUploadButtonUtilState extends State { @override Widget build(BuildContext context) { double limitedInputTextSize = LimitedFontSizeUtil.getInputFontSize(context); - bool _isLoading = false; + bool isLoading = false; return Builder( builder: (context) { @@ -72,7 +72,7 @@ class _MediaUploadButtonUtilState extends State { child: GestureDetector( onTap: () async { setState(() { - _isLoading = true; + isLoading = true; }); final selectedMedia = await selectMediaWithSourceBottomSheet( @@ -120,7 +120,7 @@ class _MediaUploadButtonUtilState extends State { showUploadMessage(context, message); } else { setState(() { - _isLoading = false; + isLoading = false; }); final message = FFLocalizations.of(context) .getVariableText( @@ -131,7 +131,7 @@ class _MediaUploadButtonUtilState extends State { } } else { setState(() { - _isLoading = false; + isLoading = false; }); } }, @@ -150,7 +150,7 @@ class _MediaUploadButtonUtilState extends State { mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - _isLoading + isLoading ? SizedBox( width: 30.0, height: 30.0, diff --git a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart index 6502afbc..264db202 100644 --- a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart +++ b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart @@ -14,6 +14,7 @@ import 'package:hub/shared/utils/log_util.dart'; import '/flutter_flow/flutter_flow_theme.dart'; +// ignore: must_be_immutable class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget { BottomArrowLinkedLocalsComponentWidget({super.key, required this.response}); ApiCallResponse? response; @@ -76,7 +77,7 @@ class _BottomArrowLinkedLocalsComponentWidgetState Future _fetchLocals() async { try { setState(() => _loading = true); - widget.response = await PhpGroup.getLocalsCall.call(); + widget.response = await FreAccessWSGlobal.getLocalsCall.call(); final bool isError = widget.response?.jsonBody['error']; if (isError) { @@ -148,7 +149,8 @@ class _BottomArrowLinkedLocalsComponentWidgetState Future _fetchResponseLink(String status, String cliID) async { try { await StorageHelper().set(ProfileStorageKey.clientUUID.key, cliID); - var response = await PhpGroup.resopndeVinculo.call(tarefa: status); + var response = + await FreAccessWSGlobal.resopndeVinculo.call(tarefa: status); if (response.jsonBody['error'] == false) { return { @@ -204,7 +206,6 @@ class _BottomArrowLinkedLocalsComponentWidgetState } Widget _item(BuildContext context, dynamic local) { - log('local: ${local['CLI_NOME']}'); return CardItemTemplateComponentWidget( key: ValueKey(local['CLI_NOME']), imagePath: _imagePath(local), diff --git a/lib/components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart b/lib/components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart index 0baeea54..3810f5bb 100644 --- a/lib/components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart +++ b/lib/components/organism_components/schedule_visit_detail/schedule_visit_detail_widget.dart @@ -781,7 +781,7 @@ class _ScheduleVisitDetailWidgetState extends State { IconButton( onPressed: () async { _model.postScheduleVisit = - await PhpGroup.postScheduleVisitCall.call( + await FreAccessWSGlobal.postScheduleVisitCall.call( devDesc: widget.visitObsStr, idVisitante: widget.visitorStrList, dtInicio: @@ -793,13 +793,14 @@ class _ScheduleVisitDetailWidgetState extends State { obs: widget.visitObsStr, ); - if (PhpGroup.postScheduleVisitCall.error( + if (FreAccessWSGlobal.postScheduleVisitCall.error( (_model.postScheduleVisit?.jsonBody ?? ''), ) == false) { context.pop(); } else { - final String? msg = PhpGroup.postScheduleVisitCall.errorMsg( + final String? msg = + FreAccessWSGlobal.postScheduleVisitCall.errorMsg( (_model.postScheduleVisit?.jsonBody ?? ''), ); await DialogUtil.error(context, msg!) diff --git a/lib/components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart b/lib/components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart index d1ad656e..6ddc5984 100644 --- a/lib/components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart +++ b/lib/components/organism_components/up_arrow_linked_locals_component/up_arrow_linked_locals_component_widget.dart @@ -75,7 +75,7 @@ class _UpArrowLinkedLocalsComponentWidgetState ), ), child: FutureBuilder( - future: PhpGroup.getLocalsCall.call(), + future: FreAccessWSGlobal.getLocalsCall.call(), builder: (context, snapshot) { // Customize what your widget looks like when it's loading. if (!snapshot.hasData) { @@ -94,7 +94,7 @@ class _UpArrowLinkedLocalsComponentWidgetState return Builder( builder: (context) { - final eachLocals = (PhpGroup.getLocalsCall + final eachLocals = (FreAccessWSGlobal.getLocalsCall .locais( gridViewGetLocalsResponse.jsonBody, ) diff --git a/lib/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_model.dart b/lib/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_model.dart index 03352151..69e93268 100644 --- a/lib/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_model.dart +++ b/lib/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_model.dart @@ -63,14 +63,14 @@ class AccessNotificationModalTemplateComponentModel }) async { ApiCallResponse? visitRequest; - visitRequest = await PhpGroup.respondeSolicitacaoCall.call( + visitRequest = await FreAccessWSGlobal.respondeSolicitacaoCall.call( referencia: refUUID, tarefa: actionValue, resposta: responseValue, idVisitante: vteUUID, ); - if (PhpGroup.respondeSolicitacaoCall.error( + if (FreAccessWSGlobal.respondeSolicitacaoCall.error( (visitRequest.jsonBody ?? ''), ) == false) { 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 c9034798..53c509aa 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 @@ -5,7 +5,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; -import 'package:material_symbols_icons/symbols.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; @@ -159,6 +158,7 @@ class _CardItemTemplateComponentWidgetState } Widget _generateImage() { + log('img: ${widget.imagePath ?? ''}'); // CachedNetworkImage.evictFromCache(widget.imagePath ?? ''); return ClipRRect( borderRadius: BorderRadius.circular(20), 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 67a21e19..6e78a391 100644 --- a/lib/components/templates_components/details_component/details_component_widget.dart +++ b/lib/components/templates_components/details_component/details_component_widget.dart @@ -67,75 +67,114 @@ class _DetailsComponentWidgetState extends State { // CachedNetworkImage.evictFromCache(widget.imagePath ?? ''); final double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); - return Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width, - maxHeight: MediaQuery.of(context).size.height, - ), - decoration: BoxDecoration( - color: FlutterFlowTheme.of(context).primaryBackground, - borderRadius: const BorderRadius.all(Radius.circular(25.0)), - ), - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox(height: MediaQuery.of(context).size.height * 0.02), - if (widget.imagePath != null && widget.imagePath != '') - Container( - width: MediaQuery.of(context).size.width * 0.3, - height: MediaQuery.of(context).size.width * 0.3, - clipBehavior: Clip.antiAlias, - decoration: const BoxDecoration( - shape: BoxShape.circle, + return Material( + type: MaterialType.transparency, + child: Container( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width, + maxHeight: MediaQuery.of(context).size.height, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).primaryBackground, + borderRadius: const BorderRadius.all(Radius.circular(25.0)), + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * 0.02), + if (widget.imagePath != null && widget.imagePath != '') + Container( + width: MediaQuery.of(context).size.width * 0.3, + height: MediaQuery.of(context).size.width * 0.3, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: CachedNetworkImage( + fadeInDuration: const Duration(milliseconds: 100), + fadeOutDuration: const Duration(milliseconds: 100), + imageUrl: widget.imagePath!, + fit: BoxFit.cover, + useOldImageOnUrlChange: true, + ), ), - child: CachedNetworkImage( - fadeInDuration: const Duration(milliseconds: 100), - fadeOutDuration: const Duration(milliseconds: 100), - imageUrl: widget.imagePath!, - fit: BoxFit.cover, - useOldImageOnUrlChange: true, + if (widget.icon != null && widget.icon != '') + Container( + width: MediaQuery.of(context).size.width * 0.3, + height: MediaQuery.of(context).size.width * 0.3, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: widget.icon!, ), - ), - if (widget.icon != null && widget.icon != '') - Container( - width: MediaQuery.of(context).size.width * 0.3, - height: MediaQuery.of(context).size.width * 0.3, - clipBehavior: Clip.antiAlias, - decoration: const BoxDecoration( - shape: BoxShape.circle, - ), - child: widget.icon!, - ), - SizedBox(height: MediaQuery.of(context).size.height * 0.03), - Row( - children: statusLinkedHashMap.expand((linkedHashMap) { - return linkedHashMap.entries - .map((MapEntry item) { - return Expanded( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: MediaQuery.of(context).size.width * 0.05, - ), - child: TextFormField( - autofocus: false, - canRequestFocus: false, - readOnly: true, - initialValue: item.key, - obscureText: false, - decoration: InputDecoration( - isDense: true, - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: item.value, + SizedBox(height: MediaQuery.of(context).size.height * 0.03), + Row( + children: statusLinkedHashMap.expand((linkedHashMap) { + return linkedHashMap.entries + .map((MapEntry item) { + return Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width * 0.05, + ), + child: TextFormField( + autofocus: false, + canRequestFocus: false, + readOnly: true, + initialValue: item.key, + obscureText: false, + decoration: InputDecoration( + isDense: true, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: item.value, + ), + ), + filled: true, + fillColor: item.value, + // labelText: item.key, + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + fontWeight: FontWeight.bold, + color: FlutterFlowTheme.of(context).info, + letterSpacing: 0.0, + useGoogleFonts: + GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily, + ), + fontSize: limitedBodyFontSize, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context) + .labelMediumFamily, + color: FlutterFlowTheme.of(context).info, + letterSpacing: 0.0, + useGoogleFonts: + GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context) + .labelMediumFamily, + ), + fontSize: limitedBodyFontSize, + ), + focusedBorder: InputBorder.none, + errorBorder: InputBorder.none, + focusedErrorBorder: InputBorder.none, + suffixIcon: Icon( + Icons.info, + color: FlutterFlowTheme.of(context).info, ), ), - filled: true, - fillColor: item.value, - // labelText: item.key, - labelStyle: FlutterFlowTheme.of(context) + style: FlutterFlowTheme.of(context) .labelMedium .override( fontFamily: FlutterFlowTheme.of(context) @@ -149,150 +188,117 @@ class _DetailsComponentWidgetState extends State { ), fontSize: limitedBodyFontSize, ), - hintStyle: FlutterFlowTheme.of(context) - .labelMedium - .override( - fontFamily: FlutterFlowTheme.of(context) - .labelMediumFamily, - color: FlutterFlowTheme.of(context).info, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey( - FlutterFlowTheme.of(context) - .labelMediumFamily, - ), - fontSize: limitedBodyFontSize, - ), - focusedBorder: InputBorder.none, - errorBorder: InputBorder.none, - focusedErrorBorder: InputBorder.none, - suffixIcon: Icon( - Icons.info, - color: FlutterFlowTheme.of(context).info, - ), + textAlign: TextAlign.center, + maxLines: null, + keyboardType: TextInputType.name, + validator: _model.textController1Validator + .asValidator(context), ), - style: FlutterFlowTheme.of(context) - .labelMedium - .override( - fontFamily: FlutterFlowTheme.of(context) - .labelMediumFamily, - fontWeight: FontWeight.bold, - color: FlutterFlowTheme.of(context).info, - letterSpacing: 0.0, - useGoogleFonts: GoogleFonts.asMap().containsKey( + ), + ); + }).toList(); + }).toList(), + ), + SizedBox(height: MediaQuery.of(context).size.height * 0.03), + ListView.builder( + shrinkWrap: true, + itemCount: labelsLinkedHashMap.length, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + String key = labelsLinkedHashMap.keys.elementAt(index); + String value = labelsLinkedHashMap[key]!; + // return Text('key: $key, value: $value'); + return TextFormField( + readOnly: true, + initialValue: value, + 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, + ), + fontSize: limitedBodyFontSize, + ), + decoration: InputDecoration( + labelText: key, + filled: true, + fillColor: FlutterFlowTheme.of(context).primaryBackground, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryBackground, // Change border color here + ), + ), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: FlutterFlowTheme.of(context).labelMediumFamily, - ), - fontSize: limitedBodyFontSize, + color: FlutterFlowTheme.of(context).primaryText, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).labelMediumFamily, ), - textAlign: TextAlign.center, - maxLines: null, - keyboardType: TextInputType.name, - validator: _model.textController1Validator - .asValidator(context), + ), + 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( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryBackground, // Change border color here + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryBackground, // Change border color here + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryBackground, // Change border color here + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context) + .primaryBackground, // Change border color here + ), ), ), ); - }).toList(); - }).toList(), - ), - SizedBox(height: MediaQuery.of(context).size.height * 0.03), - ListView.builder( - shrinkWrap: true, - itemCount: labelsLinkedHashMap.length, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - String key = labelsLinkedHashMap.keys.elementAt(index); - String value = labelsLinkedHashMap[key]!; - // return Text('key: $key, value: $value'); - return TextFormField( - readOnly: true, - initialValue: value, - 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, - ), - fontSize: limitedBodyFontSize, - ), - decoration: InputDecoration( - labelText: key, - filled: true, - fillColor: FlutterFlowTheme.of(context).primaryBackground, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, // Change border color here - ), - ), - 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( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, // Change border color here - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, // Change border color here - ), - ), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, // Change border color here - ), - ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, // Change border color here - ), - ), - ), - ); - }, - ), - SizedBox(height: MediaQuery.of(context).size.height * 0.02), - if (widget.buttons!.isNotEmpty || widget.buttons != null) - OverflowBar( - overflowAlignment: OverflowBarAlignment.center, - alignment: MainAxisAlignment.center, - overflowSpacing: 2, - spacing: 2, - // mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: widget.buttons!, + }, ), - SizedBox(height: MediaQuery.of(context).size.height * 0.02), - ], + SizedBox(height: MediaQuery.of(context).size.height * 0.02), + if (widget.buttons!.isNotEmpty || widget.buttons != null) + OverflowBar( + overflowAlignment: OverflowBarAlignment.center, + alignment: MainAxisAlignment.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/message_notificaion_modal_template_component/message_notification_widget.dart b/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart index 1039a738..733f058e 100644 --- a/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart +++ b/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart @@ -60,8 +60,7 @@ class _MessageNotificationModalTemplateComponentWidgetState @override Widget build(BuildContext context) { double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); - double limitedSubHeaderFontSize = - LimitedFontSizeUtil.getSubHeaderFontSize(context); + LimitedFontSizeUtil.getSubHeaderFontSize(context); return Container( width: MediaQuery.sizeOf(context).width, diff --git a/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart b/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart index 54e96540..783c114d 100644 --- a/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart +++ b/lib/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart @@ -951,9 +951,10 @@ class _ScheduleProvisionalVisitPageWidgetState ? null : () async { try { - model.provVisitSchedule = await PhpGroup - .postProvVisitSchedulingCall - .call( + model.provVisitSchedule = + await FreAccessWSGlobal + .postProvVisitSchedulingCall + .call( data: DateFormat('dd/MM/yyyy HH:mm:ss') .format(DateFormat( 'dd/MM/yyyy HH:mm:ss') @@ -964,7 +965,8 @@ class _ScheduleProvisionalVisitPageWidgetState nome: model.personNameTextController.text, proID: model.ownerUUID, ); - if (PhpGroup.postProvVisitSchedulingCall + if (FreAccessWSGlobal + .postProvVisitSchedulingCall .error((model.provVisitSchedule ?.jsonBody ?? '')) == @@ -982,7 +984,7 @@ class _ScheduleProvisionalVisitPageWidgetState model.notesTextController?.clear(); }); } else { - var message = PhpGroup + var message = FreAccessWSGlobal .postProvVisitSchedulingCall .msg((model.provVisitSchedule ?.jsonBody ?? 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 c3d0ee0b..268d9c3a 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 @@ -46,7 +46,7 @@ class RegisiterVistorTemplateComponentModel Future getVisitanteByDocument( String document, BuildContext context) async { - final response = await PhpGroup.getVisitorByDocCall.call( + final response = await FreAccessWSGlobal.getVisitorByDocCall.call( documento: document, ); 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 b6c71aaf..7cf15002 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 @@ -15,7 +15,6 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_widgets.dart'; import '/flutter_flow/form_field_controller.dart'; -import '/flutter_flow/upload_data.dart'; import 'regisiter_vistor_template_component_model.dart'; export 'regisiter_vistor_template_component_model.dart'; @@ -43,10 +42,6 @@ class _RegisiterVistorTemplateComponentWidgetState final _formKey = GlobalKey(); - void _resetForm() { - _formKey.currentState?.reset(); - } - @override void initState() { super.initState(); @@ -766,7 +761,7 @@ class _RegisiterVistorTemplateComponentWidgetState _model.uploadedLocalFile, ); _model.scheduleVisitor = - await PhpGroup.postScheduleVisitorCall + await FreAccessWSGlobal.postScheduleVisitorCall .call( documento: _model.textController2.text, nome: _model.textController1.text, @@ -781,7 +776,7 @@ class _RegisiterVistorTemplateComponentWidgetState .onError((e, s) async { return await DialogUtil.errorDefault(context); }); - if (PhpGroup.postScheduleVisitorCall.error( + if (FreAccessWSGlobal.postScheduleVisitorCall.error( (_model.scheduleVisitor?.jsonBody ?? ''), ) == false) { @@ -828,8 +823,8 @@ class _RegisiterVistorTemplateComponentWidgetState } else { return await DialogUtil.error( context, - PhpGroup.postScheduleVisitorCall.errorMsg( - _model + FreAccessWSGlobal.postScheduleVisitorCall + .errorMsg(_model .scheduleVisitor?.jsonBody) == null ? FFLocalizations.of(context) @@ -838,7 +833,8 @@ class _RegisiterVistorTemplateComponentWidgetState 'Erro ao se conectar com o servidor', enText: 'Error connecting to server', ) - : PhpGroup.postScheduleVisitorCall + : FreAccessWSGlobal + .postScheduleVisitorCall .errorMsg( _model.scheduleVisitor?.jsonBody) .toString()); diff --git a/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart b/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart index 3ad2c626..be56144e 100644 --- a/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart +++ b/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart @@ -107,9 +107,9 @@ class _SignUpTemplateComponentWidgetState @override Widget build(BuildContext context) { - final MediaQueryData mediaQuery = MediaQuery.of(context); - final double screenWidth = mediaQuery.size.width; - final double screenHeight = mediaQuery.size.height; + // final MediaQueryData mediaQuery = MediaQuery.of(context); + // final double screenWidth = mediaQuery.size.width; + // final double screenHeight = mediaQuery.size.height; double limitedHeaderFontSize = LimitedFontSizeUtil.getHeaderFontSize(context); diff --git a/lib/components/templates_components/view_visit_detail/view_visit_detail_widget.dart b/lib/components/templates_components/view_visit_detail/view_visit_detail_widget.dart index 41f38054..0104c183 100644 --- a/lib/components/templates_components/view_visit_detail/view_visit_detail_widget.dart +++ b/lib/components/templates_components/view_visit_detail/view_visit_detail_widget.dart @@ -818,11 +818,11 @@ class _ViewVisitDetailWidgetState extends State { ), onPressed: () async { _model.deleteVisit = - await PhpGroup.deleteVisitCall.call( + await FreAccessWSGlobal.deleteVisitCall.call( idVisita: widget.visitIdStr, ); - if (PhpGroup.deleteVisitCall.error( + if (FreAccessWSGlobal.deleteVisitCall.error( (_model.deleteVisit?.jsonBody ?? ''), ) == false) { 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 41fe84e8..a6b016c8 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 @@ -406,23 +406,23 @@ class _VisitorSearchModalTemplateComponentWidgetState _model.textController?.selection = TextSelection.collapsed(offset: _model.textController!.text.length); }); - _model.getVisitorByDoc = await PhpGroup.getVisitorByDocCall.call( + _model.getVisitorByDoc = await FreAccessWSGlobal.getVisitorByDocCall.call( documento: _model.textController.text.replaceFirst(RegExp(r'^0+'), '')); - if (PhpGroup.getVisitorByDocCall + if (FreAccessWSGlobal.getVisitorByDocCall .vistanteId((_model.getVisitorByDoc?.jsonBody ?? '')) != '0' && - PhpGroup.getVisitorByDocCall + FreAccessWSGlobal.getVisitorByDocCall .error((_model.getVisitorByDoc?.jsonBody ?? '')) == false && - PhpGroup.getVisitorByDocCall + FreAccessWSGlobal.getVisitorByDocCall .vistanteId((_model.getVisitorByDoc?.jsonBody ?? '')) != null) { String newDoc = _model.textController.text.replaceFirst(RegExp(r'^0+'), ''); bool existDoc = _model.docs.contains(newDoc); if (existDoc == false) { - _model.addToVisitors(PhpGroup.getVisitorByDocCall + _model.addToVisitors(FreAccessWSGlobal.getVisitorByDocCall .visitante((_model.getVisitorByDoc?.jsonBody ?? ''))); safeSetState(() {}); _model.addToDocs( diff --git a/lib/features/auth/authentication_service.dart b/lib/features/auth/authentication_service.dart index 24f5c0c9..88f3acf7 100644 --- a/lib/features/auth/authentication_service.dart +++ b/lib/features/auth/authentication_service.dart @@ -14,7 +14,7 @@ import '../../../flutter_flow/random_data_util.dart'; class AuthenticationService { static Future login(BuildContext context) async { try { - final GetLocalsCall callback = PhpGroup.getLocalsCall; + final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall; final response = await callback.call(); if (response.jsonBody['error']) { @@ -46,7 +46,7 @@ class AuthenticationService { }) async { try { final ApiCallResponse? response; - final LoginCall callback = PhpGroup.loginCall; + final LoginCall callback = FreAccessWSGlobal.loginCall; String deviceDescription = randomString(10, 10, true, false, false); await StorageHelper() .set(SecureStorageKey.deviceDescription.value, deviceDescription); @@ -111,7 +111,7 @@ class AuthenticationService { if ((email != null && email != '') && (passwd != null && passwd != '' && passwd.length > 7) && (name != null && name != '')) { - response = await PhpGroup.registerCall.call( + response = await FreAccessWSGlobal.registerCall.call( name: name, password: passwd, email: email, @@ -137,7 +137,7 @@ class AuthenticationService { } static Future signOut(BuildContext context) async { - await PhpGroup.unregisterDevice.call(); + await FreAccessWSGlobal.unregisterDevice.call(); final Map extra = { kTransitionInfoKey: const TransitionInfo( hasTransition: true, @@ -158,7 +158,7 @@ class AuthenticationService { static Future forgotPassword(BuildContext context, String email) async { try { final ApiCallResponse? response; - final ForgotPasswordCall callback = PhpGroup.forgotPasswordCall; + final ForgotPasswordCall callback = FreAccessWSGlobal.forgotPasswordCall; final String message = FFLocalizations.of(context).getVariableText( enText: "Send E-mail Successful!", ptText: "E-mail Enviado com Sucesso!"); @@ -183,7 +183,8 @@ class AuthenticationService { static Future changePassword( BuildContext context, String email, String password, String token) async { try { - final ApiCallResponse response = await PhpGroup.changePasswordCall + final ApiCallResponse response = await FreAccessWSGlobal + .changePasswordCall .call(email: email, psswd: password, token: token); if (response.jsonBody['error'] == false) { @@ -209,7 +210,7 @@ class AuthenticationService { static Future deleteAccount(BuildContext context) async { String content; try { - await PhpGroup.deleteAccount.call().then((value) async { + await FreAccessWSGlobal.deleteAccount.call().then((value) async { if (value.jsonBody['error'] == false) { content = FFLocalizations.of(context).getVariableText( enText: 'Account deleted successfully', diff --git a/lib/features/backend/api_requests/api_calls.dart b/lib/features/backend/api_requests/api_calls.dart index fd77fd3c..78d1444d 100644 --- a/lib/features/backend/api_requests/api_calls.dart +++ b/lib/features/backend/api_requests/api_calls.dart @@ -1,13 +1,17 @@ +// ignore_for_file: unused_element + import 'dart:async'; import 'dart:convert'; import 'dart:developer'; import 'package:flutter/foundation.dart'; +import 'package:hub/features/documents/documents.dart' as doc; import 'package:hub/features/notification/index.dart'; import 'package:hub/features/storage/index.dart'; import 'package:hub/shared/utils/log_util.dart'; import 'package:hub/shared/utils/validator_util.dart'; +import 'package:hub/shared/widgets.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'api_manager.dart'; @@ -22,7 +26,9 @@ abstract class Api { GetLicense getLicense = GetLicense(); } -class PhpGroup extends Api { +abstract interface class Endpoint {} + +class FreAccessWSGlobal extends Api { static String getBaseUrl() => 'https://freaccess.com.br/freaccess'; static Map headers = {}; static LoginCall loginCall = LoginCall(); @@ -73,6 +79,9 @@ class PhpGroup extends Api { static UpdateVehicle updateVehicle = UpdateVehicle(); static DeleteVehicle deleteVehicle = DeleteVehicle(); static CancelDeleteVehicle cancelDelete = CancelDeleteVehicle(); + static GetPDF getPDF = GetPDF(); + static GetCategories getCategories = GetCategories(); + static GetDocuments getDocuments = GetDocuments(); } class CancelDeleteVehicle { @@ -82,7 +91,7 @@ class CancelDeleteVehicle { required final String model, required final String color, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -124,7 +133,7 @@ class DeleteVehicle { required final String model, required final String color, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -167,7 +176,7 @@ class RegisterVehicle { final String? color, final String? model, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -211,7 +220,7 @@ class UpdateVehicle { final String? color, final String? model, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -246,11 +255,115 @@ class UpdateVehicle { alwaysAllowBody: false, ); } + + static GetCategories getCategories = GetCategories(); + static GetDocuments getDocuments = GetDocuments(); } -class GetProvSchedules { +class GetPDF extends Endpoint { + Future call(final int id) async { + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); + final String devUUID = + (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; + final String userUUID = + (await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? ''; + final String cliUUID = + (await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? ''; + const String atividade = 'visualizarDocumento'; + const String callname = 'getDocumento.php'; + + return Uri.parse( + "$baseUrl/$callname?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=$atividade&documentId=$id"); + } +} + +class GetCategories extends Endpoint { + @override + Future call() async { + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); + final String devUUID = + (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; + final String userUUID = + (await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? ''; + final String cliID = + (await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? ''; + const String atividade = 'listaCategoriasDocumentos'; + const String pageSize = '10'; + // final bool isFiltered = filter != '' && filter != '.*'; + return await ApiManager.instance.makeApiCall( + callName: 'listaCategoriasDocumentos', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + params: { + // if (isFiltered) 'filter': filter, + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'pageSize': pageSize, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + isStreamingApi: false, + alwaysAllowBody: false, + ); + } +} + +class GetDocuments extends Endpoint { + @override + Future call( + final dynamic page, + final Query query, + ) async { + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); + final String devUUID = + (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; + final String userUUID = + (await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? ''; + final String cliID = + (await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? ''; + const String atividade = 'listaDocumentos'; + const String pageSize = '10'; + // final bool isFiltered = filter != '' && filter != '.*'; + // final isCategory = !category; + // final isDescription = !desc.isNullOrEmpty; + return await ApiManager.instance.makeApiCall( + callName: 'listaDocumentos', + apiUrl: '$baseUrl/processRequest.php', + callType: ApiCallType.POST, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + params: { + // if (isFiltered) 'filter': filter, + + 'devUUID': devUUID, + 'userUUID': userUUID, + 'cliID': cliID, + 'atividade': atividade, + 'page': page.toString(), + 'pageSize': pageSize, + if (query is doc.Category) 'categoryId': query.id, + if (query is doc.Document) 'searh': query.description, + }, + bodyType: BodyType.X_WWW_FORM_URL_ENCODED, + returnBody: true, + encodeBodyUtf8: false, + decodeUtf8: false, + cache: false, + isStreamingApi: false, + alwaysAllowBody: false, + ); + } +} + +class GetProvSchedules extends Endpoint { + @override Future call(final String page, final String status) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -286,9 +399,10 @@ class GetProvSchedules { } } -class GetOpenedVisits { +class GetOpenedVisits extends Endpoint { + @override Future call(final String page) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -321,9 +435,10 @@ class GetOpenedVisits { } } -class GetResidentsByProperty { +class GetResidentsByProperty extends Endpoint { + @override Future call(final String page) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = await StorageHelper().get(ProfileStorageKey.devUUID.key) ?? ''; final String userUUID = @@ -355,9 +470,10 @@ class GetResidentsByProperty { } } -class GetVehiclesByProperty { +class GetVehiclesByProperty extends Endpoint { + @override Future call(final String page) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -391,9 +507,10 @@ class GetVehiclesByProperty { static GetLicense getLicense = GetLicense(); } -class GetLicense { +class GetLicense extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -425,9 +542,10 @@ class GetLicense { } } -class UnregisterDevice { +class UnregisterDevice extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -455,9 +573,10 @@ class UnregisterDevice { } } -class DeletePet { +class DeletePet extends Endpoint { + @override Future call({final int? petID = 0}) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -491,7 +610,8 @@ class DeletePet { } } -class UpdatePet { +class UpdatePet extends Endpoint { + @override Future call({ final int? petID, final String? image, @@ -504,7 +624,7 @@ class UpdatePet { final String? size, final String? notes, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -550,12 +670,13 @@ class UpdatePet { } } -class GetPets { +class GetPets extends Endpoint { + @override Future call({ final int? page, final int? pageSize, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -590,9 +711,10 @@ class GetPets { } } -class GetPetPhoto { +class GetPetPhoto extends Endpoint { + @override Future call({final int? petId}) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -626,7 +748,8 @@ class GetPetPhoto { } } -class RegisterPet { +class RegisterPet extends Endpoint { + @override Future call({ final String? image, final String? name, @@ -638,7 +761,7 @@ class RegisterPet { final String? size, final String? notes, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -683,7 +806,8 @@ class RegisterPet { } } -class BuscaEnconcomendas { +class BuscaEnconcomendas extends Endpoint { + @override Future call({ final String? page, final String? pageSize, @@ -698,7 +822,7 @@ class BuscaEnconcomendas { (await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? ''; const String atividade = 'getEncomendas'; - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); return await ApiManager.instance.makeApiCall( callName: 'getEncomendas', @@ -727,7 +851,8 @@ class BuscaEnconcomendas { } } -class CancelaVisita { +class CancelaVisita extends Endpoint { + @override Future call({ final int? idDestino, final int? idVisita, @@ -735,7 +860,7 @@ class CancelaVisita { final String? UsuEmail, final String? DevDesc, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -772,14 +897,15 @@ class CancelaVisita { } } -class DeleteAccount { +class DeleteAccount extends Endpoint { + @override Future call() async { final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = (await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? ''; - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); return await ApiManager.instance.makeApiCall( callName: 'deleteAccount', apiUrl: '$baseUrl/deleteAccount.php', @@ -802,11 +928,12 @@ class DeleteAccount { } } -class ChangePanic { +class ChangePanic extends Endpoint { + @override Future call({ final String? newSenhaPanico, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -841,11 +968,12 @@ class ChangePanic { } } -class ChangePass { +class ChangePass extends Endpoint { + @override Future call({ final String? newSenha, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -880,11 +1008,12 @@ class ChangePass { } } -class RespondeVinculo { +class RespondeVinculo extends Endpoint { + @override Future call({ final String? tarefa, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -917,11 +1046,12 @@ class RespondeVinculo { } } -class ChangeNotifica { +class ChangeNotifica extends Endpoint { + @override Future call({ final String? notifica, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -956,9 +1086,10 @@ class ChangeNotifica { } } -class UpdateIDE { +class UpdateIDE extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -995,9 +1126,10 @@ class UpdateIDE { } } -class UpdToken { +class UpdToken extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1028,9 +1160,10 @@ class UpdToken { } } -class LoginCall { +class LoginCall extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String email = @@ -1078,7 +1211,8 @@ class LoginCall { } } -class RegisterCall { +class RegisterCall extends Endpoint { + @override Future call({ required final String name, required final String email, @@ -1088,7 +1222,7 @@ class RegisterCall { required final String tipo, required final String descricao, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); return await ApiManager.instance.makeApiCall( callName: 'register', @@ -1117,13 +1251,14 @@ class RegisterCall { } } -class ChangePasswordCall { +class ChangePasswordCall extends Endpoint { + @override Future call({ required final String email, required final String token, required final String psswd, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; final String userUUID = @@ -1157,11 +1292,12 @@ class ChangePasswordCall { } } -class ForgotPasswordCall { +class ForgotPasswordCall extends Endpoint { + @override Future call({ final String? email, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); return await ApiManager.instance.makeApiCall( callName: 'forgotPassword', @@ -1184,9 +1320,10 @@ class ForgotPasswordCall { } } -class GetLocalsCall { +class GetLocalsCall extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = await StorageHelper().get(ProfileStorageKey.devUUID.key) ?? ''; @@ -1223,14 +1360,15 @@ class GetLocalsCall { ) as List?; } -class PostScheduleVisitorCall { +class PostScheduleVisitorCall extends Endpoint { + @override Future call({ required final String documento, required final String nome, required final String tipo, required final String foto, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1277,7 +1415,8 @@ class PostScheduleVisitorCall { )); } -class PostScheduleVisitCall { +class PostScheduleVisitCall extends Endpoint { + @override Future call({ final String? devDesc, final String? idVisitante, @@ -1288,7 +1427,7 @@ class PostScheduleVisitCall { final int? idNAC, final String? obs, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1339,13 +1478,14 @@ class PostScheduleVisitCall { )); } -class GetScheduleVisitCall { +class GetScheduleVisitCall extends Endpoint { + @override Future call({ final int? pageSize, final int? pageNumber, final String? chaveBusca, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1620,9 +1760,10 @@ class GetScheduleVisitCall { )); } -class GetDadosCall { +class GetDadosCall extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1866,11 +2007,12 @@ class GetDadosCall { )); } -class GetVisitorByDocCall { +class GetVisitorByDocCall extends Endpoint { + @override Future call({ final String? documento, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1922,12 +2064,13 @@ class GetVisitorByDocCall { )); } -class GetFotoVisitanteCall { +class GetFotoVisitanteCall extends Endpoint { + @override Future call({ final String? documento, final String? tipo, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -1962,14 +2105,15 @@ class GetFotoVisitanteCall { } } -class PostProvVisitSchedulingCall { +class PostProvVisitSchedulingCall extends Endpoint { + @override Future call({ final String? data, final String? motivo, final String? nome, final String? proID, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2016,12 +2160,13 @@ class PostProvVisitSchedulingCall { )); } -class GetVisitsCall { +class GetVisitsCall extends Endpoint { + @override Future call({ final int? pageSize, final int? pageNumber, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2283,11 +2428,12 @@ class GetVisitsCall { .toList(); } -class DeleteVisitCall { +class DeleteVisitCall extends Endpoint { + @override Future call({ final String? idVisita, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2331,9 +2477,10 @@ class DeleteVisitCall { )); } -class GetPessoasLocalCall { +class GetPessoasLocalCall extends Endpoint { + @override Future call() async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2396,14 +2543,15 @@ class GetPessoasLocalCall { .toList(); } -class RespondeSolicitacaoCall { +class RespondeSolicitacaoCall extends Endpoint { + @override Future call({ final String? referencia, final String? tarefa, final String? resposta, final String? idVisitante, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2450,13 +2598,14 @@ class RespondeSolicitacaoCall { )); } -class GetAccessCall { +class GetAccessCall extends Endpoint { + @override Future call({ final String? pageSize, final String? pageNumber, final String? pesTipo, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; @@ -2704,9 +2853,10 @@ class GetAccessCall { .toList(); } -class GetLiberationsCall { +class GetLiberationsCall extends Endpoint { + @override Stream call() { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final StreamController controller = StreamController(); Future.microtask(() async { @@ -2897,13 +3047,14 @@ class GetLiberationsCall { .toList(); } -class GetMessagesCall { +class GetMessagesCall extends Endpoint { + @override Future call({ final String? pageSize, final String? pageNumber, final String? tipoDestino, }) async { - final String baseUrl = PhpGroup.getBaseUrl(); + final String baseUrl = FreAccessWSGlobal.getBaseUrl(); final String devUUID = (await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? ''; diff --git a/lib/features/backend/api_requests/api_manager.dart b/lib/features/backend/api_requests/api_manager.dart index d12c03dd..7f13a68f 100644 --- a/lib/features/backend/api_requests/api_manager.dart +++ b/lib/features/backend/api_requests/api_manager.dart @@ -1,6 +1,5 @@ import 'dart:convert'; import 'dart:core'; -import 'dart:developer'; import 'dart:io'; import 'dart:typed_data'; diff --git a/lib/features/documents/documents.dart b/lib/features/documents/documents.dart new file mode 100644 index 00000000..1373641d --- /dev/null +++ b/lib/features/documents/documents.dart @@ -0,0 +1,788 @@ +import 'dart:developer'; +import 'package:easy_debounce/easy_debounce.dart'; +import 'package:flutter/material.dart'; +import 'package:hub/components/templates_components/details_component/details_component_widget.dart'; +import 'package:hub/features/backend/index.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:hub/shared/extensions.dart'; +import 'package:hub/shared/utils.dart'; +import 'package:hub/shared/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_rx_bloc/flutter_rx_bloc.dart'; +import 'package:rx_bloc/rx_bloc.dart'; +import 'package:rxdart/rxdart.dart' as rx; + +part 'documents.rxb.g.dart'; + +/// ----------------------------------------------- +/// [TypeDefs] ----------------------------------- +/// ----------------------------------------------- + +typedef DocumentKey = GlobalKey; + +/// ----------------------------------------------- +/// [Extensions] --------------------------------- +/// ----------------------------------------------- + +extension ExplicitRxdartStartWithExtension on Stream { + Stream rxdartStartWith(T? value) => + rx.StartWithExtension(this).startWith(value); +} + +/// ----------------------------------------------- +/// [Pages] --------------------------------------- +/// ----------------------------------------------- + +class DocumentPage extends StatefulPage { + const DocumentPage({super.key}); + + @override + State createState() => DocumentPageState(); +} + +class DocumentPageState extends PageState { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return RxBlocMultiBuilder2( + state1: (bloc) => bloc.states.isDocumentSelected, + state2: (bloc) => bloc.states.currentDocument, + bloc: context.read(), + builder: (context, isSelect, current, bloc) { + if (isSelect.hasData && isSelect.data!) { + return _buildDocumentViewScreen(current, bloc); + } else { + return _buildDocumentManagerScreen(); + } + }, + ); + } + + Widget _buildDocumentManagerScreen() { + final model = context.read().model; + + return DocumentManagerScreen( + model: model, + state: this, + ); + } + + Widget _buildDocumentViewScreen( + AsyncSnapshot<(Document, Uri)?> snapshot, DocumentPageBlocType bloc) { + if (snapshot.hasData) { + return DocumentViewerScreen( + doc: snapshot.data!, + bloc: bloc, + ); + } else { + return const Center(child: CircularProgressIndicator()); + } + } +} + +/// ----------------------------------------------- +/// [Screens] ------------------------------------ +/// ----------------------------------------------- + +class DocumentManagerScreen extends StatelessScreen { + final DocumentModel model; + final DocumentPageState state; + + const DocumentManagerScreen({ + super.key, + required this.model, + required this.state, + }); + + @override + Widget build(BuildContext context) { + final String title = FFLocalizations.of(context).getVariableText( + enText: 'Documents', + ptText: 'Documentos', + ); + final theme = FlutterFlowTheme.of(context); + action() => Navigator.pop(context); + + return Scaffold( + backgroundColor: theme.primaryBackground, + appBar: buildAppBar(title, context, action), + body: buildBody(context), + ); + } + + Widget buildBody(BuildContext context) { + const SizedBox space = SizedBox(height: 10); + final controller = EnhancedListViewController( + headerBuilder: model.itemHeaderBuilder, + bodyBuilder: model.itemBodyBuilder, + footerBuilder: model.itemFooterBuilder, + ); + final repository = EnhancedListViewRepository( + fetchHeader: model.generateHeaderItems, + fetchBody: model.generateBodyItems, + fetchFooter: model.generateFooterItems, + ); + + return Column( + children: [ + Expanded( + child: EnhancedListView( + key: model.enhancedListViewKey, + controller: controller, + repository: repository, + ), + ), + ] // + .addToStart(space) + .addToEnd(space), + ); + } +} + +class DocumentViewerScreen extends StatefulScreen { + const DocumentViewerScreen({ + super.key, + required this.doc, + required this.bloc, + }); + + final (Document, Uri) doc; + final DocumentPageBlocType bloc; + + @override + ScreenState createState() => + _DocumentViewerScreenState(); +} + +class _DocumentViewerScreenState extends ScreenState { + @override + void initState() { + super.initState(); + } + + backAction() => widget.bloc.events.unselectDocument(); + + @override + Widget build(BuildContext context) { + final String title = widget.doc.$1.description; + final theme = FlutterFlowTheme.of(context); + final locale = FFLocalizations.of(context); + + infoAction() => DetailsComponentWidget( + buttons: [], + statusHashMap: [ + Map.from({ + widget.doc.$1.description: widget.doc.$1.category.color, + }) + ], + labelsHashMap: Map.from({ + locale.getVariableText( + enText: 'Description', + ptText: 'Descrição', + ): widget.doc.$1.description, + locale.getVariableText( + enText: 'Category', + ptText: 'Categoria', + ): widget.doc.$1.category.title, + if (widget.doc.$1.person.isNotEmpty) + locale.getVariableText( + enText: 'Person', + ptText: 'Pessoa', + ): widget.doc.$1.person, + if (widget.doc.$1.property.isNotEmpty) + locale.getVariableText( + enText: 'Property', + ptText: 'Propriedade', + ): widget.doc.$1.property, + locale.getVariableText( + enText: 'Created At', + ptText: 'Criado em', + ): ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd', widget.doc.$1.createdAt), + locale.getVariableText( + enText: 'Updated At', + ptText: 'Atualizado em', + ): ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd', widget.doc.$1.updatedAt), + }), + ); + + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) => backAction(), + child: Scaffold( + backgroundColor: theme.primaryBackground, + appBar: buildAppBar(title, context, backAction, infoAction), + body: buildBody(context), + ), + ); + } + + Widget buildBody(BuildContext context) { + return ReadView( + title: widget.doc.$1.description, + url: widget.doc.$2.toString(), + onError: backAction, + ); + } +} + +/// ----------------------------------------------- +/// [Models] -------------------------------------- +/// ----------------------------------------------- + +class DocumentModel extends FlutterFlowModel { + final DocumentPageBlocType bloc; + DocumentModel(this.bloc); + + late EnhancedListViewKey + enhancedListViewKey; + late EnhancedCarouselViewKey carouselViewKey; + + late DocumentKey vehicleScreenViewer; + + /// ------------ + + @override + void initState(BuildContext context) { + enhancedListViewKey = + EnhancedListViewKey(); + carouselViewKey = EnhancedCarouselViewKey(); + vehicleScreenViewer = DocumentKey(); + } + + @override + void dispose() { + enhancedListViewKey.currentState?.dispose(); + carouselViewKey.currentState?.dispose(); + vehicleScreenViewer.currentState?.dispose(); + } + + /// ------------ + + /// [Body] + + void onView(Document document, BuildContext context) async { + bloc.events.selectDocument(document); + } + + Widget itemBodyBuilder( + BuildContext context, T item, int index) { + log('ItemBuilder -> $index'); + + return DocumentComponent( + document: item, + onPressed: onView, + ); + } + + Future> generateBodyItems( + int pageKey, int pageSize, Q query) async { + final List error = [null]; + log('Query: ${query is Document}'); + final GetDocuments getDocuments = FreAccessWSGlobal.getDocuments; + final ApiCallResponse newItems = await getDocuments.call(pageKey, query); + + if (newItems.jsonBody == null) return error; + if (newItems.jsonBody['error'] == true) return error; + + final List list = newItems.jsonBody['value']['list']; + + late final List docs = []; + + for (var item in list) { + final String description = item['description']; + final String type = item['type']; + final String category = item['category']['description']; + final String color = item['category']['color']; + final String person = item['person'] ?? ''; + final String property = item['property'] ?? ''; + final String createdAt = item['createdAt']; + final String updatedAt = item['updatedAt']; + final int categoryId = item['category']['id']; + final int documentId = item['id']; + + final doc = Document( + id: documentId, + description: description, + type: type, + category: Category( + id: categoryId, + color: color.toColor(), + title: category, + ), + person: person, + property: property, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + docs.add(doc); + } + + return docs as List; + } + + /// [Footer] + + Widget itemFooterBuilder( + Future> Function() fetchData) => + Builder(builder: (context) { + CategoryComponent categoryItemBuilder(T? item, bool isSelected) { + return CategoryComponent( + category: item! as Category, isSelected: isSelected); + } + + return EnhancedCarouselView( + key: carouselViewKey, + dataProvider: fetchData, + itemBuilder: categoryItemBuilder, + filter: filterByCategory, + showIndicator: true, + ); + }); + + Future> generateFooterItems() async { + final List error = [null]; + + final GetCategories getCategories = FreAccessWSGlobal.getCategories; + final ApiCallResponse newItems = await getCategories.call(); + + if (newItems.jsonBody['error'] == true) return error; + if (newItems.jsonBody == null) return error; + final list = newItems.jsonBody['value'] as List; + late final List cats = []; + for (var item in list) { + final String color = item['color']; + final String title = item['description']; + final int id = item['id']; + + final cat = Category( + id: id, + color: color.toColor(), + title: title, + ); + cats.add(cat); + } + return cats as List; + } + + /// [Header] + + Widget itemHeaderBuilder( + Future> Function() generateHeaderItems) { + return Builder(builder: (context) { + final theme = FlutterFlowTheme.of(context); + final locale = FFLocalizations.of(context); + TextEditingController editingController = TextEditingController(); + return TextFormField( + controller: editingController, + onChanged: (value) => EasyDebounce.debounce( + '_model.keyTextFieldTextController', + const Duration(milliseconds: 500), + () => filterBySearchBar(Document.from(value), context), + ), + cursorColor: theme.primaryText, + showCursor: false, + cursorWidth: 2.0, + cursorRadius: Radius.circular(100), + style: TextStyle( + color: theme.primaryText, + fontSize: 16.0, + decorationColor: Colors.amber, + ), + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + autocorrect: true, + textCapitalization: TextCapitalization.sentences, + decoration: InputDecoration( + prefixIcon: Icon(Icons.search, color: theme.primary), + labelText: locale.getVariableText( + ptText: 'Pesquisar', + enText: 'Search', + ), + labelStyle: TextStyle( + color: theme.primaryText, + fontSize: 16.0, + ), + hintText: locale.getVariableText( + ptText: 'Digite sua pesquisa', + enText: 'Enter your search', + ), + hintStyle: TextStyle( + color: theme.accent2, + fontSize: 14.0, + ), + filled: true, + fillColor: Colors.transparent, + helperStyle: TextStyle( + color: theme.primaryText, + decorationColor: theme.primaryText, + ), + focusColor: theme.primaryText, + contentPadding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), + enabledBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide(color: theme.primaryText), + ), + focusedBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide(color: theme.primaryText), + ), + errorBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide(color: theme.primaryText), + ), + focusedErrorBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide(color: theme.primaryText, width: 2.0), + ), + ), + ); + }); + } + + Future> generateHeaderItems() async { + final SearchField item = SearchField(); + return [item] as List; + } + + /// [Filter] + + void filterBySearchBar(T query, BuildContext context) { + final enhancedListViewState = enhancedListViewKey.currentState; + return enhancedListViewState?.filterBodyItems(query); + } + + void filterByCategory(T? query, BuildContext context) { + final enhancedListViewState = enhancedListViewKey.currentState; + + enhancedListViewState?.filterBodyItems(query); + } + + /// [Exception] + void onFetchError(Object e, StackTrace s) { + DialogUtil.errorDefault(vehicleScreenViewer.currentContext!); + LogUtil.requestAPIFailed( + "proccessRequest.php", "", "Consulta de Veículo", e, s); + } +} + +/// ----------------------------------------------- +/// [BLoCs] --------------------------------------- +/// ----------------------------------------------- + +abstract class DocumentPageBlocEvents { + void selectDocument(Document document); + void unselectDocument(); +} + +abstract class DocumentPageBlocStates { + Stream get isDocumentSelected; + Stream<(Document, Uri)?> get currentDocument; +} + +@RxBloc() +class DocumentPageBloc extends $DocumentPageBloc { + late final DocumentModel model; + + DocumentPageBloc(BuildContext context) { + model = DocumentModel(this); + model.initState(context); + } + + @override + Stream<(Document, Uri)?> _mapToCurrentDocumentState() => _$selectDocumentEvent + .switchMap((event) async* { + final uri = await GetPDF().call(event.id); + yield (event, uri); + }) + .rxdartStartWith(null) + .mergeWith([_$unselectDocumentEvent.map((_) => null)]); + + @override + Stream _mapToIsDocumentSelectedState() => _mapToCurrentDocumentState() + .map((document) => document != null) + .rxdartStartWith(false) + .map((isSelected) => isSelected ?? false); +} + +/// ----------------------------------------------- +/// [Interfaces] --------------------------------- +/// ----------------------------------------------- + +abstract interface class Archive extends Entity {} + +interface class SearchField extends Archive { + SearchField(); +} + +interface class Document extends Archive { + final int id; + final String description; + final String type; + final Category category; + final String person; + final String property; + String createdAt; + String updatedAt; + + Document({ + required this.id, + required this.description, + required this.type, + required this.category, + required this.person, + required this.property, + required this.createdAt, + required this.updatedAt, + }); + + factory Document.from(String desc) => Document( + id: 0, + description: desc, + type: '', + category: Category.fromDesc(''), + person: '', + property: '', + createdAt: '', + updatedAt: '', + ); +} + +interface class Category extends Archive { + final int id; + final Color color; + final String title; + + Category({ + required this.id, + required this.color, + required this.title, + }); + + factory Category.fromDesc(String desc) { + return Category( + id: 0, + color: Colors.transparent, + title: desc, + ); + } + + static Color isSelected() => Colors.black; +} + +/// ----------------------------------------------- +/// [Components] ------------------------------------- +/// ----------------------------------------------- + +// ignore: must_be_immutable +class DocumentComponent extends StatelessComponent { + final Document document; + void Function(Document, BuildContext) onPressed; + + DocumentComponent({ + super.key, + required this.document, + required this.onPressed, + }); + + Tooltip _buildTooltip(String text, Color color, BuildContext context, + BoxConstraints constraints) { + final Color textColor = FlutterFlowTheme.of(context).info; + + final area = (MediaQuery.of(context).size.height + + MediaQuery.of(context).size.width) / + 2; + + final double boxHeight = area * 0.033; + final double boxWidth = area * 0.19; + + return Tooltip( + message: text, + child: Container( + width: boxWidth, + height: boxHeight, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(10), + ), + child: Center( + child: AutoText( + text, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: textColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final Color primaryText = FlutterFlowTheme.of(context).primaryText; + final Color primaryColor = FlutterFlowTheme.of(context).primary; + + final TextStyle textStyleMajor = TextStyle( + color: primaryText, + fontWeight: FontWeight.bold, + ); + final TextStyle textStyleMinor = TextStyle( + color: primaryText, + fontWeight: FontWeight.normal, + fontStyle: FontStyle.italic, + ); + + return Padding( + padding: const EdgeInsets.all(8), + child: LayoutBuilder( + builder: (context, constraints) { + final double boxHeight = constraints.maxHeight > 350 + ? MediaQuery.of(context).size.height * 0.07 + : MediaQuery.of(context).size.height * 2; + final color = document.category.color; + // final color = FlutterFlowTheme.of(context).primary; + final icon = Icons.description; + const space = SizedBox(width: 10); + final description = document.description; + final title = document.category.title; + const double size = 20; + final date = ValidatorUtil.toLocalDateTime( + 'yyyy-MM-dd', + document.updatedAt, + ); + + return Tooltip( + message: description, + child: InkWell( + onTap: () => onPressed(document, context), + enableFeedback: true, + overlayColor: WidgetStateProperty.all(primaryColor), + borderRadius: BorderRadius.circular(10), + child: SizedBox( + height: boxHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: size, + children: [ + // const SizedBox(width: 10), + Icon(icon, color: color), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Tooltip( + message: description, + child: AutoText( + description, + style: textStyleMajor, + overflow: TextOverflow.ellipsis, + ), + ), + Tooltip( + message: date, + child: AutoText( + date, + style: textStyleMinor, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _buildTooltip(title, color, context, constraints), + ], + ), + ), + // const SizedBox(width: 10), + Center( + child: Icon( + Icons.arrow_right, + color: primaryText, + ), + ), + ] // + .addToStart(space) + .addToEnd(space), + ), + ), + ), + ); + }, + ), + ); + } + + DocumentComponent copyWith({ + Document? document, + }) { + return DocumentComponent( + document: document ?? this.document, + onPressed: onPressed, + ); + } +} + +class CategoryComponent extends StatelessComponent { + final Category category; + final bool isSelected; + + const CategoryComponent({ + super.key, + required this.category, + this.isSelected = false, + }); + + @override + Widget build(BuildContext context) { + final backgroundTheme = FlutterFlowTheme.of(context).primaryBackground; + final textTheme = FlutterFlowTheme.of(context).primaryText; + final color = isSelected ? category.color.highlight : category.color; + return ColoredBox( + color: backgroundTheme, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + ), + child: Icon( + Icons.folder, + color: Colors.white, + size: 40, + ), + ), + const SizedBox(height: 8), + Text( + category.title, + style: TextStyle( + color: textTheme, + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/documents/documents.rxb.g.dart b/lib/features/documents/documents.rxb.g.dart new file mode 100644 index 00000000..38bc4c6b --- /dev/null +++ b/lib/features/documents/documents.rxb.g.dart @@ -0,0 +1,70 @@ +// dart format width=80 +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// Generator: RxBlocGeneratorForAnnotation +// ************************************************************************** + +part of 'documents.dart'; + +/// Used as a contractor for the bloc, events and states classes +/// @nodoc +abstract class DocumentPageBlocType extends RxBlocTypeBase { + DocumentPageBlocEvents get events; + DocumentPageBlocStates get states; +} + +/// [$DocumentPageBloc] extended by the [DocumentPageBloc] +/// @nodoc +abstract class $DocumentPageBloc extends RxBlocBase + implements + DocumentPageBlocEvents, + DocumentPageBlocStates, + DocumentPageBlocType { + final _compositeSubscription = rx.CompositeSubscription(); + + /// Тhe [Subject] where events sink to by calling [selectDocument] + final _$selectDocumentEvent = rx.PublishSubject(); + + /// Тhe [Subject] where events sink to by calling [unselectDocument] + final _$unselectDocumentEvent = rx.PublishSubject(); + + /// The state of [isDocumentSelected] implemented in + /// [_mapToIsDocumentSelectedState] + late final Stream _isDocumentSelectedState = + _mapToIsDocumentSelectedState(); + + /// The state of [currentDocument] implemented in [_mapToCurrentDocumentState] + late final Stream<(Document, Uri)?> _currentDocumentState = + _mapToCurrentDocumentState(); + + @override + void selectDocument(Document document) => _$selectDocumentEvent.add(document); + + @override + void unselectDocument() => _$unselectDocumentEvent.add(null); + + @override + Stream get isDocumentSelected => _isDocumentSelectedState; + + @override + Stream<(Document, Uri)?> get currentDocument => _currentDocumentState; + + Stream _mapToIsDocumentSelectedState(); + + Stream<(Document, Uri)?> _mapToCurrentDocumentState(); + + @override + DocumentPageBlocEvents get events => this; + + @override + DocumentPageBlocStates get states => this; + + @override + void dispose() { + _$selectDocumentEvent.close(); + _$unselectDocumentEvent.close(); + _compositeSubscription.dispose(); + super.dispose(); + } +} diff --git a/lib/features/history/presentation/pages/acess_history_page_widget.dart b/lib/features/history/presentation/pages/acess_history_page_widget.dart index bb6a8891..f49fb1d5 100644 --- a/lib/features/history/presentation/pages/acess_history_page_widget.dart +++ b/lib/features/history/presentation/pages/acess_history_page_widget.dart @@ -201,7 +201,7 @@ class _AccessHistoryState extends State { Future fetchAccessHistoryService() async { try { setState(() => _loading = true); - var response = await PhpGroup.getAccessCall.call( + var response = await FreAccessWSGlobal.getAccessCall.call( pageSize: _pageSize.toString(), pageNumber: _pageNumber.toString(), pesTipo: _personType != 'E' && _personType != 'O' ? 'T' : _personType, diff --git a/lib/features/history/presentation/pages/provisional_history_page.dart b/lib/features/history/presentation/pages/provisional_history_page.dart index e4bfde25..bfaca8cf 100644 --- a/lib/features/history/presentation/pages/provisional_history_page.dart +++ b/lib/features/history/presentation/pages/provisional_history_page.dart @@ -222,8 +222,8 @@ class ProvisionalHistoryState extends State { Future fetchHistoryService() async { try { setState(() => _loading = true); - var response = - await PhpGroup.getProvSchedules(_pageNumber.toString(), status); + var response = await FreAccessWSGlobal.getProvSchedules( + _pageNumber.toString(), status); final List history = response.jsonBody['agendamento']['value'] ?? []; @@ -350,6 +350,7 @@ class ProvisionalHistoryState extends State { ); } + // ignore: unused_element String _imageUrlAtomWidget(String document, String type) { return valueOrDefault( "https://freaccess.com.br/freaccess/getImage.php?&cliID=&atividade=getFoto&Documento=$document&tipo=$type", @@ -404,6 +405,7 @@ class ProvisionalHistoryState extends State { } Map _getStatusMap(BuildContext context, dynamic json) { + // ignore: unused_local_variable late Map statusColorMap; log(DateTime.parse(json['AGP_DT_VISITA']).toString()); log(DateTime.now().toString()); diff --git a/lib/features/history/presentation/widgets/access_filter_modal.dart b/lib/features/history/presentation/widgets/access_filter_modal.dart index 1346fe8b..7ce32e33 100644 --- a/lib/features/history/presentation/widgets/access_filter_modal.dart +++ b/lib/features/history/presentation/widgets/access_filter_modal.dart @@ -187,6 +187,7 @@ class _AccessFilterState extends State { ); } + // ignore: unused_element void _updateSelection(String? value, String key) { setState(() { if (value == '.') { diff --git a/lib/features/home/presentation/pages/about_system.dart b/lib/features/home/presentation/pages/about_system.dart index 2e99ba46..36fb77e5 100644 --- a/lib/features/home/presentation/pages/about_system.dart +++ b/lib/features/home/presentation/pages/about_system.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -8,8 +7,6 @@ import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/shared/utils/log_util.dart'; -import 'package:stack_trace/stack_trace.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/lib/features/home/presentation/widgets/drawer_widget.dart b/lib/features/home/presentation/widgets/drawer_widget.dart index 014fa9f8..d71d58b9 100644 --- a/lib/features/home/presentation/widgets/drawer_widget.dart +++ b/lib/features/home/presentation/widgets/drawer_widget.dart @@ -136,6 +136,7 @@ class DrawerWidget extends StatelessWidget { ); } + // ignore: unused_element Padding _buildSearchBar(BuildContext context, HomeState state) { final theme = FlutterFlowTheme.of(context); final errorColor = theme.error; diff --git a/lib/features/local/data/data_sources/locals_local_data_source.dart b/lib/features/local/data/data_sources/locals_local_data_source.dart index c63aec38..80e97bdc 100644 --- a/lib/features/local/data/data_sources/locals_local_data_source.dart +++ b/lib/features/local/data/data_sources/locals_local_data_source.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:hub/features/storage/constants/locals_constants.dart'; import 'package:hub/features/storage/index.dart'; import 'package:sqflite/sqflite.dart'; @@ -75,7 +74,7 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource { await DatabaseService.database .delete(LocalsConstants.tableLocalsKeychain); } catch (e, s) { - log('() => clearAll keychain: $e', stackTrace: s); + log('() => clearAll keychain: $e stackTrace: $s'); } } } diff --git a/lib/features/local/data/data_sources/locals_remote_data_source.dart b/lib/features/local/data/data_sources/locals_remote_data_source.dart index a40883cf..c991ed37 100644 --- a/lib/features/local/data/data_sources/locals_remote_data_source.dart +++ b/lib/features/local/data/data_sources/locals_remote_data_source.dart @@ -32,22 +32,15 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { @override Future linkLocal(BuildContext context) async { try { - final GetLocalsCall callback = PhpGroup.getLocalsCall; + final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall; var response = await callback.call(); - final bool? isError = response.jsonBody['error']; + if (response.jsonBody == null) return; + final bool? isError = response.jsonBody['error']; if (isError == true) { LocalUtil.handleError(context, response.jsonBody['error_msg']); return; } - if (response.jsonBody == null) { - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); - // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); - return; - } final List locals = response.jsonBody['locais'] ?? []; final bool isEmpty = locals.isEmpty; @@ -70,9 +63,9 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { @override Future processLocals(BuildContext context) async { - log('() => processLocals'); + log('-> processLocals'); try { - final GetLocalsCall callback = PhpGroup.getLocalsCall; + final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall; final ApiCallResponse response = await callback.call(); final bool? isError = response.jsonBody['error']; @@ -82,10 +75,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { return false; } if (response.jsonBody == null) { - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Verify your connection', + // ptText: 'Verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } @@ -114,36 +107,35 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { } else if (isEnabled) { return await LocalUtil.handleEnabled(context, locals[0]); } else if (isUnselected) { - log('() => isUnselected'); + log('-> isUnselected'); return await selectLocal(context, response); } else if (isSelected) { - log('() => isSelected'); + log('-> isSelected'); return await processProperty(context).then((v) async { if (v == true) return await LicenseRepositoryImpl().updateLicense(); return v; }); } else if (isAvailable) { - log('() => isAvailable'); + log('-> isAvailable'); return await processProperty(context).then((v) async { if (v == true) return await LicenseRepositoryImpl().updateLicense(); return v; }); } else { - if (!isUnique && !isActive) log('() => not unique and not active'); - if (!isUnique && isInactived) log('() => not unique and inactived'); - if (!isUnique && isPending) log('() => not unique and pending'); - if (!isUnique && isBlocked) log('() => not unique and blocked'); - log('() => else'); + if (!isUnique && !isActive) log('-> not unique and not active'); + if (!isUnique && isInactived) log('-> not unique and inactived'); + if (!isUnique && isPending) log('-> not unique and pending'); + if (!isUnique && isBlocked) log('-> not unique and blocked'); + log('-> else'); return await selectLocal(context, response); } } catch (e, s) { - log('() => stack: $s'); - log('() => catch: $e', stackTrace: s); + log('-> catch: $e', stackTrace: s); // return await selectLocal(context); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Error getting locals, verify your connection', - ptText: 'Erro ao obter locais, verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Error getting locals, verify your connection', + // ptText: 'Erro ao obter locais, verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null)); return false; } @@ -163,25 +155,25 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { @override Future processProperty(BuildContext context) async { try { - final GetDadosCall callback = PhpGroup.getDadosCall; + final GetDadosCall callback = FreAccessWSGlobal.getDadosCall; ApiCallResponse? response = await callback.call(); if (response.jsonBody == null) { - final GetLocalsCall callback = PhpGroup.getLocalsCall; + final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall; response = await callback.call(); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Verify your connection', + // ptText: 'Verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } final bool? isError = response.jsonBody['error']; if (isError == true) { - final GetLocalsCall callback = PhpGroup.getLocalsCall; + final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall; response = await callback.call(); - final String errorMsg = - response.jsonBody['error_msg'] ?? 'Local indisponível'; + // final String errorMsg = + // response.jsonBody['error_msg'] ?? 'Local indisponível'; // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } else { @@ -189,11 +181,11 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { return true; } } catch (e, s) { - log('() => error processData: $e', stackTrace: s); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Error getting data, verify your connection', - ptText: 'Erro ao obter dados, verifique sua conexão', - ); + log('-> error processData: $e', stackTrace: s); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Error getting data, verify your connection', + // ptText: 'Erro ao obter dados, verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null)); return false; } @@ -231,8 +223,9 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { enText: 'Device unlinked successfully', ptText: 'Dispositivo desvinculado com sucesso', ); - final bool status = - await PhpGroup.resopndeVinculo.call(tarefa: 'I').then((value) async { + final bool status = await FreAccessWSGlobal.resopndeVinculo + .call(tarefa: 'I') + .then((value) async { if (value.jsonBody['error'] == false) { await StorageHelper().set(ProfileStorageKey.clientName.key, ''); await StorageHelper().set(ProfileStorageKey.ownerName.key, ''); diff --git a/lib/features/local/data/repositories/locals_repository_impl.dart b/lib/features/local/data/repositories/locals_repository_impl.dart index a7245383..71956dae 100644 --- a/lib/features/local/data/repositories/locals_repository_impl.dart +++ b/lib/features/local/data/repositories/locals_repository_impl.dart @@ -106,6 +106,7 @@ class LocalsRepositoryImpl implements LocalsRepository { await DialogUtil.error(context, errorMsg); } + // ignore: unused_element Future _notifyBlocs(BuildContext context) async { context.read().add(LocalProfileEvent()); context.read().add(MenuEvent()); diff --git a/lib/features/local/utils/local_util.dart b/lib/features/local/utils/local_util.dart index 783e7fa7..c555238e 100644 --- a/lib/features/local/utils/local_util.dart +++ b/lib/features/local/utils/local_util.dart @@ -52,7 +52,7 @@ class LocalUtil { await StorageHelper() .set(ProfileStorageKey.ownerName.key, locals[0]['CLU_OWNER_DSC']); - var response = await PhpGroup.resopndeVinculo.call(tarefa: 'A'); + var response = await FreAccessWSGlobal.resopndeVinculo.call(tarefa: 'A'); if (response.jsonBody['error'] == true) { await StorageHelper().set(ProfileStorageKey.clientUUID.key, ''); await StorageHelper().set(ProfileStorageKey.ownerUUID.key, ''); diff --git a/lib/features/menu/presentation/blocs/menu_bloc.dart b/lib/features/menu/presentation/blocs/menu_bloc.dart index dc384bf0..c5eddf2d 100644 --- a/lib/features/menu/presentation/blocs/menu_bloc.dart +++ b/lib/features/menu/presentation/blocs/menu_bloc.dart @@ -37,7 +37,8 @@ class MenuBloc extends Bloc { } Future _onMenuEvent(MenuEvent event, Emitter emit) async { - await LicenseRemoteDataSourceImpl(PhpGroup()).waitForSaveCompletion(); + await LicenseRemoteDataSourceImpl(FreAccessWSGlobal()) + .waitForSaveCompletion(); final List newEntries = await MenuRepositoryImpl().entries2Items(entries, item); diff --git a/lib/features/menu/presentation/mappers/menu_entry.dart b/lib/features/menu/presentation/mappers/menu_entry.dart index 3398b0ae..4715118c 100644 --- a/lib/features/menu/presentation/mappers/menu_entry.dart +++ b/lib/features/menu/presentation/mappers/menu_entry.dart @@ -204,6 +204,16 @@ class MenuEntry implements BaseModule { route: '/messageHistoryPage', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), + MenuEntry( + key: 'FRE-HUB-DOCUMENT', + icon: Icons.description, + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( + ptText: 'Documentos', + enText: 'Documents', + ), + route: '/documentPage', + types: [MenuEntryType.Home, MenuEntryType.Drawer], + ), MenuEntry( key: 'FRE-HUB-ABOUT-PROPERTY', icon: Icons.home, diff --git a/lib/features/module/data/repositories/license_repository_impl.dart b/lib/features/module/data/repositories/license_repository_impl.dart index c578608f..3d7068b4 100644 --- a/lib/features/module/data/repositories/license_repository_impl.dart +++ b/lib/features/module/data/repositories/license_repository_impl.dart @@ -17,7 +17,7 @@ class LicenseRepositoryImpl implements LicenseRepository { LicenseRepositoryImpl([Database? database, Api? api]) : database = database ?? DatabaseService.database, - api = api ?? PhpGroup() { + api = api ?? FreAccessWSGlobal() { localDataSource = LicenseLocalDataSourceImpl(this.database); remoteDataSource = LicenseRemoteDataSourceImpl(this.api); } diff --git a/lib/features/module/domain/entities/license.dart b/lib/features/module/domain/entities/license.dart index dde5fee0..91c88e43 100644 --- a/lib/features/module/domain/entities/license.dart +++ b/lib/features/module/domain/entities/license.dart @@ -26,7 +26,8 @@ enum LicenseKeys { people('FRE-HUB-PEOPLE'), petsHistory('FRE-HUB-PETS-HISTORY'), settings('FRE-HUB-SETTINGS'), - logout('FRE-HUB-LOGOUT'); + logout('FRE-HUB-LOGOUT'), + document('FRE-HUB-DOCUMENT'); final String value; const LicenseKeys(this.value); @@ -138,6 +139,13 @@ class License { startDate: '', quantity: 0, ), + Module( + key: LicenseKeys.document.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), Module( key: LicenseKeys.openedVisits.value, display: isNewVersionWithModule diff --git a/lib/features/notification/deep_link_service.dart b/lib/features/notification/deep_link_service.dart index 77792519..003f1903 100644 --- a/lib/features/notification/deep_link_service.dart +++ b/lib/features/notification/deep_link_service.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; import 'package:hub/features/storage/index.dart'; @@ -21,7 +22,7 @@ class DeepLinkService { if (_isInitialized) return; try { _appLinks = AppLinks(); - print('initDeepLinks'); + log('initDeepLinks'); _linkSubscription = _appLinks.uriLinkStream.listen((uri) async { if (!StorageHelper().isRecovered) { await _handleDeepLink(uri); @@ -29,25 +30,25 @@ class DeepLinkService { }); _isInitialized = true; } catch (e) { - print('Error initializing deep links: $e'); + log('Error initializing deep links: $e'); } } Future _handleDeepLink(Uri uri) async { try { - print('Handling deep link: $uri'); + log('Handling deep link: $uri'); if (StorageHelper().isRecovered) return; StorageHelper().isRecovered = true; final email = uri.queryParameters['email'] ?? ''; final token = uri.queryParameters['token'] ?? ''; - print('email: $email, token: $token'); + log('email: $email, token: $token'); if (email.isNotEmpty && token.isNotEmpty) { await _showForgotPasswordScreen(email, token); } } catch (e, s) { - print('Error handling deep link: $e, $s'); + log('Error handling deep link: $e, $s'); } } @@ -72,11 +73,11 @@ class DeepLinkService { enableDrag: true, ).whenComplete(() { StorageHelper().isRecovered = false; - print('showModalBottomSheet completed'); + log('showModalBottomSheet completed'); }); }); } catch (e, s) { - print('Error showing forgot password screen: $e, $s'); + log('Error showing forgot password screen: $e, $s'); } } diff --git a/lib/features/notification/firebase_messaging_service.dart b/lib/features/notification/firebase_messaging_service.dart index 68fc300a..60fb2fa3 100644 --- a/lib/features/notification/firebase_messaging_service.dart +++ b/lib/features/notification/firebase_messaging_service.dart @@ -48,7 +48,7 @@ class FirebaseMessagingService { await StorageHelper().set(SecureStorageKey.token.value, deviceToken); final ApiCallResponse? response; - response = await PhpGroup.updToken.call(); + response = await FreAccessWSGlobal.updToken.call(); if (response.jsonBody['error'] == false) { log('Token Atualizado com Sucesso!'); diff --git a/lib/features/notification/notification_service.dart b/lib/features/notification/notification_service.dart index 8c7b423c..610c83d4 100644 --- a/lib/features/notification/notification_service.dart +++ b/lib/features/notification/notification_service.dart @@ -25,7 +25,8 @@ Future onMessageReceived( required String? response, required String? id}) async { final ApiCallResponse? respondeSolicitacaoCall; - final RespondeSolicitacaoCall callback = PhpGroup.respondeSolicitacaoCall; + final RespondeSolicitacaoCall callback = + FreAccessWSGlobal.respondeSolicitacaoCall; respondeSolicitacaoCall = await callback.call( referencia: ref, diff --git a/lib/features/storage/enums/shared_storage_key.dart b/lib/features/storage/enums/shared_storage_key.dart index 7cd1dc3e..2f615f4f 100644 --- a/lib/features/storage/enums/shared_storage_key.dart +++ b/lib/features/storage/enums/shared_storage_key.dart @@ -9,8 +9,6 @@ extension SharedPreferencesKeyExtension on SharedPreferencesKey { switch (this) { case SharedPreferencesKey.isFirstRun: return 'fre_isFirstRun'; - default: - return ''; } } } diff --git a/lib/features/storage/services/database_storage_service.dart b/lib/features/storage/services/database_storage_service.dart index 813e09e9..d27bb2cc 100644 --- a/lib/features/storage/services/database_storage_service.dart +++ b/lib/features/storage/services/database_storage_service.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:hub/features/module/index.dart'; import 'package:hub/features/storage/index.dart'; import 'package:sqflite/sqflite.dart'; @@ -33,29 +35,29 @@ class DatabaseService { onOpen: _onOpen, onConfigure: _onConfigure, ); - print('Database initialized'); + log('Database initialized'); await LicenseRepositoryImpl().updateLicense(); isInitialized = true; } Future _onConfigure(Database database) async { - print('Configuring database...'); + log('Configuring database...'); } Future _onOpen(Database database) async { - print('Opening database...'); + log('Opening database...'); await _executePragmas(database); } Future _onCreate(Database database, int version) async { - print('Creating database...'); + log('Creating database...'); await database.execute(createKeychainTable); await _onUpgrade(database, 1, _dbVersion); } Future _onUpgrade( Database database, int oldVersion, int newVersion) async { - print('Upgrading database from version $oldVersion to $newVersion...'); + log('Upgrading database from version $oldVersion to $newVersion...'); if (oldVersion < 2 && newVersion >= 2) { await database.execute(LicenseConstants.createLicenseTable); await database.execute(LicenseConstants.updatePetsHistoryTrigger); @@ -70,7 +72,7 @@ class DatabaseService { Future _onDowngrade( Database database, int oldVersion, int newVersion) async { - print('Downgrading database from version $oldVersion to $newVersion...'); + log('Downgrading database from version $oldVersion to $newVersion...'); if (oldVersion >= 2 && newVersion < 2) { await database.execute(LicenseConstants.deleteLicenseTable); await database.execute(LicenseConstants.dropPeopleDisplayTrigger); diff --git a/lib/flutter_flow/custom_functions.dart b/lib/flutter_flow/custom_functions.dart index 231eef12..ed8fcd2d 100644 --- a/lib/flutter_flow/custom_functions.dart +++ b/lib/flutter_flow/custom_functions.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:math' as math; +import 'dart:developer' as dev; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -50,7 +51,7 @@ Future> stringToMap(String v) async { }), )); } catch (e) { - print('Error parsing string to map: $e'); + dev.log('Error parsing string to map: $e'); return Future.value({}); } } diff --git a/lib/flutter_flow/flutter_flow_theme.dart b/lib/flutter_flow/flutter_flow_theme.dart index d178b517..b331757e 100644 --- a/lib/flutter_flow/flutter_flow_theme.dart +++ b/lib/flutter_flow/flutter_flow_theme.dart @@ -158,7 +158,7 @@ class LightModeTheme extends FlutterFlowTheme { late Color primary = const Color(0xFF1AAB5F); late Color secondary = const Color(0xFFB59E9E); - late Color tertiary = const Color(0xFF984BB6); + late Color tertiary = const Color(0xFF000000); late Color alternate = const Color(0xFFF2F2F2); late Color alternate2 = const Color(0xFF232323); late Color primaryText = const Color(0xFF000000); @@ -192,7 +192,7 @@ class DarkModeTheme extends FlutterFlowTheme { late Color primary = const Color(0xFF1AAB5F); late Color secondary = const Color(0xFF18AA99); - late Color tertiary = const Color(0xFF984BB6); + late Color tertiary = const Color(0xFF000000); late Color alternate = const Color(0xFF232323); late Color alternate2 = const Color(0xFF171717); late Color primaryText = const Color(0xFFFFFFFF); diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 6da3a666..e42b6c74 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -3,7 +3,9 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_rx_bloc/flutter_rx_bloc.dart'; import 'package:hub/features/backend/index.dart'; +import 'package:hub/features/documents/documents.dart'; import 'package:hub/features/history/index.dart'; import 'package:hub/features/home/index.dart'; import 'package:hub/features/local/index.dart'; @@ -298,6 +300,29 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { return PetsPageWidget(pet: pet); }, ), + FFRoute( + name: 'documentPage', + path: '/documentPage', + builder: (context, params) { + return RxBlocProvider( + create: (context) => DocumentPageBloc(context), + child: DocumentPage(), + ); + }, + ), + // FFRoute( + // name: 'documentViewerScreen', + // path: '/documentViewerScreen', + // builder: (context, params) { + // final Document doc = params.getParam('doc', ParamType.Function); + // final Uri uri = params.getParam('uri', ParamType.Function); + // return DocumentViewScreen( + // key: UniqueKey(), + // doc: (doc, + // uri: uri, + // ); + // }, + // ), // FFRoute(name: 'settingsPage', path: '/settingsPage', builder: (context, params) => params.isEmpty ? const NavBarPage(initialPage: 'settingsPage') : const SettingsPageWidget()) ].map((r) => r.toRoute(appStateNotifier)).toList(), ); diff --git a/lib/flutter_flow/nav/serialization_util.dart b/lib/flutter_flow/nav/serialization_util.dart index a4d36fd0..94a8350b 100644 --- a/lib/flutter_flow/nav/serialization_util.dart +++ b/lib/flutter_flow/nav/serialization_util.dart @@ -218,9 +218,6 @@ dynamic deserializeParam( case ParamType.Enum: return deserializeEnum(param); - - default: - return null; } } catch (e) { return null; diff --git a/lib/initialization.dart b/lib/initialization.dart index e420c331..f579c7cf 100644 --- a/lib/initialization.dart +++ b/lib/initialization.dart @@ -44,21 +44,21 @@ Future _initializeAppTrackingTransparency() async { } Future _initializeFirebase() async { - print('Initializing Firebase...'); + log('Initializing Firebase...'); await Firebase.initializeApp(); - print('Firebase initialized'); + log('Firebase initialized'); } Future _initializeNotificationService() async { - print('Initializing Notification Service...'); + log('Initializing Notification Service...'); await NotificationService.initialize(); - print('Notification Service initialized'); + log('Notification Service initialized'); } Future _initializeUrlStrategy() async { print('Initializing URL Strategy...'); setUrlStrategy(PathUrlStrategy()); - print('URL Strategy initialized'); + log('URL Strategy initialized'); } Future _initializeSystemSettings() async { @@ -71,7 +71,18 @@ Future _initializeSystemSettings() async { print('Debug mode'); await crashlyticsInstance.setCrashlyticsCollectionEnabled(false); } else { - print('Release mode'); + log('Release mode'); + + // bool unsentReports = + // await FirebaseCrashlytics.instance.checkForUnsentReports(); + // if (unsentReports) { + // // Existem relatórios não enviados + // await crashlyticsInstance.sendUnsentReports(); + // log('Existem relatórios de falhas não enviados.'); + // } else { + // // Não existem relatórios não enviados + // log('Todos os relatórios de falhas foram enviados.'); + // } await crashlyticsInstance.setCrashlyticsCollectionEnabled(true); if (crashlyticsInstance.isCrashlyticsCollectionEnabled) { @@ -94,15 +105,15 @@ Future _initializeSystemSettings() async { } Future _initializeFlutterFlow() async { - print('Initializing FlutterFlow...'); + log('Initializing FlutterFlow...'); await FlutterFlowTheme.initialize(); await FFLocalizations.initialize(); - print('FlutterFlow initialized'); + log('FlutterFlow initialized'); } Future _initializeNav() async { - print('Initializing Nav...'); + log('Initializing Nav...'); GoRouter.optionURLReflectsImperativeAPIs = true; usePathUrlStrategy(); - print('Nav initialized'); + log('Nav initialized'); } diff --git a/lib/main.dart b/lib/main.dart index 6a34430c..50069c3f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -21,6 +22,15 @@ import 'initialization.dart'; final GlobalKey navigatorKey = GlobalKey(); +class CustomScrollBehavior extends MaterialScrollBehavior { + // Override behavior methods and getters like dragDevices + @override + Set get dragDevices => { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }; +} + void main() async { await initializeBindings(); runApp(const ProviderScope(child: App())); @@ -65,38 +75,6 @@ class _AppState extends State { late GoRouter _router; bool displaySplashImage = true; - final ThemeData _darkTheme = ThemeData( - brightness: Brightness.dark, - scrollbarTheme: ScrollbarThemeData( - thumbVisibility: WidgetStateProperty.all(false), - interactive: false, - thumbColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.dragged)) { - return const Color(0xff1aab5f); - } - if (states.contains(WidgetState.hovered)) { - return const Color(0xff1aab5f); - } - return const Color(0xff1aab5f); - }), - ), - ); - final ThemeData _theme = ThemeData( - brightness: Brightness.light, - scrollbarTheme: ScrollbarThemeData( - thumbVisibility: WidgetStateProperty.all(false), - interactive: false, - thumbColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.dragged)) { - return const Color(0xff1aab5f); - } - if (states.contains(WidgetState.hovered)) { - return const Color(0xff1aab5f); - } - return const Color(0xff1aab5f); - }), - ), - ); final Iterable>? localizationsDelegates = const [ FFLocalizationsDelegate(), @@ -192,15 +170,49 @@ class _AppState extends State { @override Widget build(BuildContext context) { + final themeSchema = FlutterFlowTheme.of(context); + + final ThemeData darkTheme = ThemeData( + brightness: Brightness.dark, + scrollbarTheme: ScrollbarThemeData( + thumbVisibility: WidgetStateProperty.all(false), + interactive: false, + thumbColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.dragged)) return themeSchema.primary; + if (states.contains(WidgetState.hovered)) return themeSchema.primary; + return themeSchema.primary; + }), + ), + ); + final ThemeData lightTheme = ThemeData( + brightness: Brightness.light, + textSelectionTheme: TextSelectionThemeData( + cursorColor: themeSchema.primaryText, // Cor do cursor + selectionColor: themeSchema.accent2, // Cor da seleção de texto + selectionHandleColor: + themeSchema.primaryText, // Cor do manipulador de seleção + ), + scrollbarTheme: ScrollbarThemeData( + thumbVisibility: WidgetStateProperty.all(false), + interactive: false, + thumbColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.dragged)) return themeSchema.primary; + if (states.contains(WidgetState.hovered)) return themeSchema.primary; + return themeSchema.primary; + }), + ), + ); + return MaterialApp.router( + scrollBehavior: CustomScrollBehavior(), key: navigatorKey, title: 'FRE ACCESS HUB', builder: builder, localizationsDelegates: localizationsDelegates, locale: _locale, supportedLocales: supportedLocales, - theme: _theme, - darkTheme: _darkTheme, + theme: lightTheme, + darkTheme: darkTheme, themeMode: _themeMode, routerConfig: _router, ); diff --git a/lib/pages/liberation_history/liberation_history_model.dart b/lib/pages/liberation_history/liberation_history_model.dart index dc93f26b..044fd7a3 100644 --- a/lib/pages/liberation_history/liberation_history_model.dart +++ b/lib/pages/liberation_history/liberation_history_model.dart @@ -50,7 +50,8 @@ class LiberationHistoryModel extends FlutterFlowModel { required String? response, required String? id}) async { final ApiCallResponse? respondeSolicitacaoCall; - final RespondeSolicitacaoCall callback = PhpGroup.respondeSolicitacaoCall; + final RespondeSolicitacaoCall callback = + FreAccessWSGlobal.respondeSolicitacaoCall; respondeSolicitacaoCall = await callback.call( referencia: ref, diff --git a/lib/pages/liberation_history/liberation_history_widget.dart b/lib/pages/liberation_history/liberation_history_widget.dart index d4f4ce88..5a199022 100644 --- a/lib/pages/liberation_history/liberation_history_widget.dart +++ b/lib/pages/liberation_history/liberation_history_widget.dart @@ -333,7 +333,7 @@ class _LiberationHistoryWidgetState extends State { Future _fetchRequests() async { try { safeSetState(() => _loading = true); - var response = await PhpGroup.getLiberationsCall.call().first; + var response = await FreAccessWSGlobal.getLiberationsCall.call().first; final List requests = response.jsonBody['solicitacoes'] ?? []; diff --git a/lib/pages/message_history_page/message_history_page_widget.dart b/lib/pages/message_history_page/message_history_page_widget.dart index 3e72708b..4e0f64cc 100644 --- a/lib/pages/message_history_page/message_history_page_widget.dart +++ b/lib/pages/message_history_page/message_history_page_widget.dart @@ -97,7 +97,7 @@ class _MessageHistoryPageWidgetState extends State try { setState(() => _loading = true); - var response = await PhpGroup.getMessagesCall.call( + var response = await FreAccessWSGlobal.getMessagesCall.call( pageSize: _pageSize.toString(), pageNumber: _pageNumber.toString(), tipoDestino: _destinyType, diff --git a/lib/pages/package_order_page/package_order_page.dart b/lib/pages/package_order_page/package_order_page.dart index a8d04b60..e6af9962 100644 --- a/lib/pages/package_order_page/package_order_page.dart +++ b/lib/pages/package_order_page/package_order_page.dart @@ -97,7 +97,7 @@ class _PackageOrderPage extends State { try { setState(() => _loading = true); - var response = await PhpGroup.buscaEnconcomendas.call( + var response = await FreAccessWSGlobal.buscaEnconcomendas.call( pageSize: _pageSize.toString(), page: _pageNumber.toString(), adresseeType: _adresseeType == '.*' ? 'TOD' : _adresseeType, @@ -314,7 +314,7 @@ class _PackageOrderPage extends State { } String _imagePath(dynamic order) { - return '${PhpGroup.getBaseUrl()}/getImage.php?cliID=$cliUUID&atividade=getFotoEncomenda&orderId=${order['id'] ?? ''}'; + return '${FreAccessWSGlobal.getBaseUrl()}/getImage.php?cliID=$cliUUID&atividade=getFotoEncomenda&orderId=${order['id'] ?? ''}'; } Map _labelsHashMap(dynamic order) { diff --git a/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart b/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart index 097f9090..9a802749 100644 --- a/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart +++ b/lib/pages/people_on_the_property_page/people_on_the_property_page_widget.dart @@ -82,7 +82,7 @@ class _PeopleOnThePropertyPageState extends State { body: SafeArea( top: true, child: FutureBuilder( - future: PhpGroup.getPessoasLocalCall.call(), + future: FreAccessWSGlobal.getPessoasLocalCall.call(), builder: (context, snapshot) { // Customize what your widget looks like when it's loading. if (!snapshot.hasData) { @@ -123,7 +123,7 @@ class _PeopleOnThePropertyPageState extends State { } final columnGetPessoasLocalResponse = snapshot.data!; - final getPoepleProperty = PhpGroup.getPessoasLocalCall + final getPoepleProperty = FreAccessWSGlobal.getPessoasLocalCall .pessoas( columnGetPessoasLocalResponse.jsonBody, ) diff --git a/lib/pages/pets_on_the_property_page/pets_history_screen.dart b/lib/pages/pets_on_the_property_page/pets_history_screen.dart index 813c1158..f6eace39 100644 --- a/lib/pages/pets_on_the_property_page/pets_history_screen.dart +++ b/lib/pages/pets_on_the_property_page/pets_history_screen.dart @@ -100,7 +100,7 @@ class _PetsHistoryScreenState extends State try { setState(() => _loading = true); - var response = await PhpGroup.getPets.call( + var response = await FreAccessWSGlobal.getPets.call( pageSize: _pageSize, page: _pageNumber, ); diff --git a/lib/pages/pets_page/pets_page_model.dart b/lib/pages/pets_page/pets_page_model.dart index 6671c468..a0c2fd31 100644 --- a/lib/pages/pets_page/pets_page_model.dart +++ b/lib/pages/pets_page/pets_page_model.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; @@ -163,8 +164,10 @@ class PetsPageModel extends FlutterFlowModel { // updateImage!(); (() async { - Response response = await get(Uri.parse( - 'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId')); + final String url = + 'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId'; + log('img: $url'); + Response response = await get(Uri.parse(url)); String base64 = base64Encode(response.bodyBytes); uploadedTempFile = await ImageUtils.convertToUploadFile(base64); updateImage?.call(); @@ -280,7 +283,8 @@ class PetsPageModel extends FlutterFlowModel { img = "base64;jpeg,$img"; final url = 'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId'; - final response = await PhpGroup.updatePet.call( + log('img: $url'); + final response = await FreAccessWSGlobal.updatePet.call( petID: petId, image: img, birthdayDate: textControllerData!.text, @@ -323,7 +327,7 @@ class PetsPageModel extends FlutterFlowModel { Future registerPet() async { var img = await ImageUtils.convertImageFileToBase64(uploadedLocalFile!); img = "base64;jpeg,$img"; - final response = await PhpGroup.registerPet.call( + final response = await FreAccessWSGlobal.registerPet.call( image: img, birthdayDate: textControllerData!.text, color: textControllerColor!.text, @@ -464,7 +468,7 @@ class PetsPageModel extends FlutterFlowModel { enText: 'Are you sure you want to delete this pet?', ), () async { int id = item['id']; - await PhpGroup.deletePet + await FreAccessWSGlobal.deletePet .call( petID: id, ) diff --git a/lib/pages/preferences_settings_page/preferences_settings_model.dart b/lib/pages/preferences_settings_page/preferences_settings_model.dart index 17e79b25..0f57850c 100644 --- a/lib/pages/preferences_settings_page/preferences_settings_model.dart +++ b/lib/pages/preferences_settings_page/preferences_settings_model.dart @@ -62,7 +62,7 @@ class PreferencesPageModel with ChangeNotifier { onConfirm() async { String content; String value = !isNotify ? 'S' : 'N'; - await PhpGroup.changeNotifica + await FreAccessWSGlobal.changeNotifica .call(notifica: value) .then((value) async { if (value.jsonBody['error'] == false) { @@ -109,7 +109,7 @@ class PreferencesPageModel with ChangeNotifier { ); onConfirm() async { String content; - await PhpGroup.updateIDE.call().then((value) async { + await FreAccessWSGlobal.updateIDE.call().then((value) async { if (value.jsonBody['error'] == false) { notifyListeners(); content = FFLocalizations.of(context).getVariableText( @@ -141,7 +141,7 @@ class PreferencesPageModel with ChangeNotifier { Future toggleAccess(BuildContext context) async { onChange(String key) async { await StorageHelper().set(SecureStorageKey.accessPass.value, key); - await PhpGroup.changePass + await FreAccessWSGlobal.changePass .call(newSenha: key) .then((value) async { final String content; @@ -180,7 +180,7 @@ class PreferencesPageModel with ChangeNotifier { Future togglePanic(BuildContext context) async { onChange(String key) async { await StorageHelper().set(SecureStorageKey.panicPass.value, key); - await PhpGroup.changePanic + await FreAccessWSGlobal.changePanic .call(newSenhaPanico: key) .then((value) async { final String content; 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 f7832214..bab42743 100644 --- a/lib/pages/qr_code_page/qr_code_page_widget.dart +++ b/lib/pages/qr_code_page/qr_code_page_widget.dart @@ -103,8 +103,7 @@ class _QrCodePageWidgetState extends State screenWidth < screenHeight ? screenWidth : screenHeight; double dimension = smallerDimension * 0.75; double totalTimeInSeconds = 100.0; - double limitedHeaderTextSize = - LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16); + LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16); double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); return SafeArea( diff --git a/lib/pages/reception_page/reception_page_widget.dart b/lib/pages/reception_page/reception_page_widget.dart index 4fc8c064..ba986784 100644 --- a/lib/pages/reception_page/reception_page_widget.dart +++ b/lib/pages/reception_page/reception_page_widget.dart @@ -29,9 +29,7 @@ class _ReceptionPageWidgetState extends State void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); - () async { - final lifecycle = await AwesomeNotifications().getAppLifeCycle(); - }(); + () async {}(); FirebaseMessagingService().updateDeviceToken(); LocalsRepositoryImpl().validateLocal(context); @@ -183,7 +181,7 @@ class _ReceptionPageWidgetState extends State padding: const EdgeInsets.fromLTRB(60, 0, 60, 25), child: FFButtonWidget( onPressed: () async { - PhpGroup.unregisterDevice(); + FreAccessWSGlobal.unregisterDevice(); AuthenticationService.signOut(context); setState(() {}); }, diff --git a/lib/pages/residents_on_the_property/residents_on_the_property_screen.dart b/lib/pages/residents_on_the_property/residents_on_the_property_screen.dart index 64b61acf..74d3f8df 100644 --- a/lib/pages/residents_on_the_property/residents_on_the_property_screen.dart +++ b/lib/pages/residents_on_the_property/residents_on_the_property_screen.dart @@ -175,8 +175,8 @@ class _ResidentsOnThePropertyState extends State try { setState(() => _loading = true); - var response = - await PhpGroup.getResidentsByProperty.call(_pageNumber.toString()); + var response = await FreAccessWSGlobal.getResidentsByProperty + .call(_pageNumber.toString()); final List residents = response.jsonBody['residents'] ?? []; safeSetState(() => count = response.jsonBody['total_rows'] ?? 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 f6c80364..3da22d1f 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 @@ -361,7 +361,7 @@ class ScheduleCompleteVisitPageModel required String? accessKey, required String? email}) async { final ApiCallResponse? response; - final CancelaVisita callback = PhpGroup.cancelaVisita; + final CancelaVisita callback = FreAccessWSGlobal.cancelaVisita; response = await callback.call( idDestino: idDestino, 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 f5247241..bc34c8f6 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 @@ -90,6 +90,7 @@ class _ScheduleCompleteVisitPageWidgetState } } + // ignore: unused_element void _scrollListener() { if (_visitHistoryController.position.pixels == _visitHistoryController.position.maxScrollExtent) { @@ -1071,7 +1072,8 @@ class _ScheduleCompleteVisitPageWidgetState height: scaledSizedBoxSize * 0.5, decoration: const BoxDecoration(), child: FutureBuilder( - future: PhpGroup.getDadosCall.call(), + future: + FreAccessWSGlobal.getDadosCall.call(), builder: (context, snapshot) { if (!snapshot.hasData) { return Center( @@ -1088,13 +1090,14 @@ class _ScheduleCompleteVisitPageWidgetState ); } - final reasonsJsonList = - PhpGroup.getDadosCall.reasonsJsonList( - snapshot.data!.jsonBody); - final reasonsOptionLabels = PhpGroup + final reasonsJsonList = FreAccessWSGlobal .getDadosCall - .reasonsMotDescStrList( + .reasonsJsonList( snapshot.data!.jsonBody); + final reasonsOptionLabels = + FreAccessWSGlobal.getDadosCall + .reasonsMotDescStrList( + snapshot.data!.jsonBody); model.processDropDown1(reasonsJsonList!); @@ -1195,7 +1198,8 @@ class _ScheduleCompleteVisitPageWidgetState height: scaledSizedBoxSize * 0.5, decoration: const BoxDecoration(), child: FutureBuilder( - future: PhpGroup.getDadosCall.call(), + future: + FreAccessWSGlobal.getDadosCall.call(), builder: (context, snapshot) { if (!snapshot.hasData) { return Center( @@ -1212,13 +1216,14 @@ class _ScheduleCompleteVisitPageWidgetState ); } - final lavelsJsonList = - PhpGroup.getDadosCall.levelJsonList( - snapshot.data!.jsonBody); - final lavelsOptionLabels = PhpGroup + final lavelsJsonList = FreAccessWSGlobal .getDadosCall - .levelNACDescricaoStrList( + .levelJsonList( snapshot.data!.jsonBody); + final lavelsOptionLabels = + FreAccessWSGlobal.getDadosCall + .levelNACDescricaoStrList( + snapshot.data!.jsonBody); model.processDropDown2(lavelsJsonList!); return FlutterFlowDropDown( @@ -1556,7 +1561,7 @@ class _ScheduleCompleteVisitPageWidgetState onPressed: model.isValid() ? () async { Future scheduleVisit() async { - await PhpGroup.postScheduleVisitCall + await FreAccessWSGlobal.postScheduleVisitCall .call( devDesc: model.textController3.text, idVisitante: model.visitorStrList, @@ -1572,7 +1577,7 @@ class _ScheduleCompleteVisitPageWidgetState .catchError((e) async => await DialogUtil.errorDefault(context)) .then((value) async { - if (PhpGroup.postScheduleVisitCall.error( + if (FreAccessWSGlobal.postScheduleVisitCall.error( (value.jsonBody ?? ''), ) == false) { diff --git a/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart b/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart index 0c4ddaf1..9c4f234e 100644 --- a/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/visit_history_page_widget.dart @@ -76,7 +76,7 @@ class _VisitHistoryWidgetState extends State setState(() => _loading = true); var response = await ScheduleCompleteVisitPageModel().visitHistory( - requestFn: () => PhpGroup.getVisitsCall.call( + requestFn: () => FreAccessWSGlobal.getVisitsCall.call( pageSize: _pageSize, pageNumber: _pageNumber, ), diff --git a/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart b/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart index ddbf6271..7d6c7eae 100644 --- a/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart +++ b/lib/pages/vehicles_on_the_property/vehicle_history_screen.dart @@ -10,7 +10,7 @@ class VehicleHistoryScreen extends StatefulWidget { class _VehicleHistoryScreenState extends State with Pageable { - final apiCall = PhpGroup.getVehiclesByProperty; + final apiCall = FreAccessWSGlobal.getVehiclesByProperty; int totalOwnerVehicles = 0; final PagingController _pagingController = PagingController(firstPageKey: 1); diff --git a/lib/pages/vehicles_on_the_property/vehicle_model.dart b/lib/pages/vehicles_on_the_property/vehicle_model.dart index 61a53dc5..0a5f23c6 100644 --- a/lib/pages/vehicles_on_the_property/vehicle_model.dart +++ b/lib/pages/vehicles_on_the_property/vehicle_model.dart @@ -7,8 +7,8 @@ import 'package:hub/features/backend/index.dart'; import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/index.dart'; import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart'; -import 'package:hub/shared/extensions/index.dart'; -import 'package:hub/shared/utils/index.dart'; +import 'package:hub/shared/extensions.dart'; +import 'package:hub/shared/utils.dart'; /// [VehicleModel] is a class that contains the business logic of the vehicle page. class VehicleModel extends FlutterFlowModel @@ -196,7 +196,7 @@ mixin class _BaseVehiclePage { /// [_VehicleRegisterScreenModel] is a mixin that contains the business logic of the vehicle register page. mixin _VehicleRegisterScreenModel on _BaseVehiclePage { Future registerVehicle() async { - final response = await PhpGroup.registerVehicle.call( + final response = await FreAccessWSGlobal.registerVehicle.call( licensePlate: textFieldControllerLicensePlate!.text, color: textFieldControllerColor!.text, model: textFieldControllerModel!.text, @@ -218,7 +218,7 @@ mixin _VehicleRegisterScreenModel on _BaseVehiclePage { /// [_VehicleUpdateScreenModel] is a mixin that contains the business logic of the vehicle update page. mixin _VehicleUpdateScreenModel on _BaseVehiclePage { Future updateVehicle() async { - final response = await PhpGroup.updateVehicle.call( + final response = await FreAccessWSGlobal.updateVehicle.call( licensePlate: textFieldControllerLicensePlate!.text, color: textFieldControllerColor!.text, model: textFieldControllerModel!.text, @@ -403,7 +403,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { Future processDeleteRequest(dynamic item) async { log('processDeleteRequest -> item[$item]'); - bool result = await PhpGroup.deleteVehicle + bool result = await FreAccessWSGlobal.deleteVehicle .call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], @@ -493,7 +493,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { } Future processCancelDeleteRequest(dynamic item) async { - return await PhpGroup.deleteVehicle.call( + return await FreAccessWSGlobal.deleteVehicle.call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], model: item['model'], @@ -502,7 +502,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { } Future processCancelUpdateRequest(dynamic item) async { - return await PhpGroup.deleteVehicle.call( + return await FreAccessWSGlobal.deleteVehicle.call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], model: item['model'], @@ -511,7 +511,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage { } Future processCancelCreateRequest(dynamic item) async { - return await PhpGroup.cancelDelete.call( + return await FreAccessWSGlobal.cancelDelete.call( vehicleId: item['vehicleId'], licensePlate: item['licensePlate'], model: item['model'], diff --git a/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart b/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart index 9e51e429..318d05c7 100644 --- a/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart +++ b/lib/pages/vehicles_on_the_property/vehicles_on_the_property.dart @@ -13,7 +13,7 @@ import 'package:hub/features/backend/index.dart'; import 'package:hub/features/module/index.dart'; import 'package:hub/flutter_flow/index.dart'; import 'package:hub/pages/vehicles_on_the_property/vehicle_model.dart'; -import 'package:hub/shared/extensions/index.dart'; +import 'package:hub/shared/extensions.dart'; import 'package:hub/shared/mixins/pageable_mixin.dart'; import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/utils/license_util.dart'; diff --git a/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart index 345d8a93..ad1fae23 100644 --- a/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart +++ b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart @@ -54,8 +54,8 @@ class _VisitsOnThePropertyState extends State @override Widget build(BuildContext context) { - late final limitedBodyTextSize = - LimitedFontSizeUtil.getBodyFontSize(context); + // late final limitedBodyTextSize = + // LimitedFontSizeUtil.getBodyFontSize(context); late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); @@ -176,7 +176,7 @@ class _VisitsOnThePropertyState extends State setState(() => _loading = true); var response = - await PhpGroup.getOpenedVisits.call(_pageNumber.toString()); + await FreAccessWSGlobal.getOpenedVisits.call(_pageNumber.toString()); final List visits = response.jsonBody['visitas'] ?? []; safeSetState(() => count = response.jsonBody['total_rows'] ?? 0); diff --git a/lib/shared/constants.dart b/lib/shared/constants.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/shared/constants/index.dart b/lib/shared/constants/index.dart deleted file mode 100644 index 8b137891..00000000 --- a/lib/shared/constants/index.dart +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/shared/enums.dart b/lib/shared/enums.dart new file mode 100644 index 00000000..85af0099 --- /dev/null +++ b/lib/shared/enums.dart @@ -0,0 +1 @@ +export 'enums/enum_throw_exception.dart'; diff --git a/lib/shared/enums/index.dart b/lib/shared/enums/index.dart deleted file mode 100644 index 585bd715..00000000 --- a/lib/shared/enums/index.dart +++ /dev/null @@ -1 +0,0 @@ -export 'enum_throw_exception.dart'; diff --git a/lib/shared/extensions.dart b/lib/shared/extensions.dart new file mode 100644 index 00000000..c07e669c --- /dev/null +++ b/lib/shared/extensions.dart @@ -0,0 +1,3 @@ +export 'extensions/dialog_extensions.dart'; +export 'extensions/flutter_secure_storage_extensions.dart'; +export 'extensions/string_extensions.dart'; diff --git a/lib/shared/extensions/index.dart b/lib/shared/extensions/index.dart deleted file mode 100644 index 0f71878e..00000000 --- a/lib/shared/extensions/index.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'dialog_extensions.dart'; -export 'flutter_secure_storage_extensions.dart'; -export 'string_extensions.dart'; diff --git a/lib/shared/extensions/string_extensions.dart b/lib/shared/extensions/string_extensions.dart index 43d536ba..45bde526 100644 --- a/lib/shared/extensions/string_extensions.dart +++ b/lib/shared/extensions/string_extensions.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + extension StringNullableExtensions on String? { bool get toBoolean { if (this == null) return false; @@ -24,3 +26,16 @@ extension StringExtensions on String { } extension StringExtension on String? {} + +extension HexColor on String { + Color toColor() { + final hexCode = replaceAll('#', ''); + final buffer = StringBuffer(); + if (hexCode.length == 6) { + buffer + .write('ff'); // Adiciona opacidade total caso não esteja especificada + } + buffer.write(hexCode); + return Color(int.parse(buffer.toString(), radix: 16)); + } +} diff --git a/lib/shared/helpers.dart b/lib/shared/helpers.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/shared/helpers/index.dart b/lib/shared/helpers/index.dart deleted file mode 100644 index 8b137891..00000000 --- a/lib/shared/helpers/index.dart +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/shared/mixins.dart b/lib/shared/mixins.dart new file mode 100644 index 00000000..bd86cf22 --- /dev/null +++ b/lib/shared/mixins.dart @@ -0,0 +1,4 @@ +export 'mixins/pegeable_mixin.dart'; +export 'mixins/status_mixin.dart'; +export 'mixins/switcher_mixin.dart'; +export 'mixins/template_mixin.dart'; diff --git a/lib/shared/mixins/index.dart b/lib/shared/mixins/index.dart deleted file mode 100644 index f41f8c59..00000000 --- a/lib/shared/mixins/index.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'status_mixin.dart'; -export 'switcher_mixin.dart'; diff --git a/lib/shared/mixins/pegeable_mixin.dart b/lib/shared/mixins/pegeable_mixin.dart new file mode 100644 index 00000000..9be57f32 --- /dev/null +++ b/lib/shared/mixins/pegeable_mixin.dart @@ -0,0 +1,139 @@ +// import 'package:flutter/material.dart'; +// import 'package:hub/flutter_flow/index.dart'; +// import 'package:hub/shared/utils/limited_text_size.dart'; +// import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; + +// extension PagedListViewExtension +// on PagedSliverList {} + +// typedef PaginatedListViewHeaderBuilder = Widget Function( +// Future> Function() gen); +// typedef PaginatedListViewBodyBuilder = Widget Function(BuildContext, T, int); + +// mixin Pageable on State { +// Expanded buildPaginatedListView( +// String noDataFound, +// PagingController pg, +// Future> Function() headerItems, +// PaginatedListViewHeaderBuilder headerBuilder, +// PaginatedListViewBodyBuilder bodyBuilder) { +// final theme = FlutterFlowTheme.of(context); +// return Expanded( +// child: RefreshIndicator( +// backgroundColor: theme.primaryBackground, +// color: theme.primary, +// onRefresh: () async => pg.refresh(), +// child: PagedListView( +// pagingController: pg, +// builderDelegate: PagedChildBuilderDelegate( +// animateTransitions: true, +// itemBuilder: (context, item, int index) { +// return Column(children: [ +// if (index == 0) headerBuilder(headerItems), +// bodyBuilder(context, item, index), +// ]); +// }, +// newPageProgressIndicatorBuilder: (context) => +// buildLoadingIndicator(context), +// firstPageProgressIndicatorBuilder: (context) => +// buildLoadingIndicator(context), +// noItemsFoundIndicatorBuilder: (context) => +// buildNoDataFound( +// context, noDataFound, headerItems, headerBuilder), +// firstPageErrorIndicatorBuilder: (context) => const Placeholder(), +// newPageErrorIndicatorBuilder: (context) => const Placeholder(), +// ), +// ), +// ), +// ); +// } + +// Future showError(PagingStatus status, PagingController pg) async { +// if (status == PagingStatus.subsequentPageError) { +// final message = FFLocalizations.of(context).getVariableText( +// enText: 'Something went wrong while fetching a new page.', +// ptText: 'Algo deu errado ao buscar uma nova página.', +// ); +// final retry = FFLocalizations.of(context).getVariableText( +// enText: 'Retry', +// ptText: 'Recarregar', +// ); + +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text(message), +// action: SnackBarAction( +// label: retry, +// onPressed: () => pg.retryLastFailedRequest(), +// ), +// ), +// ); +// } +// } + +// Future fetchPage({ +// required Future<(bool, dynamic)> Function() dataProvider, +// required void Function(dynamic data) onDataAvailable, +// required void Function() onDataUnavailable, +// required void Function(Object error, StackTrace stackTrace) onFetchError, +// }) async { +// try { +// final (bool isDataAvailable, dynamic data) = await dataProvider(); +// if (isDataAvailable) { +// onDataAvailable(data); +// } else { +// onDataUnavailable(); +// } +// } catch (error, stackTrace) { +// onFetchError(error, stackTrace); +// } +// } + +// void showNoMoreDataSnackBar(BuildContext context) { +// final message = FFLocalizations.of(context).getVariableText( +// ptText: "Não há mais dados.", +// enText: "No more data.", +// ); + +// showSnackbar(context, message, true); +// } + +// Widget buildNoDataFound( +// BuildContext context, +// String title, +// Future> Function() items, +// Widget Function(Future> Function() items) headerBuilder, +// ) { +// final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context); +// // final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); +// return Column( +// children: [ +// headerBuilder(items), +// Expanded( +// child: Center( +// child: Text( +// title, +// style: TextStyle( +// fontFamily: 'Nunito', +// fontSize: headerFontSize, +// ), +// ), +// ), +// ), +// ], +// ); +// } + +// Widget buildLoadingIndicator(BuildContext context) { +// return Container( +// padding: const EdgeInsets.symmetric(vertical: 15), +// child: Center( +// child: CircularProgressIndicator( +// valueColor: AlwaysStoppedAnimation( +// FlutterFlowTheme.of(context).primary, +// ), +// ), +// ), +// ); +// } +// } diff --git a/lib/shared/mixins/template_mixin.dart b/lib/shared/mixins/template_mixin.dart new file mode 100644 index 00000000..38e9268b --- /dev/null +++ b/lib/shared/mixins/template_mixin.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; + +mixin Template { + PreferredSizeWidget buildAppBar( + String title, + BuildContext context, [ + dynamic Function()? backAction, + dynamic Function()? frontAction, + ]) { + final theme = FlutterFlowTheme.of(context); + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text( + title, + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 16.0, + fontWeight: FontWeight.bold, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + leading: _backButton(context, theme, backAction), + centerTitle: true, + elevation: 0.0, + actions: _frontButton(context, theme, frontAction), + ); + } + + List _frontButton(BuildContext context, FlutterFlowTheme theme, + dynamic Function()? action) { + if (action == null) return []; + return [ + IconButton( + onPressed: () async => await showModalBottomSheet( + context: context, + builder: (context) => action(), + ), + icon: Icon( + Symbols.info_i_rounded, + color: FlutterFlowTheme.of(context).primaryText, + ), + ) + ]; + } + + Widget? _backButton(BuildContext context, FlutterFlowTheme theme, + dynamic Function()? onPressed) { + if (onPressed == null) return null; + return FlutterFlowIconButton( + key: ValueKey('BackNavigationAppBar'), + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: theme.primaryText, + size: 30.0, + ), + onPressed: onPressed, + ); + } +} diff --git a/lib/shared/services.dart b/lib/shared/services.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/shared/services/index.dart b/lib/shared/services/index.dart deleted file mode 100644 index 8b137891..00000000 --- a/lib/shared/services/index.dart +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/shared/utils.dart b/lib/shared/utils.dart new file mode 100644 index 00000000..c3eae2ca --- /dev/null +++ b/lib/shared/utils.dart @@ -0,0 +1,15 @@ +export 'utils/biometric_util.dart'; +export 'utils/device_util.dart'; +export 'utils/dialog_util.dart'; +export 'utils/image_util.dart'; +export 'utils/limited_text_size.dart'; +export 'utils/loading_util.dart'; +export 'utils/log_util.dart'; +export 'utils/path_util.dart'; +export 'utils/share_util.dart'; +export 'utils/snackbar_util.dart'; +export 'utils/string_util.dart'; +export 'utils/text_util.dart'; +export 'utils/validator_util.dart'; +export 'utils/webview_util.dart'; +export 'utils/color_util.dart'; diff --git a/lib/shared/utils/color_util.dart b/lib/shared/utils/color_util.dart new file mode 100644 index 00000000..291762a8 --- /dev/null +++ b/lib/shared/utils/color_util.dart @@ -0,0 +1,48 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +class ColorUtil { + static Color getContrastColor(Color a, Color b) { + double luminance(Color color) { + return (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255; + } + + double contrastRatio(Color a, Color b) { + final lumA = luminance(a) + 0.05; + final lumB = luminance(b) + 0.05; + return lumA > lumB ? lumA / lumB : lumB / lumA; + } + + if (contrastRatio(a, b) < 4.5) { + // Find a color with higher contrast within the same hue + final hsv = HSVColor.fromColor(a); + double hue = hsv.hue; + double saturation = hsv.saturation; + double brightness = hsv.value; + + // Increase brightness to ensure higher contrast + brightness = brightness > 0.5 ? brightness - 0.5 : brightness + 0.5; + + return HSVColor.fromAHSV(1.0, hue, saturation, brightness).toColor(); + } + + return b; + } + + static Color getSelfContrastColor(Color color) { + final hsv = HSVColor.fromColor(color); + double hue = hsv.hue; + double saturation = hsv.saturation; + double brightness = hsv.value; + + // Increase brightness to ensure higher contrast + brightness = brightness > 0.5 ? brightness - 0.5 : brightness + 0.5; + + return HSVColor.fromAHSV(1.0, hue, saturation, brightness).toColor(); + } +} + +extension ColorUtilExtension on Color { + Color get highlight => ColorUtil.getSelfContrastColor(this); +} diff --git a/lib/shared/utils/index.dart b/lib/shared/utils/index.dart deleted file mode 100644 index 6d20915d..00000000 --- a/lib/shared/utils/index.dart +++ /dev/null @@ -1,14 +0,0 @@ -export 'biometric_util.dart'; -export 'device_util.dart'; -export 'dialog_util.dart'; -export 'image_util.dart'; -export 'limited_text_size.dart'; -export 'loading_util.dart'; -export 'log_util.dart'; -export 'path_util.dart'; -export 'share_util.dart'; -export 'snackbar_util.dart'; -export 'string_util.dart'; -export 'text_util.dart'; -export 'validator_util.dart'; -export 'webview_util.dart'; diff --git a/lib/shared/utils/log_util.dart b/lib/shared/utils/log_util.dart index c9c9526b..b6bfebf9 100644 --- a/lib/shared/utils/log_util.dart +++ b/lib/shared/utils/log_util.dart @@ -6,7 +6,7 @@ import 'package:hub/features/backend/index.dart'; class LogUtil { static void requestAPIFailed(String url, String body, String reason, dynamic error, StackTrace stack) async { - final fullUrl = "${PhpGroup.getBaseUrl()}/$url"; + final fullUrl = "${FreAccessWSGlobal.getBaseUrl()}/$url"; log("URL: $fullUrl"); log("Body: $body"); log("Reason: $reason"); diff --git a/lib/shared/utils/validator_util.dart b/lib/shared/utils/validator_util.dart index 51abce74..a8eef8db 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 { @@ -34,10 +36,16 @@ class ValidatorUtil { } 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); + try { + if (value.isEmpty) return ''; + DateFormat dateFormat = DateFormat(format); + DateTime? dateTime = dateFormat.tryParse(value); + if (dateTime == null) return ''; + return dateFormat.format(dateTime); + } catch (e, s) { + log(e.toString(), stackTrace: s); + return ''; + } } static String formatDateTimePicker(String dateTime) { diff --git a/lib/shared/widgets.dart b/lib/shared/widgets.dart new file mode 100644 index 00000000..1622e8b2 --- /dev/null +++ b/lib/shared/widgets.dart @@ -0,0 +1,18 @@ +/// [Base] +library; + +export 'widgets/page.dart'; +export 'widgets/component.dart'; +export 'widgets/screen.dart'; +export 'widgets/model.dart'; +export 'widgets/entity.dart'; + +/// [View]'s +export 'widgets/list_view.dart'; +export 'widgets/read_view.dart'; +export 'widgets/enhanced_carousel_view.dart'; +export 'widgets/enhanced_list_view.dart'; +export 'widgets/enhanced_search_view.dart'; + +/// [Component]'s +export 'widgets/text.dart'; diff --git a/lib/shared/widgets/component.dart b/lib/shared/widgets/component.dart new file mode 100644 index 00000000..a622f134 --- /dev/null +++ b/lib/shared/widgets/component.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:hub/shared/widgets.dart'; + +/// [ComponentWidget] + +abstract class ComponentWidget extends Widget { + const ComponentWidget({super.key}); +} + +abstract class ModelComponent extends ModelWidget + implements ComponentWidget { + const ModelComponent({super.key}); +} + +abstract class StatelessComponent extends StatelessWidget + implements ComponentWidget { + const StatelessComponent({super.key}); +} + +abstract class StatefulComponent extends StatefulWidget + implements ComponentWidget { + const StatefulComponent({super.key}); +} + +abstract class ComponentState extends State {} diff --git a/lib/shared/widgets/enhanced_carousel_view.dart b/lib/shared/widgets/enhanced_carousel_view.dart new file mode 100644 index 00000000..c031172b --- /dev/null +++ b/lib/shared/widgets/enhanced_carousel_view.dart @@ -0,0 +1,124 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:hub/shared/utils.dart'; + +typedef EnhancedCarouselViewKey = GlobalKey<_EnhancedCarouselViewState>; + +class EnhancedCarouselView extends StatefulWidget { + final Future> Function() dataProvider; + final void Function(T?, BuildContext) filter; + final Widget Function(T? item, bool isSelected) itemBuilder; + final bool showIndicator; + + const EnhancedCarouselView({ + super.key, + required this.dataProvider, + required this.filter, + required this.itemBuilder, + this.showIndicator = false, + }); + + @override + _EnhancedCarouselViewState createState() => + _EnhancedCarouselViewState(); +} + +class _EnhancedCarouselViewState extends State> { + T? selectedCategory; + + bool itemIsSelected(T item) { + return selectedCategory == item; + } + + @override + Widget build(BuildContext context) { + final theme = FlutterFlowTheme.of(context); + final backgroundColor = theme.primary; + final overlayColor = WidgetStateProperty.all(Colors.transparent); + + return Stack( + children: [ + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 50, 0), + child: Text( + FFLocalizations.of(context).getVariableText( + ptText: 'Suas Categorias', + enText: 'Your Categories', + ), + style: TextStyle( + color: FlutterFlowTheme.of(context).primaryText, + fontSize: LimitedFontSizeUtil.getHeaderFontSize(context), + ), + ), + ), + FutureBuilder>( + future: widget.dataProvider(), + builder: (context, snapshot) { + if (!snapshot.hasData) return SizedBox(); + final items = snapshot.data! + .map((item) => + widget.itemBuilder(item, itemIsSelected(item as T))) + .toList(); + return SizedBox( + height: 130, // Set a specific height + child: CarouselView( + itemExtent: 140, + enableSplash: true, + itemSnapping: true, + controller: CarouselController(initialItem: 1), + backgroundColor: backgroundColor, + overlayColor: overlayColor, + padding: EdgeInsets.zero, + elevation: 0, + reverse: true, + shrinkExtent: 10, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: (index) async { + log('Selected: ${snapshot.data![index]}'); + log('Selected Category: $selectedCategory'); + final bool isSame = + itemIsSelected(snapshot.data![index]!); + setState(() { + if (isSame) { + selectedCategory = null; + } else { + selectedCategory = snapshot.data![index] as T; + } + }); + if (isSame) + widget.filter(null, context); + else + widget.filter(snapshot.data![index] as T, context); + }, + children: items, + ), + ); + }, + ), + ], + ), + if (widget.showIndicator) + Positioned( + left: 0, + top: 50, + child: Icon(Icons.arrow_left, size: 30, color: Colors.grey), + ), + if (widget.showIndicator) + Positioned( + right: 0, + top: 50, + child: Icon(Icons.arrow_right, size: 30, color: Colors.grey), + ), + ], + ); + } +} diff --git a/lib/shared/widgets/enhanced_list_view.dart b/lib/shared/widgets/enhanced_list_view.dart new file mode 100644 index 00000000..1f370b65 --- /dev/null +++ b/lib/shared/widgets/enhanced_list_view.dart @@ -0,0 +1,616 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:rx_bloc/rx_bloc.dart'; +import 'package:rx_bloc_list/rx_bloc_list.dart'; +import 'package:rxdart/rxdart.dart'; + +/// [TypeDefs] ---------------------------------------------------- + +typedef EnhancedListViewKey + = GlobalKey< + EnhancedListViewState>; +typedef HeaderTileBuilder = Widget Function( + Future> Function() headerItems); +typedef BodyTileBuilder = Widget Function( + BuildContext context, BodyType item, int index); +typedef FooterTileBuilder = Widget Function( + Future> Function() footerItems); +typedef Query = QueryType?; +typedef BodyRetrievalUseCase = Future> + Function(int page, int pageSize, QueryType query); +typedef HeaderRetrievalUseCase = Future> + Function(); +typedef FooterRetrievalUseCase = Future> + Function(); + +/// [Extensions] ---------------------------------------------------- +/// +extension PaginatedListMergeExtensions + on Stream>> { + Stream> mergeWithPaginatedList( + BehaviorSubject> currentList) { + return map( + (result) { + final current = currentList.value; + if (result is ResultSuccess>) { + final newPaginated = result.data; + return current.items.isEmpty + ? newPaginated + : current.copyWith( + list: [...current.items, ...newPaginated.items], + currentPage: newPaginated.currentPage, + totalCount: newPaginated.totalCount, + error: newPaginated.error, + ); + } else if (result is ResultError>) { + return current.copyWith(error: result.error); + } else { + return current; + } + }, + ); + } +} + +extension PublishSubjectExtensions on PublishSubject { + Stream startWith(T initial) => Rx.concat([Stream.value(initial), this]); +} + +extension StreamStartWithExtension on Stream { + Stream startWith(T initial) => Rx.concat([Stream.value(initial), this]); +} + +extension QueryBlocStreamExtensions on Stream { + // Stream>> fetchData( + // EnhancedListViewRepository repository, + // PaginatedListViewBodyBuilder builder, + // BehaviorSubject> paginatedList, + // ) => + // switchMap((reset) { + // if (reset) { + // paginatedList.add(paginatedList.value.resetAll()); + // } + // final nextPage = paginatedList.value.currentPage + 1; + // return repository + // .fetchPage(nextPage, paginatedList.value.pageSize, builder) + // .asResultStream(); + // }); +} + +/// [Interfaces] ---------------------------------------------------- + +interface class EnhancedPaginatedList extends PaginatedList { + @override + final Exception? error; + final bool isInitialized; + @override + final bool isLoading; + final List items; + @override + final int pageSize; + @override + final int? totalCount; + final int currentPage; + + EnhancedPaginatedList({ + required this.items, + required this.pageSize, + this.currentPage = 0, + this.totalCount, + required this.error, + required this.isInitialized, + required this.isLoading, + }) : super( + error: error, + isInitialized: isInitialized, + isLoading: isLoading, + list: items, + pageSize: pageSize, + totalCount: totalCount, + ); + + EnhancedPaginatedList resetAll() => EnhancedPaginatedList( + error: null, + isInitialized: false, + isLoading: false, + items: const [], + pageSize: pageSize, + totalCount: null, + currentPage: 0, + ); + + @override + EnhancedPaginatedList copyWith({ + List? list, + bool? isLoading, + int? totalCount, + Exception? error, + int? pageSize, + bool? isInitialized, + int? currentPage, + }) => + EnhancedPaginatedList( + error: error ?? this.error, + isInitialized: isInitialized ?? this.isInitialized, + isLoading: isLoading ?? this.isLoading, + items: list ?? this.items, + pageSize: pageSize ?? this.pageSize, + totalCount: totalCount ?? this.totalCount, + currentPage: currentPage ?? this.currentPage, + ); + + @override + int get itemCount => items.length; + + @override + T? getItem(int index) => index < items.length ? items[index] : null; + + Future awaitLoad() async => Future.value(); +} + +abstract interface class EnhancedListViewBase extends StatefulWidget { + const EnhancedListViewBase({super.key}); +} + +abstract interface class EnhancedListViewBaseState + extends State< + EnhancedListViewBase> {} + +/// [Mixins] ---------------------------------------------------- + +mixin EnhancedListViewMixin { + late EnhancedListViewBloc bloc; + + void filterBodyItems(QueryType query) => bloc.filterBodyItems(query); + + void filterHeaderItems(QueryType query) => bloc.filterHeaderItems(query); + + void filterFooterItems(QueryType query) => bloc.filterFooterItems(query); +} + +/// [Widgets] ---------------------------------------------------- + +class EnhancedListView + extends EnhancedListViewBase { + final EnhancedListViewRepository + repository; + final EnhancedListViewController + controller; + + const EnhancedListView({ + Key? key, + required this.repository, + required this.controller, + }) : super(key: key); + + @override + EnhancedListViewState + createState() => + EnhancedListViewState(); +} + +class EnhancedListViewState + extends State> + with EnhancedListViewMixin { + @override + void initState() { + super.initState(); + + bloc = EnhancedListViewBloc( + bodyItemsBuilder: widget.repository.fetchBody, + headerItemsBuilder: widget.repository.fetchHeader ?? () async => [], + footerItemsBuilder: widget.repository.fetchFooter ?? () async => [], + ); + bloc.events.loadBodyItems(); + bloc.events.loadHeaderItems(); + bloc.events.loadFooterItems(); + } + + @override + Widget build(BuildContext context) { + final String defaultMessage = FFLocalizations.of(context).getVariableText( + ptText: 'Nenhum item encontrado', + enText: 'No items found', + ); + final header = StreamBuilder>( + stream: bloc.states.headerItems.cast>(), + builder: (context, headerSnapshot) { + if (headerSnapshot.connectionState == ConnectionState.waiting) { + return const EnhancedProgressIndicator(); + } else if (headerSnapshot.hasError) { + return EnhancedErrorWidget(error: headerSnapshot.error); + } else if (!headerSnapshot.hasData || headerSnapshot.data!.isEmpty) { + return const SizedBox.shrink(); + } else { + return widget + .controller.headerBuilder!(() async => headerSnapshot.data!); + } + }, + ); + final footer = StreamBuilder>( + stream: bloc.states.footerItems.cast>(), + builder: (context, footerSnapshot) { + if (footerSnapshot.connectionState == ConnectionState.waiting) { + return const EnhancedProgressIndicator(); + } else if (footerSnapshot.hasError) { + return EnhancedErrorWidget(error: footerSnapshot.error); + } else if (!footerSnapshot.hasData || footerSnapshot.data!.isEmpty) { + return const SizedBox.shrink(); + } else { + return widget + .controller.footerBuilder!(() async => footerSnapshot.data!); + } + }, + ); + final body = Expanded( + child: StreamBuilder>( + stream: bloc.states.bodyItems.cast>(), + builder: (context, bodySnapshot) { + if (bodySnapshot.connectionState == ConnectionState.waiting) { + return const EnhancedProgressIndicator(); + } else if (bodySnapshot.hasError) { + return EnhancedErrorWidget(error: bodySnapshot.error); + } else if (!bodySnapshot.hasData || bodySnapshot.data!.isEmpty) { + return Center( + child: Text(defaultMessage), + ); + } else { + return ListView.builder( + itemCount: bodySnapshot.data?.length ?? 0, + itemBuilder: (context, index) { + return widget.controller + .bodyBuilder(context, bodySnapshot.data![index], index); + }, + ); + } + }, + ), + ); + + return Column( + children: [ + if (widget.controller.headerBuilder != null) header, + body, + if (widget.controller.footerBuilder != null) footer, + ], + ); + } + + @override + void dispose() { + bloc.dispose(); + super.dispose(); + } +} + +/// [Utils] ---------------------------------------------------- + +class EnhancedListTile extends StatelessWidget { + const EnhancedListTile( + {required this.leading, required this.title, super.key}); + + final T leading; + final T title; + + @override + Widget build(BuildContext context) { + return Card( + child: ListTile( + leading: leading, + title: title, + ), + ); + } +} + +class EnhancedErrorWidget extends StatelessWidget { + final Object? error; + const EnhancedErrorWidget({required this.error, super.key}); + + @override + Widget build(BuildContext context) { + log('error: $error'); + return Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + error.toString(), + style: const TextStyle(color: Colors.red), + ), + ); + } +} + +class EnhancedProgressIndicator extends StatelessWidget { + const EnhancedProgressIndicator({super.key}); + + @override + Widget build(BuildContext context) => const Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 12), + child: CircularProgressIndicator(), + ), + ); +} + +class NetworkError implements Exception { + final String message; + NetworkError(this.message); +} + +class ParsingError implements Exception { + final String message; + ParsingError(this.message); +} + +class AuthorizationError implements Exception { + final String message; + AuthorizationError(this.message); +} + +/// [Repositories] ---------------------------------------------------- + +class EnhancedListViewRepository { + final BodyRetrievalUseCase fetchBody; + final HeaderRetrievalUseCase? fetchHeader; + final FooterRetrievalUseCase? fetchFooter; + + const EnhancedListViewRepository({ + required this.fetchBody, + this.fetchHeader, + this.fetchFooter, + }); +} + +// class HeaderRepository {} +// class BodyRepository {} +// class FooterRepository {} + +/// [Controllers] ---------------------------------------------------- + +class EnhancedListViewController { + final BodyTileBuilder bodyBuilder; + final HeaderTileBuilder? headerBuilder; + final FooterTileBuilder? footerBuilder; + + const EnhancedListViewController({ + required this.bodyBuilder, + this.headerBuilder, + this.footerBuilder, + }); +} + +// class HeaderController {} +// class BodyController {} +// class FooterController {} + +/// [Blocs] ---------------------------------------------------- + +Stream get loadingState => Stream.empty(); +Stream get errorState => Stream.empty(); + +abstract class EnhancedListViewEvents { + void loadBodyItems({bool reset = false, dynamic query = null}); + void loadHeaderItems(); + void loadFooterItems(); +} + +abstract class EnhancedListViewStates { + Stream> get bodyItems; + Stream> get headerItems; + Stream> get footerItems; + Stream get isLoading; + Stream get errors; +} + +class EnhancedListViewBloc + extends $EnhancedListViewBloc { + EnhancedListViewBloc({ + required this.bodyItemsBuilder, + required this.headerItemsBuilder, + required this.footerItemsBuilder, + }) { + _$loadBodyItemsEvent + .startWith((query: null, reset: true)) + .switchMap((item) => _fetchBodyItems(item.reset, item.query)) + .bind(_bodyItems) + .addTo(_compositeSubscription); + + _$loadHeaderItemsEvent + .switchMap((_) => _fetchHeaderItems()) + .bind(_headerItems) + .addTo(_compositeSubscription); + + _$loadFooterItemsEvent + .switchMap((_) => _fetchFooterItems()) + .bind(_footerItems) + .addTo(_compositeSubscription); + } + + final BodyRetrievalUseCase bodyItemsBuilder; + final HeaderRetrievalUseCase headerItemsBuilder; + final FooterRetrievalUseCase footerItemsBuilder; + + final _bodyItems = BehaviorSubject>.seeded([]); + + final _headerItems = BehaviorSubject>.seeded([]); + + final _footerItems = BehaviorSubject>.seeded([]); + + final _isLoading = BehaviorSubject.seeded(false); + final _errors = BehaviorSubject(); + + Stream> _fetchBodyItems(bool reset, QueryType? query) async* { + try { + _isLoading.add(true); + final items = await bodyItemsBuilder(1, 10, query); + yield items.whereType().toList(); + } catch (e) { + _errors.add(e.toString()); + } finally { + _isLoading.add(false); + } + } + + Stream> _fetchHeaderItems() async* { + try { + _isLoading.add(true); + final items = await headerItemsBuilder(); + yield items.whereType().toList(); + } catch (e) { + _errors.add(e.toString()); + } finally { + _isLoading.add(false); + } + } + + Stream> _fetchFooterItems() async* { + try { + _isLoading.add(true); + final items = await footerItemsBuilder(); + yield items.whereType().toList(); + } catch (e) { + _errors.add(e.toString()); + } finally { + _isLoading.add(false); + } + } + + void filterBodyItems(QueryType query) { + _$loadBodyItemsEvent.add((query: query, reset: true)); + } + + void filterHeaderItems(QueryType query) { + _$loadHeaderItemsEvent.add(null); + } + + void filterFooterItems(QueryType query) { + _$loadFooterItemsEvent.add(null); + } + + @override + void dispose() { + _bodyItems.close(); + _headerItems.close(); + _footerItems.close(); + _isLoading.close(); + _errors.close(); + super.dispose(); + } + + @override + Stream> _mapToBodyItemsState() => _bodyItems.stream; + @override + Stream _mapToErrorsState() => _errors.stream; + @override + Stream> _mapToFooterItemsState() => _footerItems.stream; + @override + Stream> _mapToHeaderItemsState() => _headerItems.stream; + @override + Stream _mapToIsLoadingState() => _isLoading.stream; +} + +abstract class EnhancedListViewBlocType extends RxBlocTypeBase { + EnhancedListViewEvents get events; + EnhancedListViewStates get states; +} + +abstract class $EnhancedListViewBloc extends RxBlocBase + implements + EnhancedListViewEvents, + EnhancedListViewStates, + EnhancedListViewBlocType { + final _compositeSubscription = CompositeSubscription(); + + /// Тhe [Subject] where events sink to by calling [loadBodyItems] + final _$loadBodyItemsEvent = PublishSubject<({bool reset, dynamic query})>(); + + /// Тhe [Subject] where events sink to by calling [loadHeaderItems] + final _$loadHeaderItemsEvent = PublishSubject(); + + /// Тhe [Subject] where events sink to by calling [loadFooterItems] + final _$loadFooterItemsEvent = PublishSubject(); + + /// The state of [bodyItems] implemented in [_mapToBodyItemsState] + late final Stream> _bodyItemsState = _mapToBodyItemsState(); + + /// The state of [headerItems] implemented in [_mapToHeaderItemsState] + late final Stream> _headerItemsState = + _mapToHeaderItemsState(); + + /// The state of [footerItems] implemented in [_mapToFooterItemsState] + late final Stream> _footerItemsState = + _mapToFooterItemsState(); + + /// The state of [isLoading] implemented in [_mapToIsLoadingState] + late final Stream _isLoadingState = _mapToIsLoadingState(); + + /// The state of [errors] implemented in [_mapToErrorsState] + late final Stream _errorsState = _mapToErrorsState(); + + @override + void loadBodyItems({ + bool reset = false, + dynamic query = null, + }) => + _$loadBodyItemsEvent.add(( + reset: reset, + query: query, + )); + + @override + void loadHeaderItems() => _$loadHeaderItemsEvent.add(null); + + @override + void loadFooterItems() => _$loadFooterItemsEvent.add(null); + + @override + Stream> get bodyItems => _bodyItemsState; + + @override + Stream> get headerItems => _headerItemsState; + + @override + Stream> get footerItems => _footerItemsState; + + @override + Stream get isLoading => _isLoadingState; + + @override + Stream get errors => _errorsState; + + Stream> _mapToBodyItemsState(); + + Stream> _mapToHeaderItemsState(); + + Stream> _mapToFooterItemsState(); + + Stream _mapToIsLoadingState(); + + Stream _mapToErrorsState(); + + @override + EnhancedListViewEvents get events => this; + + @override + EnhancedListViewStates get states => this; + + @override + void dispose() { + _$loadBodyItemsEvent.close(); + _$loadHeaderItemsEvent.close(); + _$loadFooterItemsEvent.close(); + _compositeSubscription.dispose(); + super.dispose(); + } +} + +// ignore: unused_element +typedef _LoadBodyItemsEventArgs = ({bool reset, dynamic query}); diff --git a/lib/shared/widgets/enhanced_search_view.dart b/lib/shared/widgets/enhanced_search_view.dart new file mode 100644 index 00000000..d8ffda2e --- /dev/null +++ b/lib/shared/widgets/enhanced_search_view.dart @@ -0,0 +1,81 @@ +// class EnhancedSearchView extends StatelessWidget { +// const EnhancedSearchView({ +// super.key, +// required this.filter, +// required this.cast, +// }); + +// final void Function(QueryType query) filter; +// final QueryType Function(String query) cast; + +// @override +// Widget build(BuildContext context) { +// final theme = FlutterFlowTheme.of(context); +// final locale = FFLocalizations.of(context); +// TextEditingController controller = TextEditingController(); +// return TextFormField( +// controller: controller, +// onChanged: (value) => EasyDebounce.debounce( +// '_model.keyTextFieldTextController', +// const Duration(milliseconds: 500), +// () => filter.call(cast.call(value)), +// ), +// cursorColor: theme.primaryText, +// showCursor: false, +// cursorWidth: 2.0, +// cursorRadius: Radius.circular(100), +// style: TextStyle( +// color: theme.primaryText, +// fontSize: 16.0, +// decorationColor: Colors.amber, +// ), +// keyboardType: TextInputType.text, +// textInputAction: TextInputAction.search, +// autocorrect: true, +// textCapitalization: TextCapitalization.sentences, +// decoration: InputDecoration( +// prefixIcon: Icon(Icons.search, color: theme.primary), +// labelText: locale.getVariableText( +// ptText: 'Pesquisar', +// enText: 'Search', +// ), +// labelStyle: TextStyle( +// color: theme.primaryText, +// fontSize: 16.0, +// ), +// hintText: locale.getVariableText( +// ptText: 'Digite sua pesquisa', +// enText: 'Enter your search', +// ), +// hintStyle: TextStyle( +// color: theme.accent2, +// fontSize: 14.0, +// ), +// filled: true, +// fillColor: Colors.transparent, +// helperStyle: TextStyle( +// color: theme.primaryText, +// decorationColor: theme.primaryText, +// ), +// focusColor: theme.primaryText, +// contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), +// enabledBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// focusedBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// errorBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// focusedErrorBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText, width: 2.0), +// ), +// ), +// ); +// } +// } diff --git a/lib/shared/widgets/entity.dart b/lib/shared/widgets/entity.dart new file mode 100644 index 00000000..58bcaa43 --- /dev/null +++ b/lib/shared/widgets/entity.dart @@ -0,0 +1 @@ +abstract class Entity {} diff --git a/lib/shared/widgets/list_view.dart b/lib/shared/widgets/list_view.dart new file mode 100644 index 00000000..04a3e12c --- /dev/null +++ b/lib/shared/widgets/list_view.dart @@ -0,0 +1,322 @@ +// typedef SearchKey = GlobalKey; + +// typedef Query = X?; + +// /// ----------------------------------------------- +// /// [EnhancedListView] +// /// ----------------------------------------------- + +// abstract interface class EnhancedListView extends StatefulWidget { +// const EnhancedListView({super.key}); +// } + +// abstract interface class EnhancedListViewState +// extends State {} + +// /// ----------------------------------------------- +// /// [EnhancedLocalListView] +// /// ----------------------------------------------- + +// class EnhancedLocalListView extends EnhancedListView { +// final List list; +// final Widget Function(T) itemBuilder; +// final bool Function(T, String) filter; +// final Widget header; +// final List Function(String)? onSearch; + +// EnhancedLocalListView({ +// Key? key, +// required this.list, +// required this.itemBuilder, +// required this.filter, +// List Function(String)? onSearch, +// Widget? header, +// }) : header = header ?? const SizedBox.shrink(), +// onSearch = onSearch ?? +// ((String query) => +// list.where((documents) => filter(documents, query)).toList()), +// super(key: key); + +// // return documents.where((documents) => filter(documents, query)).toList(); + +// @override +// EnhancedLocalListViewState createState() => +// EnhancedLocalListViewState(); +// } + +// class EnhancedLocalListViewState extends State> { +// TextEditingController editingController = TextEditingController(); +// late List filteredItems; + +// @override +// void initState() { +// filteredItems = widget.list; +// super.initState(); +// } + +// @override +// Widget build(BuildContext context) { +// void filter(value) { +// safeSetState(() { +// filteredItems = widget.onSearch!(value); +// }); +// } + +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// mainAxisSize: MainAxisSize.max, +// children: [ +// Expanded( +// child: ListView.builder( +// shrinkWrap: true, +// itemCount: filteredItems.length + 1, +// itemBuilder: (context, index) { +// if (index == 0) return widget.header; +// return widget.itemBuilder(filteredItems[index - 1]); +// }, +// ), +// ), +// Padding( +// padding: const EdgeInsets.all(30.0), +// child: TextFormField( +// controller: editingController, +// onChanged: filter, +// cursorColor: Colors.black, +// cursorWidth: 2.0, +// cursorRadius: Radius.circular(2.0), +// style: TextStyle( +// color: Colors.black, +// fontSize: 16.0, +// ), +// keyboardType: TextInputType.text, +// textInputAction: TextInputAction.search, +// autocorrect: true, +// textCapitalization: TextCapitalization.sentences, +// decoration: InputDecoration( +// prefixIcon: Icon(Icons.search, color: Colors.black), +// labelText: 'Pesquisar', +// labelStyle: TextStyle( +// color: Colors.black, +// fontSize: 16.0, +// ), +// hintText: 'Digite sua pesquisa', +// hintStyle: TextStyle( +// color: Colors.grey, +// fontSize: 14.0, +// ), +// filled: true, +// fillColor: Colors.white, +// contentPadding: +// EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), +// enabledBorder: OutlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: Colors.black), +// ), +// focusedBorder: OutlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: Colors.blue), +// ), +// errorBorder: OutlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: Colors.red), +// ), +// focusedErrorBorder: OutlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: Colors.red, width: 2.0), +// ), +// ), +// )), +// ], +// ); +// } +// } + +// /// ----------------------------------------------- +// /// [EnhancedRemoteListView] +// /// ----------------------------------------------- + +// // ignore: must_be_immutable +// class EnhancedRemoteListView extends EnhancedListView { +// final Widget Function(BuildContext, T, int) bodyBuilder; +// final Future> Function() headerItems; +// Widget Function(Future> Function() gen) headerBuilder; +// final PagingController pagingController; +// final Future<(bool, List?)> Function(int pageKey, Query query) +// dataProvider; + +// final void Function(Object, StackTrace) onFetchError; + +// EnhancedRemoteListView({ +// Key? key, +// // required this.fetchItems, +// required this.bodyBuilder, +// required this.headerItems, +// required this.headerBuilder, +// required this.pagingController, +// required this.dataProvider, +// required this.onFetchError, +// }) : super(key: key); + +// @override +// EnhancedRemoteListViewState createState() => +// EnhancedRemoteListViewState(); +// } + +// class EnhancedRemoteListViewState +// extends State> with Pageable { +// TextEditingController editingController = TextEditingController(); +// bool isLoading = false; +// Query query = Document.fromDesc(''); + +// @override +// void initState() { +// widget.pagingController.addPageRequestListener( +// (page) => fetchPage( +// dataProvider: () async => await widget.dataProvider(page, query), +// onDataUnavailable: () => showNoMoreDataSnackBar(context), +// onDataAvailable: (data) => +// widget.pagingController.appendLastPage(data), +// onFetchError: (e, s) => widget.onFetchError), +// ); +// widget.pagingController.addStatusListener(_showError); + +// super.initState(); +// } + +// Future _showError(PagingStatus status) async { +// if (status == PagingStatus.subsequentPageError) { +// final message = FFLocalizations.of(context).getVariableText( +// enText: 'Something went wrong while fetching a new page.', +// ptText: 'Algo deu errado ao buscar uma nova página.', +// ); +// final retry = FFLocalizations.of(context).getVariableText( +// enText: 'Retry', +// ptText: 'Recarregar', +// ); + +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text(message), +// action: SnackBarAction( +// label: retry, +// onPressed: () => widget.pagingController.retryLastFailedRequest(), +// ), +// ), +// ); +// } +// } + +// void filter(Query data) async { +// if (data is Category) { +// safeSetState(() => query = Category( +// id: data.id, +// color: data.color, +// title: data.title, +// )); +// widget.pagingController.refresh(); +// } else if (data is Document) { + +// safeSetState(() => query = data); +// widget.pagingController.refresh(); +// } else { +// safeSetState(() { +// query = Document.fromDesc(''); +// }); +// widget.pagingController.refresh(); +// } +// } + +// @override +// Widget build(BuildContext context) { +// final noDataFound = FFLocalizations.of(context).getVariableText( +// ptText: "Nenhum item encontrado!", +// enText: "No item found", +// ); +// final theme = FlutterFlowTheme.of(context); +// final locale = FFLocalizations.of(context); + +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// mainAxisSize: MainAxisSize.max, +// children: [ +// buildPaginatedListView( +// noDataFound, +// widget.pagingController, +// widget.headerItems, +// widget.headerBuilder, +// widget.bodyBuilder, +// ), +// Padding( +// padding: const EdgeInsets.all(8.0), +// child: TextFormField( +// controller: editingController, +// onChanged: (value) => EasyDebounce.debounce( +// '_model.keyTextFieldTextController', +// const Duration(milliseconds: 500), +// () => filter(Document.fromDesc(value)), +// ), +// cursorColor: theme.primaryText, +// showCursor: false, +// cursorWidth: 2.0, +// cursorRadius: Radius.circular(100), +// style: TextStyle( +// color: theme.primaryText, +// fontSize: 16.0, +// decorationColor: Colors.amber, +// ), +// keyboardType: TextInputType.text, +// textInputAction: TextInputAction.search, +// autocorrect: true, +// textCapitalization: TextCapitalization.sentences, +// decoration: InputDecoration( +// prefixIcon: Icon(Icons.search, color: theme.primary), +// labelText: locale.getVariableText( +// ptText: 'Pesquisar', +// enText: 'Search', +// ), +// labelStyle: TextStyle( +// color: theme.primaryText, +// fontSize: 16.0, +// ), +// hintText: locale.getVariableText( +// ptText: 'Digite sua pesquisa', +// enText: 'Enter your search', +// ), +// hintStyle: TextStyle( +// color: theme.accent2, +// fontSize: 14.0, +// ), +// filled: true, +// fillColor: Colors.transparent, +// helperStyle: TextStyle( +// color: theme.primaryText, +// decorationColor: theme.primaryText, +// ), +// focusColor: theme.primaryText, +// contentPadding: +// EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), +// enabledBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// focusedBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// errorBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText), +// ), +// focusedErrorBorder: UnderlineInputBorder( +// borderRadius: BorderRadius.all(Radius.circular(15.0)), +// borderSide: BorderSide(color: theme.primaryText, width: 2.0), +// ), +// ), +// ), +// ), +// ], +// ); +// } +// } diff --git a/lib/shared/widgets/model.dart b/lib/shared/widgets/model.dart new file mode 100644 index 00000000..0bea7b2f --- /dev/null +++ b/lib/shared/widgets/model.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; + +class ModelWidget extends Widget { + const ModelWidget({super.key}); + + @override + Element createElement() { + // TODO: implement createElement + throw UnimplementedError(); + } +} diff --git a/lib/shared/widgets/page.dart b/lib/shared/widgets/page.dart new file mode 100644 index 00000000..492c3651 --- /dev/null +++ b/lib/shared/widgets/page.dart @@ -0,0 +1,26 @@ +import 'package:flutter/widgets.dart'; +import 'package:hub/shared/mixins/template_mixin.dart'; +import 'package:hub/shared/widgets.dart'; + +/// [PageWidget] + +abstract class PageWidget extends Widget { + const PageWidget({super.key}); +} + +abstract class ModelPage extends ModelWidget implements PageWidget { + const ModelPage({super.key}); +} + +abstract class StatelessPage extends StatelessWidget + with Template + implements PageWidget { + const StatelessPage({super.key}); +} + +abstract class StatefulPage extends StatefulWidget implements PageWidget { + const StatefulPage({super.key}); +} + +abstract class PageState extends State + with Template {} diff --git a/lib/shared/widgets/read_view.dart b/lib/shared/widgets/read_view.dart new file mode 100644 index 00000000..4cd5a806 --- /dev/null +++ b/lib/shared/widgets/read_view.dart @@ -0,0 +1,183 @@ +import 'dart:developer'; +import 'dart:io'; +import 'package:flutter/material.dart'; +// Removed unnecessary import +import 'package:hub/flutter_flow/index.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; +import 'package:hub/shared/widgets.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdfx/pdfx.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:http/http.dart' as http; + +typedef ReadViewController = PdfController; +typedef DocumentType = PdfDocument; + +abstract interface class Viewer extends StatelessComponent { + final String src; + + const Viewer({ + super.key, + required this.src, + }); + + @override + Widget build(BuildContext context) { + return buildViewer(context); + } + + Widget buildViewer(BuildContext context); +} + +class ReadView extends StatefulWidget { + final String url; + final String title; + final VoidCallback onError; + + const ReadView({ + super.key, + required this.onError, + required this.url, + required this.title, + }); + + @override + State createState() => ReadViewState(); +} + +class ReadViewState extends State { + Future _initializePdf() async { + try { + final file = await downloadPdf(widget.url); + final Future document = DocumentType.openFile(file.path); + return ReadViewController(document: document); + } catch (e) { + final message = FFLocalizations.of(context).getVariableText( + ptText: 'Erro ao baixar o PDF', + enText: 'Error downloading PDF', + ); + + return Future.error(message); + } + } + + Future downloadPdf(String url) async { + try { + final response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + final bytes = response.bodyBytes; + final dir = await getTemporaryDirectory(); + final file = File('${dir.path}/downloaded.pdf'); + await file.writeAsBytes(bytes); + return file; + } else { + throw Exception('Falha ao baixar o PDF'); + } + } catch (e) { + final message = FFLocalizations.of(context).getVariableText( + ptText: 'Erro ao baixar o PDF', + enText: 'Error downloading PDF', + ); + await throwError(message, e); + rethrow; + } + } + + Future throwError(String message, dynamic error) async { + log('$message: $error'); + await DialogUtil.error(context, message) + .whenComplete(() => widget.onError()); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + _buildPDFViewer(context), + buildShareButton(context), + ], + ); + } + + Positioned buildShareButton(BuildContext context) { + final theme = FlutterFlowTheme.of(context); + return Positioned( + bottom: 10, + right: 10, + child: IconButton( + icon: Icon( + Icons.share, + color: theme.primaryText, + ), + color: theme.primaryText, + onPressed: onShare, + ), + ); + } + + Future onShare() async { + try { + final Uri uri = Uri.parse(widget.url); + final response = await http.get(uri); + if (response.statusCode == 200) { + final XFile xfile = XFile.fromData(response.bodyBytes, + name: '${widget.title}.pdf', mimeType: 'application/pdf'); + await Share.shareXFiles([xfile], + text: 'Confira este PDF!', + fileNameOverrides: ['${widget.title}.pdf']); + } else { + throw Exception( + 'Erro ao compartilhar o arquivo: ${response.statusCode}'); + } + } catch (e) { + final message = FFLocalizations.of(context).getVariableText( + ptText: 'Erro ao compartilhar o arquivo', + enText: 'Error sharing file', + ); + await throwError(message, e); + } + } + + Widget buildLoadingIndicator(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 15), + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + FlutterFlowTheme.of(context).primary, + ), + ), + ), + ); + } + + Widget _buildPDFViewer(BuildContext context) => Padding( + padding: EdgeInsets.all(10), + child: FutureBuilder( + future: _initializePdf(), + builder: (context, snapshot) { + if (!snapshot.hasData) return buildLoadingIndicator(context); + if (snapshot.error != null) { + return buildLoadingIndicator(context); + } + if (snapshot.connectionState == ConnectionState.waiting) { + return buildLoadingIndicator(context); + } + + return PdfView( + controller: snapshot.data!, + renderer: (PdfPage page) => page.render( + width: page.width * 2, + height: page.height * 2, + cropRect: Rect.fromLTWH( + 10.0, 10.0, page.width * 2, page.height * 2), + forPrint: false, + quality: 100, + format: PdfPageImageFormat.jpeg, + backgroundColor: '#ffffff', + ), + scrollDirection: Axis.vertical, + ); + }), + ); +} diff --git a/lib/shared/widgets/screen.dart b/lib/shared/widgets/screen.dart new file mode 100644 index 00000000..3acf7a57 --- /dev/null +++ b/lib/shared/widgets/screen.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:hub/shared/mixins/template_mixin.dart'; +import 'package:hub/shared/widgets.dart'; + +abstract class ScreenWidget extends Widget { + const ScreenWidget({super.key}); +} + +abstract class ModelScreen extends ModelWidget implements ScreenWidget { + const ModelScreen({super.key}); +} + +abstract class StatelessScreen extends StatelessWidget + with Template + implements ScreenWidget { + const StatelessScreen({super.key}); +} + +abstract class StatefulScreen extends StatefulWidget + implements ScreenWidget { + const StatefulScreen({super.key}); +} + +abstract class ScreenState extends State + with Template {} diff --git a/lib/shared/widgets/text.dart b/lib/shared/widgets/text.dart new file mode 100644 index 00000000..c18c2861 --- /dev/null +++ b/lib/shared/widgets/text.dart @@ -0,0 +1,12 @@ +import 'package:auto_size_text/auto_size_text.dart'; + +class AutoText extends AutoSizeText { + const AutoText( + super.text, { + super.key, + super.style, + super.overflow, + super.textAlign, + super.maxLines, + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index d2873adf..d30605b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,77 +1,103 @@ +# Informações básicas do projeto name: hub -description: A new Flutter project. +description: . # Descrição do projeto (adicione mais detalhes se necessário) +publish_to: "none" # Destino de publicação -publish_to: "none" version: 1.4.0+28 +# Restrições de versão do SDK Dart environment: - sdk: ">=3.0.0 <4.0.0" + sdk: ">=3.5.0-0.0.dev <4.0.0" +# Dependências do aplicativo dependencies: + # Dependências essenciais do Flutter flutter: sdk: flutter flutter_localizations: sdk: flutter + + # Gerenciamento de Estado + provider: 6.1.2 + flutter_bloc: ^9.0.0 + flutter_riverpod: ^2.5.1 + rx_bloc: ^6.0.1 + flutter_rx_bloc: ^7.0.0 + rx_bloc_list: ^5.0.1 + rxdart: ^0.28.0 + rx_bloc_test: ^5.0.0 + bloc_test: ^10.0.0 + bloc_concurrency: ^0.3.0 + hydrated_bloc: ^10.0.0 + + # Programação Funcional + dart_either: ^2.0.0 + result_dart: ^2.0.0 + fpdart: ^1.1.1 + + # Pacotes de UI + flutter_pdfview: ^1.4.0 + pdfx: ^2.8.0 auto_size_text: 3.0.0 barcode_widget: ^2.0.4 infinite_scroll_pagination: ^4.1.0 cached_network_image: ^3.4.0 - firebase_core: ^3.4.0 flutter_inappwebview: ^6.0.0 webview_flutter: ^4.8.0 - rxdart: ^0.28.0 + flutter_spinkit: 5.2.1 + flutter_staggered_grid_view: 0.7.0 + flutter_svg: ^2.0.15 + font_awesome_flutter: ^10.8.0 + google_fonts: 6.2.1 + material_symbols_icons: ^4.2784.0 + fluttertoast: ^8.2.8 + cupertino_icons: ^1.0.0 + qr_flutter: ^4.1.0 + percent_indicator: ^4.2.3 + page_transition: ^2.2.1 + share_plus: ^10.1.4 + dropdown_button2: ^2.3.9 + + # Firebase + firebase_core: ^3.4.0 + firebase_messaging: ^15.1.0 + firebase_analytics: ^11.3.0 + firebase_crashlytics: ^4.0.1 + + # Utilidades + app_links: ^6.3.3 collection: ^1.18.0 - app_links: ^6.3.2 - # crop_your_image: 1.1.0 csv: 6.0.0 device_info_plus: ^10.1.2 - firebase_messaging: ^15.1.0 - dropdown_button2: 2.3.9 easy_debounce: 2.0.3 equatable: ^2.0.6 file_picker: ^8.0.7 - # flutter_expandable_fab: ^2.1.0 - firebase_analytics: ^11.3.0 flutter_animate: ^4.5.2 - # flutter_cache_manager: ^3.4.1 - # flutter_plugin_android_lifecycle: ^2.0.23 - share_plus: ^10.0.0 - # connectivity_plus: ^6.0.5 flutter_secure_storage: ^10.0.0-beta.2 flutter_secure_storage_linux: ^2.0.0 flutter_secure_storage_macos: ^4.0.0 flutter_secure_storage_platform_interface: ^2.0.1 flutter_secure_storage_web: ^2.0.0 flutter_secure_storage_windows: ^4.0.0 - flutter_spinkit: 5.2.1 - flutter_staggered_grid_view: 0.7.0 - flutter_svg: ^2.0.15 - font_awesome_flutter: ^10.8.0 from_css_color: 2.0.0 go_router: ^14.3.0 - google_fonts: 6.2.1 - http: 1.2.1 + http: ^1.3.0 image_picker: 1.1.2 image_picker_android: ^0.8.12+15 image_picker_for_web: ^3.0.5 - persistent_bottom_nav_bar: ^6.2.1 image_picker_ios: ^0.8.12+1 image_picker_platform_interface: ^2.10.1 local_auth: ^2.2.0 intl: ^0.19.0 - # camera: ^0.11.0+2 json_path: ^0.7.4 mime_type: ^1.0.1 - page_transition: ^2.2.1 path_provider: ^2.1.4 path_provider_android: ^2.2.12 google_mlkit_face_detection: ^0.12.0 path_provider_foundation: ^2.4.1 path_provider_platform_interface: 2.1.2 - percent_indicator: ^4.2.3 plugin_platform_interface: 2.1.8 - provider: 6.1.2 shared_preferences: ^2.3.2 shared_preferences_android: ^2.3.3 shared_preferences_foundation: ^2.5.3 @@ -85,19 +111,7 @@ dependencies: url_launcher_android: ^6.3.12 url_launcher_ios: ^6.3.1 url_launcher_platform_interface: 2.3.2 - # video_player: 2.8.7 - # video_player_android: 2.5.0 - # video_player_avfoundation: 2.6.1 - # video_player_platform_interface: 6.2.2 - # video_player_web: 2.3.1 - material_symbols_icons: ^4.2784.0 - fluttertoast: ^8.2.8 - cupertino_icons: ^1.0.0 - flutter_bloc: ^9.0.0 - flutter_riverpod: ^2.5.1 - qr_flutter: ^4.1.0 permission_handler: ^11.3.1 - firebase_crashlytics: ^4.0.1 awesome_notifications: ^0.10.0 app_tracking_transparency: ^2.0.6+1 # dio: ^5.7.0 @@ -105,65 +119,74 @@ dependencies: freezed_annotation: ^2.4.4 package_info_plus: ^8.1.1 sliver_tools: ^0.2.12 - # json_annotation: ^4.9.0 - base: - git: - url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' - path: 'packages/base' - components: - git: - url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' - path: 'packages/components' - templates: - git: - url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' - path: 'packages/templates' - theme: - git: - url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' - path: 'packages/theme' + json_annotation: ^4.9.0 + # Dependências a partir de repositório Git (pacotes personalizados) + # base: + # git: + # url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' + # path: 'packages/base' + # components: + # git: + # url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' + # path: 'packages/components' + # templates: + # git: + # url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' + # path: 'packages/templates' + # theme: + # git: + # url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git' + # path: 'packages/theme' +# Substituição de versões específicas de pacotes, se necessário dependency_overrides: - http: 1.2.1 + http: ^1.3.0 uuid: ^4.0.0 win32: 5.5.1 +# Dependências para desenvolvimento e testes dev_dependencies: + bloc_lint: ^0.1.0 + rx_bloc_generator: ^8.0.1 flutter_launcher_icons: ^0.14.1 flutter_lints: ^5.0.0 image: ^4.3.0 lints: ^5.0.0 - # build_runner: ^2.4.13 mockito: ^5.4.4 integration_test: sdk: flutter flutter_test: sdk: flutter - build_runner: ^2.4.13 - freezed: ^2.5.7 - json_serializable: ^6.9.0 + build_runner: ^2.4.14 + freezed: ^3.0.0-0.0.dev + json_serializable: ^6.9.4 test: ^1.25.7 patrol: ^3.13.2 patrol_finders: ^2.6.0 +# Configuração do flutter_launcher_icons flutter_launcher_icons: - android: "launcher_icon" - ios: true + android: "launcher_icon" # Nome da pasta/ícone para Android + ios: true # Geração de ícones para iOS web: - generate: true + generate: true # Geração de ícones para Web image_path: "assets/images/app_launcher_icon.svg" adaptive_icon_background: "assets/images/adaptive_background_icon.svg" adaptive_icon_foreground: "assets/images/adaptive_foreground_icon.svg" +# Configurações específicas do Flutter flutter: - uses-material-design: true + uses-material-design: true # Habilita o uso do Material Design + # Definição de assets (imagens, fontes, etc.) assets: - assets/fonts/ - assets/images/ - assets/images/dark/ - assets/images/light/ + +# Configuração de fontes customizadas fonts: - family: "SF Pro" fonts: @@ -176,13 +199,15 @@ fonts: - family: Icons fonts: - asset: assets/fonts/icons.ttf + - family: Menu fonts: - asset: assets/fonts/menu.ttf +# Configuração do Patrol (ferramenta para testes de integração) patrol: app_name: FRE ACCESS HUB android: package_name: com.freaccess.hub ios: - bundle_id: br.com.freaccess.hub \ No newline at end of file + bundle_id: br.com.freaccess.hub