diff --git a/assets/files/document.pdf b/assets/files/document.pdf new file mode 100644 index 00000000..9a84c2fc Binary files /dev/null and b/assets/files/document.pdf 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 6267453a..c2b4bbb9 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -1,5 +1,4 @@ import 'dart:collection'; -import 'dart:math'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -7,12 +6,9 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:go_router/go_router.dart'; import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart'; import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; -import 'package:hub/components/templates_components/forgot_password_template_component/forgot_password_template_component_widget.dart'; import 'package:hub/features/backend/api_requests/index.dart'; import 'package:hub/features/local/index.dart'; import 'package:hub/features/menu/index.dart'; @@ -22,12 +18,9 @@ import 'package:hub/features/notification/index.dart'; import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/index.dart' as ff; import 'package:hub/flutter_flow/index.dart'; -import 'package:hub/initialization.dart'; import 'package:hub/main.dart'; -import 'package:hub/pages/forgot_password_page/forgot_password_screen.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 4045cfc3..a60a5b1f 100644 --- a/integration_test/auth_test.dart +++ b/integration_test/auth_test.dart @@ -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/lib/components/atomic_components/shared_components_atoms/toast.dart b/lib/components/atomic_components/shared_components_atoms/toast.dart index 1be2a15e..30cc5332 100644 --- a/lib/components/atomic_components/shared_components_atoms/toast.dart +++ b/lib/components/atomic_components/shared_components_atoms/toast.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:hub/shared/utils/limited_text_size.dart'; class ToastUtil { static void showToast({ 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 b832653e..00f5922e 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; 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 9c96f384..a5527a22 100644 --- a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart +++ b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart @@ -4,7 +4,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'; 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_schedule_template_model.dart b/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart index c1e82767..2985cbba 100644 --- a/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart +++ b/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:hub/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart'; import 'package:hub/features/backend/index.dart'; 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 4a9c5ebe..e17b808b 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'; @@ -35,7 +34,6 @@ class RegisiterVistorTemplateComponentWidget extends StatefulWidget { class _RegisiterVistorTemplateComponentWidgetState extends State { late RegisiterVistorTemplateComponentModel _model; - bool _isLoading = false; final scaffoldKey = GlobalKey(); bool _isVisitorRegistered = false; @@ -43,10 +41,6 @@ class _RegisiterVistorTemplateComponentWidgetState final _formKey = GlobalKey(); - void _resetForm() { - _formKey.currentState?.reset(); - } - @override void initState() { super.initState(); 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/core/meta/anotations.dart b/lib/core/meta/anotations.dart index af721eaa..842e5064 100644 --- a/lib/core/meta/anotations.dart +++ b/lib/core/meta/anotations.dart @@ -1,5 +1,3 @@ -import 'package:meta/meta.dart'; - class DeadCode { final String? desc; diff --git a/lib/features/backend/api_requests/api_calls.dart b/lib/features/backend/api_requests/api_calls.dart index 72d1a8a2..e4bdd4fc 100644 --- a/lib/features/backend/api_requests/api_calls.dart +++ b/lib/features/backend/api_requests/api_calls.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unused_element + import 'dart:async'; import 'dart:convert'; import 'dart:developer'; diff --git a/lib/features/backend/schema/structs/device_struct.dart b/lib/features/backend/schema/structs/device_struct.dart index db8a8896..0bd580ec 100644 --- a/lib/features/backend/schema/structs/device_struct.dart +++ b/lib/features/backend/schema/structs/device_struct.dart @@ -3,8 +3,6 @@ import 'package:hub/features/backend/index.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'index.dart'; - class DeviceStruct extends BaseStruct { DeviceStruct({ String? devUUID, diff --git a/lib/features/documents/document_item_component.dart b/lib/features/documents/document_item_component.dart new file mode 100644 index 00000000..3c0ff117 --- /dev/null +++ b/lib/features/documents/document_item_component.dart @@ -0,0 +1,154 @@ +part of 'index.dart'; + +interface class Category extends Entity { + final Color color; + final String title; + + Category({ + required this.color, + required this.title, + }); +} + +interface class Document extends Entity { + final String title; + final String description; + final Category category; + final String to; + final String from; + final String createdAt; + final String updatedAt; + + Document({ + required this.createdAt, + required this.updatedAt, + required this.category, + required this.to, + required this.from, + required this.title, + required this.description, + }); +} + +class DocumentItem extends StatelessWidget { + final Document document; + + const DocumentItem({Key? key, required this.document}) : super(key: key); + + Tooltip _buildTooltip(String text, Color color, BuildContext context, + BoxConstraints constraints) { + final Color textColor = FlutterFlowTheme.of(context).info; + + final double boxHeight = MediaQuery.of(context).size.height * 0.02; + final double boxWidth = MediaQuery.of(context).size.height * 0.1; + + 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; + + return InkWell( + onTap: () => print('Click'), + enableFeedback: true, + overlayColor: MaterialStateProperty.all(primaryColor), + borderRadius: BorderRadius.circular(10), + child: SizedBox( + height: boxHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // const SizedBox(width: 10), + Icon(Icons.description, color: document.category.color), + // const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Tooltip( + message: document.title, + child: AutoText( + document.title, + style: textStyleMajor, + overflow: TextOverflow.ellipsis, + ), + ), + AutoText( + document.updatedAt, + style: textStyleMinor, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _buildTooltip( + document.category.title, + document.category.color, + context, + constraints, + ), + ], + ), + ), + // const SizedBox(width: 10), + Center( + child: Icon( + Icons.arrow_right, + color: primaryText, + ), + ), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/features/documents/document_manager_screen.dart b/lib/features/documents/document_manager_screen.dart new file mode 100644 index 00000000..407a5427 --- /dev/null +++ b/lib/features/documents/document_manager_screen.dart @@ -0,0 +1,92 @@ +part of 'index.dart'; + +class DocumentManagerScreen extends StatelessScreen { + DocumentManagerScreen({ + super.key, + required this.documents, + required this.categories, + }); + + List documents; + final List categories; + + @override + Widget build(BuildContext context) { + final GlobalKey _listViewKey = + GlobalKey(); + + bool filter(document, query) { + final lowerQuery = query.toLowerCase(); + return document.title.toLowerCase().contains(lowerQuery) || + document.description.toLowerCase().contains(lowerQuery) || + document.category.title.toLowerCase().contains(lowerQuery) || + document.to.toLowerCase().contains(lowerQuery) || + document.from.toLowerCase().contains(lowerQuery) || + document.createdAt.toLowerCase().contains(lowerQuery) || + document.updatedAt.toLowerCase().contains(lowerQuery); + } + + DocumentItem itemBuilder(document) => DocumentItem(document: document); + + void filterByCategory(Category query) { + print('Test'); + final state = _listViewKey.currentState; + + if (state != null) { + state.safeSetState(() { + state.filteredItems = documents + .where((documents) => filter(documents, query.title)) + .toList(); + }); + } + } + + void unfilter(Category) { + final state = _listViewKey.currentState; + if (state != null) { + state.safeSetState(() { + state.filteredItems = documents; + }); + } + } + + final header = Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 50, 0), + child: Text('Últimos Documentos'), + ), + CategoryCarousel( + categories: categories, + onSelect: filterByCategory, + onUnselect: unfilter, + ), + ], + ); + List filterByString(String query) { + return documents.where((documents) => filter(documents, query)).toList(); + } + + final SizedBox space = SizedBox(height: 30); + + return Column( + children: [ + Expanded( + child: LocalSearchView( + key: _listViewKey, + header: header, + onSearch: filterByString, + list: documents, + itemBuilder: itemBuilder, + filter: filter, + ), + ), + ] // + .addToStart(space) + .addToEnd(space), + ); + } +} diff --git a/lib/features/documents/document_page_model.dart b/lib/features/documents/document_page_model.dart new file mode 100644 index 00000000..9ec58ac2 --- /dev/null +++ b/lib/features/documents/document_page_model.dart @@ -0,0 +1 @@ +part of 'index.dart'; diff --git a/lib/features/documents/document_page_widget.dart b/lib/features/documents/document_page_widget.dart new file mode 100644 index 00000000..99dc2849 --- /dev/null +++ b/lib/features/documents/document_page_widget.dart @@ -0,0 +1,70 @@ +part of 'index.dart'; + +List generateDocuments(int count) { + String str() => randomString(8, 8, true, true, true); + Color color() => randomColor(); + + return List.generate( + count, + (index) => Document( + title: 'Lorem Ipsum et Cetera $index', + description: 'Description for document $index', + category: Category(color: color(), title: str()), + to: str(), + from: str(), + createdAt: '00/00/0000', + updatedAt: '00/00/0000', + ), + ); +} + +List generateCategories(List documents) { + final Map categoryMap = {}; + + for (var document in documents) { + final category = document.category; + if (!categoryMap.containsKey(category.title)) { + categoryMap[category.title] = category; + } + } + + return categoryMap.values.toList(); +} + +class FREDocumentPage extends StatefulPage { + const FREDocumentPage({super.key}); + + @override + State createState() => _FREDocumentPageState(); +} + +class _FREDocumentPageState extends PageState { + @override + Widget build(BuildContext context) { + final String title = FFLocalizations.of(context) + .getVariableText(enText: 'Documents', ptText: 'Documentos'); + + return Scaffold( + appBar: buildAppBar(title, context), + body: buildBody(context), + ); + } + + late List documents; + late List categories; + + @override + void initState() { + super.initState(); + documents = generateDocuments(20); + categories = generateCategories(documents); + } + + Widget buildBody(BuildContext context) { + return DocumentManagerScreen( + documents: documents, + categories: categories, + ); + // return DocumentViewScreen(document: documents.first); + } +} diff --git a/lib/features/documents/document_viewer_screen.dart b/lib/features/documents/document_viewer_screen.dart new file mode 100644 index 00000000..9c4a0c63 --- /dev/null +++ b/lib/features/documents/document_viewer_screen.dart @@ -0,0 +1,48 @@ +part of 'index.dart'; + +class DocumentViewScreen extends StatefulScreen { + const DocumentViewScreen({ + super.key, + required this.document, + }); + + final Document document; + + @override + State createState() => _DocumentViewScreenState(); +} + +class _DocumentViewScreenState extends State { + final PDFViewerState _viewerKey = PDFViewerState(); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: FREViewerPDF( + key: _viewerKey, + url: + 'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf', + ), + ), + Positioned( + bottom: 10, + right: 10, + child: IconButton( + icon: Icon(Icons.share, color: Colors.black), + color: Colors.black, + onPressed: () { + _viewerKey.currentState?.openBookmarkView(); + // Share.share(FFLocalizations.of(context).getVariableText( + // ptText: '', + // enText: '', + // )); + }, + ), + ), + ], + ); + } +} diff --git a/lib/features/documents/index.dart b/lib/features/documents/index.dart new file mode 100644 index 00000000..c32958c7 --- /dev/null +++ b/lib/features/documents/index.dart @@ -0,0 +1,12 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:hub/shared/utils/index.dart'; +import 'package:hub/shared/widgets/widgets.dart'; + +part 'document_manager_screen.dart'; +part 'document_page_widget.dart'; +part 'document_viewer_screen.dart'; +part 'document_page_model.dart'; +part 'document_item_component.dart'; diff --git a/lib/features/history/presentation/pages/provisional_history_page.dart b/lib/features/history/presentation/pages/provisional_history_page.dart index e4bfde25..ae43ad8d 100644 --- a/lib/features/history/presentation/pages/provisional_history_page.dart +++ b/lib/features/history/presentation/pages/provisional_history_page.dart @@ -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/history/presentation/widgets/provisional_filter_modal.dart b/lib/features/history/presentation/widgets/provisional_filter_modal.dart index 44d0f538..5928e05d 100644 --- a/lib/features/history/presentation/widgets/provisional_filter_modal.dart +++ b/lib/features/history/presentation/widgets/provisional_filter_modal.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import '/flutter_flow/flutter_flow_util.dart'; diff --git a/lib/features/home/presentation/pages/about_system.dart b/lib/features/home/presentation/pages/about_system.dart index 7255388f..19b9de55 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 e259f2c3..c63aec38 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 @@ -58,7 +58,7 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource { }, conflictAlgorithm: ConflictAlgorithm.replace, ); - } catch (e, s) {} + } catch (e) {} } @override 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..fbe41ff1 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 @@ -41,10 +41,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { return; } 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; } @@ -82,10 +82,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; } @@ -140,10 +140,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { log('() => stack: $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; } @@ -168,10 +168,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { if (response.jsonBody == null) { final GetLocalsCall callback = PhpGroup.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; } @@ -180,8 +180,8 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { if (isError == true) { final GetLocalsCall callback = PhpGroup.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 { @@ -190,10 +190,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { } } 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', - ); + // 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; } diff --git a/lib/features/local/data/repositories/locals_repository_impl.dart b/lib/features/local/data/repositories/locals_repository_impl.dart index d171256e..a1cf5fdc 100644 --- a/lib/features/local/data/repositories/locals_repository_impl.dart +++ b/lib/features/local/data/repositories/locals_repository_impl.dart @@ -107,6 +107,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/menu/presentation/mappers/menu_entry.dart b/lib/features/menu/presentation/mappers/menu_entry.dart index 7e1a4b00..f290b98c 100644 --- a/lib/features/menu/presentation/mappers/menu_entry.dart +++ b/lib/features/menu/presentation/mappers/menu_entry.dart @@ -160,6 +160,16 @@ class MenuEntry implements BaseModule { route: '/acessHistoryPage', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), + MenuEntry( + key: 'FRE-HUB-DOCUMENT', + icon: Icons.document_scanner, + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( + ptText: 'Documentos', + enText: 'Documents', + ), + route: '/documentPage', + types: [MenuEntryType.Home, MenuEntryType.Drawer], + ), MenuEntry( key: 'FRE-HUB-LIBERATIONS', icon: Icons.how_to_reg_outlined, diff --git a/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart b/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart index c8f81e31..d5142c21 100644 --- a/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart +++ b/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart @@ -76,16 +76,15 @@ class _MenuButtonWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.icon != null) - Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 8.0), - child: Icon( - widget.icon, - size: 24.0, - color: FlutterFlowTheme.of(context).primaryText, - ), + Container( + alignment: Alignment.topLeft, + padding: const EdgeInsets.only(left: 8.0), + child: Icon( + widget.icon, + size: 24.0, + color: FlutterFlowTheme.of(context).primaryText, ), + ), Flexible( child: Padding( padding: const EdgeInsets.only(left: 10.0), diff --git a/lib/features/module/data/models/license_model.dart b/lib/features/module/data/models/license_model.dart index 48e215cc..df9e8f87 100644 --- a/lib/features/module/data/models/license_model.dart +++ b/lib/features/module/data/models/license_model.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'module_model.dart'; diff --git a/lib/features/module/data/models/module_model.dart b/lib/features/module/data/models/module_model.dart index e373edc3..17a2f23b 100644 --- a/lib/features/module/data/models/module_model.dart +++ b/lib/features/module/data/models/module_model.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'module_model.freezed.dart'; diff --git a/lib/features/module/domain/entities/base_module.dart b/lib/features/module/domain/entities/base_module.dart index 1cfbeef0..9e8759aa 100644 --- a/lib/features/module/domain/entities/base_module.dart +++ b/lib/features/module/domain/entities/base_module.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/flutter_flow/nav/nav.dart'; abstract class BaseModule { String get key; diff --git a/lib/features/module/domain/entities/license.dart b/lib/features/module/domain/entities/license.dart index 17a70650..b5b73407 100644 --- a/lib/features/module/domain/entities/license.dart +++ b/lib/features/module/domain/entities/license.dart @@ -25,7 +25,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); @@ -137,6 +138,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 4f6ba58d..77792519 100644 --- a/lib/features/notification/deep_link_service.dart +++ b/lib/features/notification/deep_link_service.dart @@ -1,5 +1,4 @@ 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'; diff --git a/lib/features/profile/data/data_sources/profile_local_data_source.dart b/lib/features/profile/data/data_sources/profile_local_data_source.dart index 8b0f9d1e..ee9bb176 100644 --- a/lib/features/profile/data/data_sources/profile_local_data_source.dart +++ b/lib/features/profile/data/data_sources/profile_local_data_source.dart @@ -2,7 +2,6 @@ import 'dart:developer'; import 'package:hub/features/storage/constants/profile_constants.dart'; import 'package:hub/features/storage/index.dart'; -import 'package:hub/shared/constants/index.dart'; import 'package:sqflite/sqflite.dart'; 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/repositories/storage_repository_impl.dart b/lib/features/storage/repositories/storage_repository_impl.dart index 30f3fd0d..1649b05e 100644 --- a/lib/features/storage/repositories/storage_repository_impl.dart +++ b/lib/features/storage/repositories/storage_repository_impl.dart @@ -1,7 +1,6 @@ import 'dart:developer'; import 'package:flutter/cupertino.dart'; -import 'package:hub/features/profile/data/data_sources/profile_local_data_source.dart'; import 'package:hub/features/storage/index.dart'; class StorageHelper implements StorageRepository { diff --git a/lib/flutter_flow/flutter_flow_widgets.dart b/lib/flutter_flow/flutter_flow_widgets.dart index 6845d783..122432eb 100644 --- a/lib/flutter_flow/flutter_flow_widgets.dart +++ b/lib/flutter_flow/flutter_flow_widgets.dart @@ -1,6 +1,5 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:flutter/material.dart'; -import 'package:auto_size_text/auto_size_text.dart'; class FFButtonOptions { const FFButtonOptions({ diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 600a43ad..0da33c1e 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hub/features/backend/index.dart'; +import 'package:hub/features/documents/index.dart'; import 'package:hub/features/history/index.dart'; import 'package:hub/features/home/index.dart'; import 'package:hub/features/local/index.dart'; @@ -298,6 +299,13 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { return PetsPageWidget(pet: pet); }, ), + FFRoute( + name: 'documentPage', + path: '/documentPage', + builder: (context, params) { + return FREDocumentPage(); + }, + ), // 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 04aa29c6..29273fef 100644 --- a/lib/initialization.dart +++ b/lib/initialization.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; @@ -56,21 +54,21 @@ Future _initializeSystemSettings() async { await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); if (kDebugMode) { - //kDebugMode print('Debug mode'); - bool unsentReports = - await FirebaseCrashlytics.instance.checkForUnsentReports(); - if (unsentReports) { - // Existem relatórios não enviados - await crashlyticsInstance.sendUnsentReports(); - print('Existem relatórios de falhas não enviados.'); - } else { - // Não existem relatórios não enviados - print('Todos os relatórios de falhas foram enviados.'); - } } else { print('Release mode'); + // bool unsentReports = + // await FirebaseCrashlytics.instance.checkForUnsentReports(); + // if (unsentReports) { + // // Existem relatórios não enviados + // await crashlyticsInstance.sendUnsentReports(); + // print('Existem relatórios de falhas não enviados.'); + // } else { + // // Não existem relatórios não enviados + // print('Todos os relatórios de falhas foram enviados.'); + // } + await crashlyticsInstance.setCrashlyticsCollectionEnabled(true); // if (crashlyticsInstance.isCrashlyticsCollectionEnabled) { FlutterError.onError = await crashlyticsInstance.recordFlutterError; diff --git a/lib/main.dart b/lib/main.dart index 623ac049..34d1a25f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'dart:io'; 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'; @@ -14,13 +15,21 @@ import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/shared/utils/test_util.dart'; import 'package:responsive_framework/responsive_framework.dart'; 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 initializeApp(); runApp(const ProviderScope(child: App())); @@ -193,6 +202,7 @@ class _AppState extends State { @override Widget build(BuildContext context) { return MaterialApp.router( + scrollBehavior: CustomScrollBehavior(), key: navigatorKey, title: 'FRE ACCESS HUB', builder: builder, 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 e7d5718e..ddd1854a 100644 --- a/lib/pages/reception_page/reception_page_widget.dart +++ b/lib/pages/reception_page/reception_page_widget.dart @@ -1,6 +1,3 @@ -import 'dart:developer'; - -import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -31,9 +28,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); 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..ce4d41a3 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) { 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..65f9a039 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); diff --git a/lib/shared/widgets/component.dart b/lib/shared/widgets/component.dart new file mode 100644 index 00000000..fb1383dc --- /dev/null +++ b/lib/shared/widgets/component.dart @@ -0,0 +1,22 @@ +part of '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}); +} diff --git a/lib/shared/widgets/entity.dart b/lib/shared/widgets/entity.dart new file mode 100644 index 00000000..ae05f63f --- /dev/null +++ b/lib/shared/widgets/entity.dart @@ -0,0 +1,3 @@ +part of 'widgets.dart'; + +abstract class Entity {} diff --git a/lib/shared/widgets/model.dart b/lib/shared/widgets/model.dart new file mode 100644 index 00000000..c35a6491 --- /dev/null +++ b/lib/shared/widgets/model.dart @@ -0,0 +1,11 @@ +part of 'widgets.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..ed08ad58 --- /dev/null +++ b/lib/shared/widgets/page.dart @@ -0,0 +1,64 @@ +part of 'widgets.dart'; + +mixin MixinPage { + PreferredSizeWidget buildAppBar(String title, BuildContext 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, FlutterFlowTheme.of(context)), + centerTitle: true, + elevation: 0.0, + actions: [], + ); + } + + Widget _backButton(BuildContext context, FlutterFlowTheme theme) { + 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: () => Navigator.of(context).pop(), + ); + } +} + +/// [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 + implements PageWidget { + const StatelessPage({super.key}); +} + +abstract class StatefulPage extends StatefulWidget implements PageWidget { + const StatefulPage({super.key}); +} + +abstract class PageState extends State + with MixinPage {} diff --git a/lib/shared/widgets/screen.dart b/lib/shared/widgets/screen.dart new file mode 100644 index 00000000..754a3094 --- /dev/null +++ b/lib/shared/widgets/screen.dart @@ -0,0 +1,19 @@ +part of '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 + implements ScreenWidget { + const StatelessScreen({super.key}); +} + +abstract class StatefulScreen extends StatefulWidget + implements ScreenWidget { + const StatefulScreen({super.key}); +} diff --git a/lib/shared/widgets/text.dart b/lib/shared/widgets/text.dart new file mode 100644 index 00000000..68b8b065 --- /dev/null +++ b/lib/shared/widgets/text.dart @@ -0,0 +1,12 @@ +part of 'widgets.dart'; + +class AutoText extends AutoSizeText { + const AutoText( + super.text, { + super.key, + super.style, + super.overflow, + super.textAlign, + super.maxLines, + }); +} diff --git a/lib/shared/widgets/view/carousel_view.dart b/lib/shared/widgets/view/carousel_view.dart new file mode 100644 index 00000000..fd215ce6 --- /dev/null +++ b/lib/shared/widgets/view/carousel_view.dart @@ -0,0 +1,77 @@ +part of '../widgets.dart'; + +class CategoryCarousel extends StatelessWidget { + final List categories; + final void Function(Category) onSelect; + final void Function(Category) onUnselect; + + const CategoryCarousel({ + super.key, + required this.categories, + required this.onSelect, + required this.onUnselect, + }); + + @override + Widget build(BuildContext context) { + final backgroundTheme = FlutterFlowTheme.of(context).primaryBackground; + + bool isSelected = false; + Category? current = null; + + return Container( + height: 120, + decoration: BoxDecoration( + color: backgroundTheme, + borderRadius: BorderRadius.circular(10), + ), + child: CarouselView( + itemExtent: 100, + onTap: (index) { + if (isSelected && current == categories[index]) { + onUnselect(categories[index]); + isSelected = false; + current = null; + } else { + onSelect(categories[index]); + isSelected = true; + current = categories[index]; + } + }, + children: categories.map((category) { + return GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: category.color, + shape: BoxShape.circle, + ), + child: Icon( + Icons.folder, + color: Colors.white, + size: 40, + ), + ), + const SizedBox(height: 8), + Text( + category.title, + style: TextStyle( + color: category.color, + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/shared/widgets/view/search_view.dart b/lib/shared/widgets/view/search_view.dart new file mode 100644 index 00000000..89bec502 --- /dev/null +++ b/lib/shared/widgets/view/search_view.dart @@ -0,0 +1,200 @@ +part of '../widgets.dart'; + +/// ----------------------------------------------- +/// [SearchView] + +class SearchView extends StatefulComponent { + const SearchView({super.key}); + + @override + State createState() => _SearchViewState(); +} + +class _SearchViewState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + +class LocalSearchView extends SearchView { + final List list; + final Widget Function(T) itemBuilder; + final bool Function(T, String) filter; + final Widget header; + final List Function(String)? onSearch; + + LocalSearchView({ + 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 + LocalSearchViewState createState() => LocalSearchViewState(); +} + +class LocalSearchViewState 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: TextField( + onChanged: filter, + controller: editingController, + cursorColor: Colors.black, + decoration: InputDecoration( + prefixIcon: Icon(Icons.search), + focusColor: Colors.black, + hoverColor: Colors.black, + fillColor: Colors.black, + iconColor: Colors.black, + contentPadding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: + BorderSide(color: Colors.black), // Set border color here + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide( + color: Colors.black), // Set focused border color here + ), + ), + ), + ), + ], + ); + } +} + +class RemoteSearchListView extends SearchView { + final List items; + final String title; + final Widget Function(T) itemBuilder; + final Future> Function(String) fetchItems; + + RemoteSearchListView({ + Key? key, + required this.items, + required this.title, + required this.itemBuilder, + required this.fetchItems, + }) : super(key: key); + + @override + _RemoteSearchViewState createState() => _RemoteSearchViewState(); +} + +class _RemoteSearchViewState extends State> { + TextEditingController editingController = TextEditingController(); + late List filteredItems; + bool isLoading = false; + + @override + void initState() { + filteredItems = widget.items; + super.initState(); + } + + void filterSearchResults(String query) async { + setState(() { + isLoading = true; + }); + final results = await widget.fetchItems(query); + setState(() { + filteredItems = results; + isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + onChanged: (value) { + filterSearchResults(value); + }, + controller: editingController, + decoration: InputDecoration( + labelText: "Search", + hintText: "Search", + prefixIcon: Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(25.0)), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 50, 0), + child: Text('Últimos Documentos'), + ), + isLoading + ? Center(child: CircularProgressIndicator()) + : Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: filteredItems.length, + itemBuilder: (context, index) { + return widget.itemBuilder(filteredItems[index]); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/shared/widgets/viewer/viewer.dart b/lib/shared/widgets/viewer/viewer.dart new file mode 100644 index 00000000..2e5f01c9 --- /dev/null +++ b/lib/shared/widgets/viewer/viewer.dart @@ -0,0 +1,26 @@ +part of '../widgets.dart'; + +typedef PDFViewerState = GlobalKey; + +abstract class Viewer extends StatelessComponent { + const Viewer({super.key, required this.src}); + final String src; + + @override + Widget build(BuildContext context) { + return buildViewer(context); + } + + Widget buildViewer(BuildContext context); +} + +class FREViewerPDF extends Viewer { + const FREViewerPDF({required Key key, required this.url}) + : super(key: key as PDFViewerState, src: url); + final String url; + + @override + Widget buildViewer(BuildContext context) { + return SfPdfViewer.network(src, key: key as PDFViewerState); + } +} diff --git a/lib/shared/widgets/widgets.dart b/lib/shared/widgets/widgets.dart new file mode 100644 index 00000000..7b240209 --- /dev/null +++ b/lib/shared/widgets/widgets.dart @@ -0,0 +1,21 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/features/documents/index.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; + +part 'page.dart'; +part 'component.dart'; +part 'screen.dart'; +part 'model.dart'; +part 'entity.dart'; + +/// [View]'s +part 'view/search_view.dart'; +part 'view/carousel_view.dart'; + +/// [Viewer] +part 'viewer/viewer.dart'; + +part 'text.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 26ed4273..0a647c1b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,8 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - auto_size_text: 3.0.0 + auto_size_text: ^3.0.0 + syncfusion_flutter_pdfviewer: ^28.2.4 barcode_widget: ^2.0.4 cached_network_image: ^3.4.0 firebase_core: ^3.4.0 @@ -24,7 +25,7 @@ dependencies: app_links: ^6.3.2 # crop_your_image: 1.1.0 csv: 6.0.0 - device_info_plus: ^10.1.2 + device_info_plus: ^11.2.2 firebase_messaging: ^15.1.0 dropdown_button2: 2.3.9 easy_debounce: 2.0.3 @@ -50,7 +51,7 @@ dependencies: 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 @@ -106,7 +107,7 @@ dependencies: # json_annotation: ^4.9.0 dependency_overrides: - http: 1.2.1 + http: 1.3.0 uuid: ^4.0.0 win32: 5.5.1 @@ -145,6 +146,7 @@ flutter: - assets/images/ - assets/images/dark/ - assets/images/light/ + - assets/files/ fonts: - family: "SF Pro" fonts: