This commit is contained in:
jantunesmesias 2024-07-11 09:28:06 -03:00
parent b23ab9c2ac
commit 67dd1b9f92
20 changed files with 1216 additions and 107 deletions

File diff suppressed because one or more lines are too long

1
.tool-versions Normal file
View File

@ -0,0 +1 @@
gradle 7.5

View File

@ -39,6 +39,7 @@ class PhpGroup {
static GetLiberationsCall getLiberationsCall = GetLiberationsCall(); static GetLiberationsCall getLiberationsCall = GetLiberationsCall();
static GetLiberationsCopyCall getLiberationsCopyCall = static GetLiberationsCopyCall getLiberationsCopyCall =
GetLiberationsCopyCall(); GetLiberationsCopyCall();
static GetMessagesCall getMessagesCall = GetMessagesCall();
} }
class UpdToken { class UpdToken {
@ -2045,6 +2046,45 @@ class GetLiberationsCall {
.toList(); .toList();
} }
class GetMessagesCall {
Future<ApiCallResponse> call({
String? devUUID = '',
String? userUUID = '',
String? cliID = '',
String? atividade = '',
String? pageSize = '',
String? pageNumber = '',
String? tipoDestino = '',
}) async {
final baseUrl = PhpGroup.getBaseUrl();
return ApiManager.instance.makeApiCall(
callName: 'getMessages',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'pageSize': pageSize,
'pageNumber': pageNumber,
'tipoDestino': tipoDestino,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
}
class GetLiberationsCopyCall { class GetLiberationsCopyCall {
Future<ApiCallResponse> call({ Future<ApiCallResponse> call({
String? devUUID = '', String? devUUID = '',

View File

@ -7,6 +7,7 @@ import 'package:f_r_e_hub/actions/actions.dart';
import 'package:f_r_e_hub/app_state.dart'; import 'package:f_r_e_hub/app_state.dart';
import 'package:f_r_e_hub/backend/api_requests/api_calls.dart'; import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
import 'package:f_r_e_hub/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_widget.dart'; import 'package:f_r_e_hub/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_widget.dart';
import 'package:f_r_e_hub/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart';
import 'package:f_r_e_hub/components/templates_components/visit_request_template_component/visit_request_template_component_widget.dart'; import 'package:f_r_e_hub/components/templates_components/visit_request_template_component/visit_request_template_component_widget.dart';
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -20,6 +21,8 @@ class PushNotificationService {
final Subject<RemoteMessage> _onMessage = BehaviorSubject<RemoteMessage>(); final Subject<RemoteMessage> _onMessage = BehaviorSubject<RemoteMessage>();
final BehaviorSubject<BuildContext> _context = final BehaviorSubject<BuildContext> _context =
BehaviorSubject<BuildContext>(); BehaviorSubject<BuildContext>();
final BehaviorSubject<Map<String, dynamic>> _notificationDetails =
BehaviorSubject<Map<String, dynamic>>();
PushNotificationService() { PushNotificationService() {
_initializeLocalNotifications(_context); _initializeLocalNotifications(_context);
@ -93,6 +96,8 @@ class PushNotificationService {
} }
} }
void _initializeLocalNotifications( void _initializeLocalNotifications(
BehaviorSubject<BuildContext> context) async { BehaviorSubject<BuildContext> context) async {
while (context.valueOrNull == null) { while (context.valueOrNull == null) {
@ -119,7 +124,9 @@ class PushNotificationService {
Map<String, dynamic> message = Map<String, dynamic> message =
validJsonFromString(response.payload!); validJsonFromString(response.payload!);
debugPrint('Notification payload: $message'); debugPrint('Notification payload: $message');
_handleNotificationClick(message); var data = _notificationDetails; // Assuming getOnMessage() now returns the latest RemoteMessage
debugPrint('Extra: ${data.value}');
_handleNotificationClick(message, extra: data.value ?? {'extra': 'extra'});
} catch (e) { } catch (e) {
debugPrint('Error decoding notification payload: $e'); debugPrint('Error decoding notification payload: $e');
} }
@ -161,6 +168,7 @@ class PushNotificationService {
debugPrint('Got a message whilst in the foreground!'); debugPrint('Got a message whilst in the foreground!');
debugPrint('Message data: ${message.toMap()}'); debugPrint('Message data: ${message.toMap()}');
_onMessage.add(message); _onMessage.add(message);
_notificationDetails.add(message.toMap()['notification']);
_showNotification(message); _showNotification(message);
}); });
} }
@ -174,8 +182,8 @@ class PushNotificationService {
debugPrint('Notification clicked!'); debugPrint('Notification clicked!');
_onMessage.add(message); _onMessage.add(message);
NotificationHandler().handleMessage(message.data, context); debugPrint('Extra: ${message.notification?.body}');
}); NotificationHandler().handleMessage(message.data, context); });
} }
void configureTokenRefresh() { void configureTokenRefresh() {
@ -276,13 +284,14 @@ class PushNotificationService {
); );
} }
_handleNotificationClick(Map<String, dynamic> payload) { _handleNotificationClick(Map<String, dynamic> payload, {Map<String, dynamic> extra = const {}}) {
switch (payload.isNotEmpty) { switch (payload.isNotEmpty) {
case true: case true:
// Print the 'data' property // Print the 'data' property
debugPrint('Notification payload: $payload'); debugPrint('Notification payload: $payload');
debugPrint('Extra: $extra');
// Handle the message data as needed // Handle the message data as needed
NotificationHandler().handleMessage(payload, _context.value); NotificationHandler().handleMessage(payload, _context.value, extra: extra.isEmpty ? {} : extra);
// Access the 'data' property of 'RemoteMessage' // Access the 'data' property of 'RemoteMessage'
case false: case false:
debugPrint('Notification payload is empty'); debugPrint('Notification payload is empty');
@ -298,7 +307,7 @@ class PushNotificationService {
} }
class NotificationHandler { class NotificationHandler {
void handleMessage(Map<String, dynamic> message, BuildContext context) { void handleMessage(Map<String, dynamic> message, BuildContext context, {Map<String, dynamic> extra = const {}}) {
debugPrint('Notification Received!'); debugPrint('Notification Received!');
message.forEach((key, value) { message.forEach((key, value) {
debugPrint('$key: $value'); debugPrint('$key: $value');
@ -312,10 +321,10 @@ class NotificationHandler {
case '': case '':
break; break;
case 'access': case 'access':
_showAcessNotificationModal(message, context); _showAcessNotificationModal(message, context, extra);
break; break;
case 'mensagem': case 'mensagem':
debugPrint('mensagem'); _showMessageNotificationDialog(message, context, extra);
break; break;
case 'enroll_cond': case 'enroll_cond':
debugPrint('enroll_cond'); debugPrint('enroll_cond');
@ -326,7 +335,6 @@ class NotificationHandler {
} }
String _getIdBasedOnUserType(Map<String, dynamic> message) { String _getIdBasedOnUserType(Map<String, dynamic> message) {
// Verifica o tipo de usuário
if (message['USR_TIPO'].toString() == 'O') { if (message['USR_TIPO'].toString() == 'O') {
// Retorna USR_ID se não estiver vazio/nulo, caso contrário retorna '0' // Retorna USR_ID se não estiver vazio/nulo, caso contrário retorna '0'
return message['USR_ID'].toString().isEmpty return message['USR_ID'].toString().isEmpty
@ -341,7 +349,7 @@ class NotificationHandler {
} }
void _showAcessNotificationModal( void _showAcessNotificationModal(
Map<String, dynamic> message, BuildContext context) { Map<String, dynamic> message, BuildContext context, Map<String, dynamic> extra) {
debugPrint('Showing access notification dialog'); debugPrint('Showing access notification dialog');
debugPrint('USR_TIPO: ${message['USR_TIPO']}'); debugPrint('USR_TIPO: ${message['USR_TIPO']}');
debugPrint('USR_ID: ${message['USR_ID']}'); debugPrint('USR_ID: ${message['USR_ID']}');
@ -369,6 +377,26 @@ class NotificationHandler {
); );
} }
void _showMessageNotificationDialog(
Map<String, dynamic> message, BuildContext context, Map<String, dynamic> extra) {
debugPrint('Showing message notification dialog');
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
child: MessageNotificationModalTemplateComponentWidget(
id: message['local']['CLI_ID'].toString(),
from: message['remetente'].toString(),
to: message['destinatario'].toString() == 'O' ? 'Morador' : 'Visitante',
message: extra['body'].toString(),
),
);
},
);
}
void _showVisitRequestDialog( void _showVisitRequestDialog(
Map<String, dynamic> message, BuildContext context) { Map<String, dynamic> message, BuildContext context) {
debugPrint('Showing visit request notification dialog'); debugPrint('Showing visit request notification dialog');
@ -379,12 +407,12 @@ class NotificationHandler {
return Dialog( return Dialog(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
child: VisitRequestTemplateComponentWidget( child: VisitRequestTemplateComponentWidget(
vteName: message['VTE_NOME'] ?? 'Unknown', vteName: message['mensagem'] ?? 'Unknown',
vteReason: message['motivo'] ?? 'Unknown', vteReason: message['motivo'] ?? 'Unknown',
vteMsg: message['mensagem'] ?? 'Unknown', vteMsg: message['mensagem'] ?? 'Unknown',
vteDocument: message['documento'], vteDocument: message['documento'] ?? '',
vteUUID: message['idVisitante'].toString(), vteUUID: message['idVisitante'].toString() ?? '0',
vawRef: message['referencia'].toString(), vawRef: message['referencia'].toString() ?? '0',
vawStatus: 'S', vawStatus: 'S',
changeStatusAction: changeStatusAction, changeStatusAction: changeStatusAction,
), ),
@ -410,4 +438,6 @@ class PushNotificationManager {
void dispose() { void dispose() {
_onMessageReceivedController.close(); _onMessageReceivedController.close();
} }
} }

View File

@ -81,7 +81,7 @@ class _OptionSelectionModalWidgetState extends State<OptionSelectionModalWidget>
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, crossAxisCount: 3,
crossAxisSpacing: 10.0, crossAxisSpacing: 10.0,
mainAxisSpacing: 100.0, mainAxisSpacing: 10.0,
mainAxisExtent: 120.0, mainAxisExtent: 120.0,
childAspectRatio: 10, childAspectRatio: 10,
), ),

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import '/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart'; import '/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart';
import '/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart'; import '/components/organism_components/menu_list_view_component/menu_list_view_component_widget.dart';
@ -130,11 +131,13 @@ class MenuComponentModel extends FlutterFlowModel<MenuComponentWidget> {
'liberationHistory', 'liberationHistory',
'acessHistoryPage', 'acessHistoryPage',
'scheduleCompleteVisitPage', 'scheduleCompleteVisitPage',
// 'messageHistoryPage',
], ],
iconsListIcon: <IconData>[ iconsListIcon: <IconData>[
Icons.history_rounded, Icons.history_rounded,
Icons.history_rounded, Icons.history_rounded,
Icons.history_rounded, Icons.history_rounded,
// Icons.history_rounded,
], ],
nameListStr: <String>[ nameListStr: <String>[
FFLocalizations.of(context).getVariableText( FFLocalizations.of(context).getVariableText(
@ -149,6 +152,10 @@ class MenuComponentModel extends FlutterFlowModel<MenuComponentWidget> {
ptText: 'Histórico\nde Visita', ptText: 'Histórico\nde Visita',
enText: 'Visit\nHistory', enText: 'Visit\nHistory',
), ),
// FFLocalizations.of(context).getVariableText(
// ptText: 'Histórico\nde Mensagens',
// enText: 'Message\nHistory',
// ),
], ],
), ),
); );

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '/flutter_flow/flutter_flow_icon_button.dart'; import '/flutter_flow/flutter_flow_icon_button.dart';

View File

@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';

View File

@ -1,12 +1,46 @@
import 'package:f_r_e_hub/backend/api_requests/api_manager.dart';
import 'package:f_r_e_hub/flutter_flow/request_manager.dart';
import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_util.dart';
import 'message_well_component_widget.dart' show MessageWellComponentWidget; import 'message_well_component_widget.dart' show MessageWellComponentWidget;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class MessageWellComponentModel class MessageWellComponentModel
extends FlutterFlowModel<MessageWellComponentWidget> { extends FlutterFlowModel<MessageWellComponentWidget> {
final unfocusNode = FocusNode();
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
/// Query cache managers for this widget.
final _getLiberationsManager = StreamRequestManager<ApiCallResponse>();
Stream<ApiCallResponse> getLiberations({
String? uniqueQueryKey,
bool? overrideCache,
required Stream<ApiCallResponse> Function() requestFn,
}) =>
_getLiberationsManager.performRequest(
uniqueQueryKey: uniqueQueryKey,
overrideCache: overrideCache,
requestFn: requestFn,
);
void clearGetLiberationsCache() => _getLiberationsManager.clear();
void clearGetLiberationsCacheKey(String? uniqueKey) =>
_getLiberationsManager.clearRequest(uniqueKey);
@override @override
void initState(BuildContext context) {} void initState(BuildContext context) {}
@override @override
void dispose() {} void dispose() {
unfocusNode.dispose();
textFieldFocusNode?.dispose();
textController?.dispose();
/// Dispose query cache managers for this widget.
clearGetLiberationsCache();
}
} }

View File

@ -1,10 +1,12 @@
import '/flutter_flow/flutter_flow_theme.dart'; import 'package:f_r_e_hub/app_state.dart';
import '/flutter_flow/flutter_flow_util.dart'; import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
import '/flutter_flow/flutter_flow_widgets.dart'; import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart';
import 'package:f_r_e_hub/flutter_flow/internationalization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'message_well_component_model.dart'; import 'package:provider/provider.dart';
export 'message_well_component_model.dart';
class MessageWellComponentWidget extends StatefulWidget { class MessageWellComponentWidget extends StatefulWidget {
const MessageWellComponentWidget({super.key}); const MessageWellComponentWidget({super.key});
@ -14,105 +16,57 @@ class MessageWellComponentWidget extends StatefulWidget {
_MessageWellComponentWidgetState(); _MessageWellComponentWidgetState();
} }
class _MessageWellComponentWidgetState class _MessageWellComponentWidgetState extends State<MessageWellComponentWidget> {
extends State<MessageWellComponentWidget> { late ScrollController _listViewController;
late MessageWellComponentModel _model; bool _allowScrollInSingleChildScrollView = true;
VoidCallback get _scrollListener => MessageWellNotifier()._scrollListener;
final dropdownValueNotifier = ValueNotifier<String>('All'); // Using ValueNotifier for state management
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_model = createModel(context, () => MessageWellComponentModel()); _listViewController = ScrollController();
_listViewController.addListener(_scrollListener); // Adicione esta linha
// WidgetsBinding.instance?.addPostFrameCallback((_) {
// context.read<MessageWellNotifier>().fetchMessages();
// });
} }
@override @override
void dispose() { void dispose() {
_model.maybeDispose(); _listViewController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final state = context.watch<MessageWellNotifier>();
final messages = state.getMessages();
final theme = FlutterFlowTheme.of(context);
return Align( return Align(
alignment: const AlignmentDirectional(0.0, 0.0), alignment: Alignment.center,
child: Padding( child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 40.0, 0.0, 0.0), padding: const EdgeInsets.symmetric(vertical: 40.0),
child: Container( child: SizedBox(
width: double.infinity, height: MediaQuery.of(context).size.height * 0.8,
height: 167.0,
decoration: const BoxDecoration(),
child: Column( child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( _buildHandleMessageWell(context, theme),
FFLocalizations.of(context).getText( _buildMenuMessageWell(context, theme, dropdownValueNotifier),
'8fworxmb' /* Mural de Mensagens */,
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Nunito Sans',
letterSpacing: 0.0,
useGoogleFonts:
GoogleFonts.asMap().containsKey('Nunito Sans'),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 5.0, 0.0, 0.0),
child: FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: FFLocalizations.of(context).getText(
'yikill36' /* Todos */,
),
options: FFButtonOptions(
width: 260.0,
height: 20.0,
padding:
const EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0),
color: const Color(0xFF1AAB5F),
textStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily:
FlutterFlowTheme.of(context).labelMediumFamily,
color: FlutterFlowTheme.of(context).customColor4,
letterSpacing: 0.0,
fontWeight: FontWeight.normal,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).labelMediumFamily),
),
elevation: 3.0,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1.0,
),
borderRadius: BorderRadius.circular(8.0),
),
),
),
Expanded( Expanded(
child: Padding( child: NotificationListener<ScrollNotification>(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0), onNotification: _buildScrollMessageListManager,
child: Container( child: ListView.builder(
width: 464.0, controller: _listViewController,
height: 127.0, itemCount: messages.length,
decoration: const BoxDecoration( shrinkWrap: true,
shape: BoxShape.rectangle, physics: const AlwaysScrollableScrollPhysics(),
), itemBuilder: (context, index) {
child: ListView( var message = messages[index];
padding: EdgeInsets.zero, return _buildMessageItem(context, message, index);
scrollDirection: Axis.vertical, },
children: const [],
),
), ),
), ),
), ),
@ -122,4 +76,275 @@ class _MessageWellComponentWidgetState
), ),
); );
} }
bool _buildScrollMessageListManager(ScrollNotification notification) {
final notifier = context.read<MessageWellNotifier>();
if (notification is ScrollUpdateNotification) {
debugPrint('Scrolling ...');
if (_listViewController.offset <= 0 && notification.scrollDelta! < 0) {
debugPrint('Scrolling up ...');
setState(() {
_allowScrollInSingleChildScrollView = true;
});
} else {
debugPrint('Scrolling down ...');
if (_listViewController.position.extentAfter == 0) {
debugPrint('Reached end of list. Incrementing pageNumber...');
notifier.incrementPageNumber();
} }
setState(() {
_allowScrollInSingleChildScrollView = false;
// MessageWellNotifier().fetchMessages();
});
}
}
return true;
}
Widget _buildMenuMessageWell(BuildContext context, FlutterFlowTheme theme, ValueNotifier<String> dropdownValueNotifier) {
final locations = FFLocalizations.of(context);
late String all = locations.getVariableText(enText: 'All', ptText: 'All');
late String personal = locations.getVariableText(enText: 'Personal', ptText: 'Pessoal');
late String global = locations.getVariableText(enText: 'Global', ptText: 'Global');
return SizedBox(
key: UniqueKey(),
width: 200,
height: 40,
child: ValueListenableBuilder<String>(
valueListenable: dropdownValueNotifier,
builder: (context, value, child) {
return DropdownButtonFormField<String>(
value: value,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
border: OutlineInputBorder(
borderSide: BorderSide(
color: theme.primary, // Assuming FlutterFlowTheme.of(context).primary is the correct usage
width: 2, // Adjusted width to a reasonable value
),
borderRadius: BorderRadius.circular(10),
),
filled: true,
fillColor: theme.primary,
),
onChanged: (String? newValue) {
if (newValue != null) {
// logger.log('DropDown value: $newValue'); // Assuming logger is correctly initialized elsewhere
dropdownValueNotifier.value = newValue; // Update the ValueNotifier value
}
},
items: [
DropdownMenuItem<String>(value: all, child: Text(all)),
DropdownMenuItem<String>(value: personal, child: Text(personal)),
DropdownMenuItem<String>(value: global, child: Text(global)),
],
style: theme.labelMedium.override(
fontFamily: theme.labelMediumFamily,
color: theme.primaryText,
useGoogleFonts: GoogleFonts.asMap().containsKey(theme.labelMediumFamily),
),
);
},
),
);
}
Text _buildHandleMessageWell(BuildContext context, FlutterFlowTheme theme) {
return Text(
FFLocalizations.of(context).getText('8fworxmb'), // Mural de Mensagens
style: theme.bodyMedium.override(
fontFamily: 'Nunito Sans',
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito Sans'),
),
);
}
Widget _buildMessageItem(BuildContext context, dynamic message, int index) {
final theme = Theme.of(context);
String formatMessageOrigin(String messageOrigin) {
final words = messageOrigin.split(' ');
final formattedWords = words.map((word) {
final firstLetter = word.substring(0, 1).toUpperCase();
final remainingLetters = word.substring(1).toLowerCase();
return '$firstLetter$remainingLetters';
});
return formattedWords.join(' ');
}
return GestureDetector(
onTap: () => print('Message tapped ...\nmessage[$index]: $message'),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 5, 20, 5),
child: Container(
width: MediaQuery.of(context).size.width * 0.9,
height: 127.0,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Container(
width: 64.0,
height: 64.0,
decoration: const BoxDecoration(shape: BoxShape.circle),
),
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8.0),
Center(
child: Text(
'~ ${formatMessageOrigin(message['MSG_ORIGEM_DESC'].toString())}',
style: theme.textTheme.headlineMedium!.copyWith(
fontFamily: 'Nunito Sans',
color: FlutterFlowTheme.of(context).primary,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 8.0),
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Text(
formatMessageOrigin(message['MSG_TEXTO'].toString()),
style: theme.textTheme.bodyMedium!.copyWith(
fontFamily: 'Nunito Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
),
softWrap: true,
maxLines: 10,
),
),
),
],
),
)
],
),
),
),
);
}
}
class MessageWellState {
final List<dynamic> messages;
int pageNumber;
final bool allowScrollInSingleChildScrollView;
final ScrollController listViewController;
MessageWellState({
required this.messages,
this.pageNumber = 1,
required this.allowScrollInSingleChildScrollView,
required this.listViewController,
});
MessageWellState copyWith({
List<dynamic>? messages,
int? pageNumber,
bool? allowScrollInSingleChildScrollView,
ScrollController? listViewController,
}) {
return MessageWellState(
messages: messages ?? this.messages,
pageNumber: pageNumber ?? this.pageNumber,
allowScrollInSingleChildScrollView: allowScrollInSingleChildScrollView ?? this.allowScrollInSingleChildScrollView,
listViewController: listViewController ?? this.listViewController,
);
}
}
class MessageWellNotifier extends StateNotifier<MessageWellState> {
var totalPageNumber = 1;
MessageWellNotifier()
: super(MessageWellState(messages: [], allowScrollInSingleChildScrollView: true, listViewController: ScrollController())) {
state.listViewController.addListener(_scrollListener);
fetchMessages();
}
void fetchMessages() async {
if (state.pageNumber <= totalPageNumber) {
var apiCall = GetMessagesCall();
var response = await apiCall.call(
devUUID: FFAppState().devUUID.toString(),
userUUID: FFAppState().userUUID.toString(),
cliID: FFAppState().cliUUID.toString(),
atividade: 'getMensagens',
pageSize: '10',
pageNumber: state.pageNumber.toString(),
tipoDestino: 'A',
);
if (response.statusCode == 200) {
var messagesData = response.jsonBody['mensagens'];
debugPrint('inputs: ${FFAppState().devUUID}, ${FFAppState().userUUID}, ${FFAppState().cliUUID}');
debugPrint('response: ${response.jsonBody}');
debugPrint('response[mensagens]: $messagesData');
debugPrint('response[mensagens][0][MSG_TEXTO]: ${messagesData[0]['MSG_TEXTO']}');
var newMessages = [...state.messages, ...messagesData];
var rExp = RegExp(r'\d+').allMatches(newMessages.toString()).map((e) => e.group(0)).toList();
debugPrint('rExp: $rExp');
debugPrint('newMessages: $newMessages');
state = state.copyWith(messages: newMessages);
totalPageNumber = int.parse(response.jsonBody['total_pages']);
debugPrint('totalPageNumber: $totalPageNumber');
} else {
debugPrint('Error fetching messages: ${response.statusCode}');
}
} else {
debugPrint('No more messages to fetch ...');
}
}
List<dynamic> getMessages() {
return state.messages;
}
void _scrollListener() {
if (!state.allowScrollInSingleChildScrollView) {
if (state.pageNumber <= totalPageNumber) {
state = state.copyWith(pageNumber: state.pageNumber + 1);
debugPrint('state.pageNumber: ${state.pageNumber}');
fetchMessages();
}
}
}
@override
void dispose() {
state.listViewController.removeListener(_scrollListener);
super.dispose();
}
void incrementPageNumber() {
if (state.pageNumber <= totalPageNumber) {
state = state.copyWith(pageNumber: state.pageNumber + 1);
debugPrint('state.pageNumber: ${state.pageNumber}');
}
}
}
mixin Logger {
static void log(String message) {
debugPrint('Logger: $message');
}
}
final messageWellProvider = StateNotifierProvider<MessageWellNotifier, MessageWellState>((ref) {
return MessageWellNotifier();
});

View File

@ -0,0 +1,77 @@
import '/backend/api_requests/api_calls.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'message_notification_widget.dart'
show MessageNotificationModalTemplateComponentWidget;
import 'package:flutter/material.dart';
class MessageNotificationModalTemplateComponentModel
extends FlutterFlowModel<MessageNotificationModalTemplateComponentWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode1;
TextEditingController? textController1;
String? Function(BuildContext, String?)? textController1Validator;
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode2;
TextEditingController? textController2;
String? Function(BuildContext, String?)? textController2Validator;
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode3;
TextEditingController? textController3;
String? Function(BuildContext, String?)? textController3Validator;
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode4;
TextEditingController? textController4;
String? Function(BuildContext, String?)? textController4Validator;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode1?.dispose();
textController1?.dispose();
textFieldFocusNode2?.dispose();
textController2?.dispose();
textFieldFocusNode3?.dispose();
textController3?.dispose();
textFieldFocusNode4?.dispose();
textController4?.dispose();
}
/// Action blocks.
Future<bool> visitRequestComponentAction(
BuildContext context, {
required String? actionValue,
required String? refUUID,
required String? responseValue,
required String? vteUUID,
}) async {
ApiCallResponse? visitRequest;
visitRequest = await PhpGroup.respondeSolicitacaoCall.call(
userUUID: FFAppState().userUUID,
devUUID: FFAppState().devUUID,
cliUUID: FFAppState().cliUUID,
atividade: 'respondeSolicitacao',
referencia: refUUID,
tarefa: actionValue,
resposta: responseValue,
idVisitante: vteUUID,
);
if (PhpGroup.respondeSolicitacaoCall.error(
(visitRequest.jsonBody ?? ''),
) ==
false) {
Navigator.pop(context);
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,288 @@
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'message_notification_model.dart';
class MessageNotificationModalTemplateComponentWidget extends StatefulWidget {
const MessageNotificationModalTemplateComponentWidget({
super.key,
required this.message,
required this.from,
required this.to,
required this.id,
});
final String? message;
final String? from;
final String? to;
final String? id;
@override
State<MessageNotificationModalTemplateComponentWidget> createState() =>
_MessageNotificationModalTemplateComponentWidgetState();
}
class _MessageNotificationModalTemplateComponentWidgetState
extends State<MessageNotificationModalTemplateComponentWidget> {
late MessageNotificationModalTemplateComponentModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(
context, () => MessageNotificationModalTemplateComponentModel());
_model.textController1 ??= TextEditingController(text: widget.message);
_model.textFieldFocusNode1 ??= FocusNode();
_model.textController2 ??= TextEditingController(text: widget.from);
_model.textFieldFocusNode2 ??= FocusNode();
_model.textController3 ??= TextEditingController(text: widget.to);
_model.textFieldFocusNode3 ??= FocusNode();
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
context.watch<FFAppState>();
return Align(
alignment: const AlignmentDirectional(0.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(10.0, 0.0, 10.0, 0.0),
child: Container(
width: MediaQuery.sizeOf(context).width * 0.9,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(25.0),
bottomRight: Radius.circular(25.0),
topLeft: Radius.circular(25.0),
topRight: Radius.circular(25.0),
),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
24.0, 0.0, 24.0, 0.0),
child: TextFormField(
controller: _model.textController1,
focusNode: _model.textFieldFocusNode1,
autofocus: false,
textInputAction: TextInputAction.next,
readOnly: true,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'Mensagem',
enText: 'Message',
),
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: InputBorder.none,
focusedBorder: InputBorder.none,
errorBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
suffixIcon: Icon(
Icons.message,
color: FlutterFlowTheme.of(context).accent1,
),
),
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),
),
textAlign: TextAlign.start,
maxLines: null,
keyboardType: TextInputType.name,
validator:
_model.textController1Validator.asValidator(context),
),
),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: TextFormField(
controller: _model.textController2,
focusNode: _model.textFieldFocusNode2,
autofocus: false,
textInputAction: TextInputAction.next,
readOnly: true,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'De',
enText: 'From',
),
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: InputBorder.none,
focusedBorder: InputBorder.none,
errorBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
suffixIcon: Icon(
Icons.person,
color: FlutterFlowTheme.of(context).accent1,
),
),
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),
),
textAlign: TextAlign.start,
maxLines: null,
keyboardType: TextInputType.name,
validator: _model.textController2Validator
.asValidator(context),
),
),
]
.addToStart(const SizedBox(width: 24.0))
.addToEnd(const SizedBox(width: 24.0)),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
24.0, 0.0, 24.0, 0.0),
child: TextFormField(
controller: _model.textController3,
focusNode: _model.textFieldFocusNode3,
autofocus: false,
textInputAction: TextInputAction.next,
readOnly: true,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'Para',
enText: 'To',
),
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: InputBorder.none,
focusedBorder: InputBorder.none,
errorBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
suffixIcon: Icon(
Icons.person,
color: FlutterFlowTheme.of(context).accent1,
),
),
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),
),
textAlign: TextAlign.start,
maxLines: null,
keyboardType: TextInputType.name,
validator:
_model.textController3Validator.asValidator(context),
),
),
]
.divide(const SizedBox(height: 10.0))
.addToStart(const SizedBox(height: 20.0))
.addToEnd(const SizedBox(height: 20.0)),
),
),
),
),
);
}
}

View File

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart'; import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart';
import 'package:f_r_e_hub/pages/message_history_page/message_history_page_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -77,6 +78,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter(
path: '/visitHistoryPage', path: '/visitHistoryPage',
builder: (context, params) => const VisitHistoryPageWidget(), builder: (context, params) => const VisitHistoryPageWidget(),
), ),
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()),
FFRoute( FFRoute(
name: 'registerVisitorPage', name: 'registerVisitorPage',
path: '/registerVisitorPage', path: '/registerVisitorPage',

View File

@ -4,6 +4,8 @@
// import 'package:firebase_messaging/firebase_messaging.dart'; // import 'package:firebase_messaging/firebase_messaging.dart';
// import 'package:flutter_local_notifications/flutter_local_notifications.dart'; // import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:firebase_analytics/firebase_analytics.dart'; // import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View File

@ -1,3 +1,5 @@
import 'package:f_r_e_hub/components/organism_components/message_well_component/message_well_component_model.dart';
import '/components/organism_components/local_profile_component/local_profile_component_widget.dart'; import '/components/organism_components/local_profile_component/local_profile_component_widget.dart';
import '/components/organism_components/menu_component/menu_component_widget.dart'; import '/components/organism_components/menu_component/menu_component_widget.dart';
import '/components/organism_components/message_well_component/message_well_component_widget.dart'; import '/components/organism_components/message_well_component/message_well_component_widget.dart';

View File

@ -1098,6 +1098,7 @@ class _HomePageWidgetState extends State<HomePageWidget> {
Wrap( Wrap(
spacing: 0.0, spacing: 0.0,
runSpacing: 0.0, runSpacing: 0.0,
alignment: WrapAlignment.start, alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start, crossAxisAlignment: WrapCrossAlignment.start,
direction: Axis.horizontal, direction: Axis.horizontal,
@ -1112,12 +1113,20 @@ class _HomePageWidgetState extends State<HomePageWidget> {
), ),
Align( Align(
alignment: const AlignmentDirectional(0.0, 0.0), alignment: const AlignmentDirectional(0.0, 0.0),
child: Provider<MessageWellNotifier>(
create: (_) => MessageWellNotifier(),
child: wrapWithModel( child: wrapWithModel(
model: _model.messageWellComponentModel, model: _model.messageWellComponentModel,
updateCallback: () => setState(() {}), updateCallback: () => setState(() {}),
child: const MessageWellComponentWidget(), child: const MessageWellComponentWidget(),
), ),
), ),
),
//footer
const SizedBox(
height: 100,
width: double.infinity,
)
], ],
), ),
], ],

View File

@ -0,0 +1,50 @@
import '/backend/api_requests/api_calls.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/request_manager.dart';
import 'message_history_page_widget.dart' show MessageHistoryPageWidget;
import 'package:flutter/material.dart';
class MessageHistoryPageModel extends FlutterFlowModel<MessageHistoryPageWidget> {
/// State fields for stateful widgets in this page.
///
//copyWith
final unfocusNode = FocusNode();
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
/// Query cache managers for this widget.
final _getLiberationsManager = StreamRequestManager<ApiCallResponse>();
Stream<ApiCallResponse> getLiberations({
String? uniqueQueryKey,
bool? overrideCache,
required Stream<ApiCallResponse> Function() requestFn,
}) =>
_getLiberationsManager.performRequest(
uniqueQueryKey: uniqueQueryKey,
overrideCache: overrideCache,
requestFn: requestFn,
);
void clearGetLiberationsCache() => _getLiberationsManager.clear();
void clearGetLiberationsCacheKey(String? uniqueKey) =>
_getLiberationsManager.clearRequest(uniqueKey);
@override
void initState(BuildContext context) {}
@override
void dispose() {
unfocusNode.dispose();
textFieldFocusNode?.dispose();
textController?.dispose();
/// Dispose query cache managers for this widget.
clearGetLiberationsCache();
}
}

View File

@ -0,0 +1,288 @@
// import 'dart:js_interop';
import 'package:f_r_e_hub/actions/actions.dart';
import 'package:f_r_e_hub/backend/push_notification/pushNotificationService.dart';
import 'package:f_r_e_hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:f_r_e_hub/components/templates_components/visit_request_template_component/visit_request_template_component_widget.dart';
import '/backend/api_requests/api_calls.dart';
import '/flutter_flow/flutter_flow_icon_button.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/custom_functions.dart' as functions;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'message_history_page_model.dart';
class MessageHistoryPageWidget extends StatefulWidget {
const MessageHistoryPageWidget({super.key});
@override
State<MessageHistoryPageWidget> createState() =>
_MessageHistoryPageWidgetState();
}
class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget> {
late MessageHistoryPageModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
_model = createModel(context, () => MessageHistoryPageModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
void onUpdate(BuildContext context) {
_model.clearGetLiberationsCache();
setState(() {});
}
@override
Widget build(BuildContext context) {
context.watch<FFAppState>();
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: appBarLiberationHistoryPage(context),
body: bodyLiberationHistoryPage(context, _model),
),
);
}
}
PreferredSizeWidget appBarLiberationHistoryPage(BuildContext context) {
return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false,
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: FlutterFlowTheme.of(context).primaryText,
size: 30.0,
),
onPressed: () async {
context.pop();
},
),
title: Text(
FFLocalizations.of(context).getText(
'784f83pc' /* Histórico de Liberação */,
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: 'Nunito',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 17.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'),
),
),
actions: const [],
centerTitle: true,
);
}
Widget bodyLiberationHistoryPage(
BuildContext context, MessageHistoryPageModel _model) {
return SafeArea(
top: true,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(child: liberationDynamicListView(context, _model)),
].addToStart(const SizedBox(height: 0)),
),
);
}
Widget liberationDynamicListView(
BuildContext context,
MessageHistoryPageModel _model,
) {
return Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(),
child: StreamBuilder<ApiCallResponse>(
stream: _model.getLiberations(
requestFn: () => PhpGroup.getLiberationsCall.call(
devUUID: FFAppState().devUUID,
userUUID: FFAppState().userUUID,
cliID: FFAppState().cliUUID,
atividade: 'getSolicitacoes',
),
),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: SizedBox(
width: 50.0,
height: 50.0,
child: SpinKitCircle(
color: FlutterFlowTheme.of(context).primary,
size: 50.0,
),
),
);
}
final columnGetLiberationsResponse = snapshot.data!;
final liberationHistory = PhpGroup.getLiberationsCall
.rqList(
columnGetLiberationsResponse.jsonBody,
)
?.toList() ??
[];
final filteredLiberationHistory = _model.textController.text.isNotEmpty
? liberationHistory
.where((item) => functions
.jsonToStr(getJsonField(
item,
r'''$.VTE_NOME''',
))
.toLowerCase()
.contains(
_model.textController.text.toLowerCase(),
))
.toList()
: liberationHistory;
return ListView.builder(
itemCount: filteredLiberationHistory.length,
addAutomaticKeepAlives: false,
addRepaintBoundaries: true,
cacheExtent: 1000.0,
itemBuilder: (BuildContext context, int index) {
final liberationHistoryItem = filteredLiberationHistory[index];
return Padding(
padding: EdgeInsets.only(
top: index == 0
? MediaQuery.of(context).size.height * 0.075
: 8.0,
left: 8.0,
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: liberationHistoryItemCard(
context,
liberationHistoryItem,
),
),
);
},
);
},
),
);
}
Widget liberationHistoryItemCard(
BuildContext context, dynamic liberationHistoryItem) {
return CardItemTemplateComponentWidget(
imageHashMap: Map<String, String>.from({
'key': liberationHistoryItem['VTE_ID'],
'value': 'E',
}),
labelsHashMap: Map<String, String>.from({
'Nome:': liberationHistoryItem['VTE_NOME'],
'Data:': liberationHistoryItem['NOT_DTENVIO'],
'Motivo:': liberationHistoryItem['NOT_MOTIVO'],
}),
statusHashMap: liberationHistoryItem['NOT_STATUS'] == 'L'
? Map<String, Color>.from({
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).success,
})
: liberationHistoryItem['NOT_STATUS'] == 'B'
? Map<String, Color>.from({
FFLocalizations.of(context).getVariableText(
ptText: 'Bloqueado',
enText: 'Blocked',
): FlutterFlowTheme.of(context).error,
})
: Map<String, Color>.from({
FFLocalizations.of(context).getVariableText(
ptText: 'Pendente',
enText: 'Pending',
): FlutterFlowTheme.of(context).warning,
}),
onTapCardItemAction: () async {
showModalBottomSheet(
isScrollControlled: true,
isDismissible: true,
backgroundColor: Colors.transparent,
useSafeArea: true,
context: context,
builder: (context) {
return VisitRequestTemplateComponentWidget(
vteName: liberationHistoryItem['VTE_NOME'],
vteReason: liberationHistoryItem['NOT_MOTIVO'],
vawDate: liberationHistoryItem['NOT_STATUS'] == 'S'
? liberationHistoryItem['NOT_DTENVIO']
: liberationHistoryItem['NOT_DTRESPOSTA'],
vawStatus: liberationHistoryItem['NOT_STATUS'],
vteMsg: liberationHistoryItem['NOT_MSGENVIO'],
vteUUID: liberationHistoryItem['VTE_ID'],
cliUUID: FFAppState().cliUUID,
msgUUID: liberationHistoryItem['NOT_ID'],
vawDestino: liberationHistoryItem['NOT_DESTINO'],
vawUUID: liberationHistoryItem['NOT_ID'],
vawName: liberationHistoryItem['NOT_NOME'],
vawRef: liberationHistoryItem['NOT_ID'],
changeStatusAction: changeStatusAction,
// vteDocument: liberationHistoryItem['VTE_DOCUMENTO'],
);
},
).then((_) {
PushNotificationManager _pushNotificationService =
PushNotificationManager();
_pushNotificationService.onMessageReceived.listen((received) {
if (received.data['click_action'] == 'cancel_request') {
debugPrint('Aprovado');
_pushNotificationService.dispose();
snackbar(context, opt: true);
context.pushReplacementNamed(
'liberationHistory',
extra: <String, dynamic>{
kTransitionInfoKey: const TransitionInfo(
hasTransition: true,
transitionType: PageTransitionType.scale,
alignment: Alignment.bottomCenter,
),
},
);
}
});
});
},
);
}

View File

@ -41,6 +41,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "3.0.0"
bloc:
dependency: transitive
description:
name: bloc
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
url: "https://pub.dev"
source: hosted
version: "8.1.4"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -366,6 +374,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.0" version: "4.5.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
url: "https://pub.dev"
source: hosted
version: "8.1.6"
flutter_cache_manager: flutter_cache_manager:
dependency: "direct main" dependency: "direct main"
description: description:
@ -374,6 +390,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.3.2" version: "3.3.2"
flutter_expandable_fab:
dependency: "direct main"
description:
name: flutter_expandable_fab
sha256: "85eee55657e747814007d9d09bfc713dc961ede4240e82fae6c1ade8eb5bb4d3"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
flutter_inappwebview: flutter_inappwebview:
dependency: "direct main" dependency: "direct main"
description: description:
@ -483,6 +507,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.20" version: "2.0.20"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
url: "https://pub.dev"
source: hosted
version: "2.5.1"
flutter_secure_storage: flutter_secure_storage:
dependency: "direct main" dependency: "direct main"
description: description:
@ -965,6 +997,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "0.2.0"
riverpod:
dependency: transitive
description:
name: riverpod
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
url: "https://pub.dev"
source: hosted
version: "2.5.1"
rxdart: rxdart:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1074,6 +1114,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.1" version: "1.11.1"
state_notifier:
dependency: transitive
description:
name: state_notifier
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
url: "https://pub.dev"
source: hosted
version: "1.0.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:

View File

@ -41,6 +41,7 @@ dependencies:
easy_debounce: 2.0.3 easy_debounce: 2.0.3
equatable: 2.0.5 equatable: 2.0.5
file_picker: 8.0.5 file_picker: 8.0.5
flutter_expandable_fab: ^2.1.0
firebase_analytics: 11.0.1 firebase_analytics: 11.0.1
flutter_animate: 4.5.0 flutter_animate: 4.5.0
flutter_cache_manager: 3.3.2 flutter_cache_manager: 3.3.2
@ -97,6 +98,8 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0 cupertino_icons: ^1.0.0
flutter_bloc: ^8.1.6
flutter_riverpod: ^2.5.1
dependency_overrides: dependency_overrides:
http: 1.2.1 http: 1.2.1