messages
This commit is contained in:
parent
b23ab9c2ac
commit
67dd1b9f92
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
gradle 7.5
|
|
@ -39,6 +39,7 @@ class PhpGroup {
|
|||
static GetLiberationsCall getLiberationsCall = GetLiberationsCall();
|
||||
static GetLiberationsCopyCall getLiberationsCopyCall =
|
||||
GetLiberationsCopyCall();
|
||||
static GetMessagesCall getMessagesCall = GetMessagesCall();
|
||||
}
|
||||
|
||||
class UpdToken {
|
||||
|
@ -2045,6 +2046,45 @@ class GetLiberationsCall {
|
|||
.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 {
|
||||
Future<ApiCallResponse> call({
|
||||
String? devUUID = '',
|
||||
|
|
|
@ -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/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/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:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -20,6 +21,8 @@ class PushNotificationService {
|
|||
final Subject<RemoteMessage> _onMessage = BehaviorSubject<RemoteMessage>();
|
||||
final BehaviorSubject<BuildContext> _context =
|
||||
BehaviorSubject<BuildContext>();
|
||||
final BehaviorSubject<Map<String, dynamic>> _notificationDetails =
|
||||
BehaviorSubject<Map<String, dynamic>>();
|
||||
|
||||
PushNotificationService() {
|
||||
_initializeLocalNotifications(_context);
|
||||
|
@ -93,6 +96,8 @@ class PushNotificationService {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _initializeLocalNotifications(
|
||||
BehaviorSubject<BuildContext> context) async {
|
||||
while (context.valueOrNull == null) {
|
||||
|
@ -119,7 +124,9 @@ class PushNotificationService {
|
|||
Map<String, dynamic> message =
|
||||
validJsonFromString(response.payload!);
|
||||
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) {
|
||||
debugPrint('Error decoding notification payload: $e');
|
||||
}
|
||||
|
@ -161,6 +168,7 @@ class PushNotificationService {
|
|||
debugPrint('Got a message whilst in the foreground!');
|
||||
debugPrint('Message data: ${message.toMap()}');
|
||||
_onMessage.add(message);
|
||||
_notificationDetails.add(message.toMap()['notification']);
|
||||
_showNotification(message);
|
||||
});
|
||||
}
|
||||
|
@ -174,8 +182,8 @@ class PushNotificationService {
|
|||
debugPrint('Notification clicked!');
|
||||
|
||||
_onMessage.add(message);
|
||||
NotificationHandler().handleMessage(message.data, context);
|
||||
});
|
||||
debugPrint('Extra: ${message.notification?.body}');
|
||||
NotificationHandler().handleMessage(message.data, context); });
|
||||
}
|
||||
|
||||
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) {
|
||||
case true:
|
||||
// Print the 'data' property
|
||||
debugPrint('Notification payload: $payload');
|
||||
debugPrint('Extra: $extra');
|
||||
// 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'
|
||||
case false:
|
||||
debugPrint('Notification payload is empty');
|
||||
|
@ -298,7 +307,7 @@ class PushNotificationService {
|
|||
}
|
||||
|
||||
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!');
|
||||
message.forEach((key, value) {
|
||||
debugPrint('$key: $value');
|
||||
|
@ -312,10 +321,10 @@ class NotificationHandler {
|
|||
case '':
|
||||
break;
|
||||
case 'access':
|
||||
_showAcessNotificationModal(message, context);
|
||||
_showAcessNotificationModal(message, context, extra);
|
||||
break;
|
||||
case 'mensagem':
|
||||
debugPrint('mensagem');
|
||||
_showMessageNotificationDialog(message, context, extra);
|
||||
break;
|
||||
case 'enroll_cond':
|
||||
debugPrint('enroll_cond');
|
||||
|
@ -326,7 +335,6 @@ class NotificationHandler {
|
|||
}
|
||||
|
||||
String _getIdBasedOnUserType(Map<String, dynamic> message) {
|
||||
// Verifica o tipo de usuário
|
||||
if (message['USR_TIPO'].toString() == 'O') {
|
||||
// Retorna USR_ID se não estiver vazio/nulo, caso contrário retorna '0'
|
||||
return message['USR_ID'].toString().isEmpty
|
||||
|
@ -341,7 +349,7 @@ class NotificationHandler {
|
|||
}
|
||||
|
||||
void _showAcessNotificationModal(
|
||||
Map<String, dynamic> message, BuildContext context) {
|
||||
Map<String, dynamic> message, BuildContext context, Map<String, dynamic> extra) {
|
||||
debugPrint('Showing access notification dialog');
|
||||
debugPrint('USR_TIPO: ${message['USR_TIPO']}');
|
||||
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(
|
||||
Map<String, dynamic> message, BuildContext context) {
|
||||
debugPrint('Showing visit request notification dialog');
|
||||
|
@ -379,12 +407,12 @@ class NotificationHandler {
|
|||
return Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
child: VisitRequestTemplateComponentWidget(
|
||||
vteName: message['VTE_NOME'] ?? 'Unknown',
|
||||
vteName: message['mensagem'] ?? 'Unknown',
|
||||
vteReason: message['motivo'] ?? 'Unknown',
|
||||
vteMsg: message['mensagem'] ?? 'Unknown',
|
||||
vteDocument: message['documento'],
|
||||
vteUUID: message['idVisitante'].toString(),
|
||||
vawRef: message['referencia'].toString(),
|
||||
vteDocument: message['documento'] ?? '',
|
||||
vteUUID: message['idVisitante'].toString() ?? '0',
|
||||
vawRef: message['referencia'].toString() ?? '0',
|
||||
vawStatus: 'S',
|
||||
changeStatusAction: changeStatusAction,
|
||||
),
|
||||
|
@ -410,4 +438,6 @@ class PushNotificationManager {
|
|||
void dispose() {
|
||||
_onMessageReceivedController.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class _OptionSelectionModalWidgetState extends State<OptionSelectionModalWidget>
|
|||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 100.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 120.0,
|
||||
childAspectRatio: 10,
|
||||
),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
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/organism_components/menu_list_view_component/menu_list_view_component_widget.dart';
|
||||
|
@ -130,11 +131,13 @@ class MenuComponentModel extends FlutterFlowModel<MenuComponentWidget> {
|
|||
'liberationHistory',
|
||||
'acessHistoryPage',
|
||||
'scheduleCompleteVisitPage',
|
||||
// 'messageHistoryPage',
|
||||
],
|
||||
iconsListIcon: <IconData>[
|
||||
Icons.history_rounded,
|
||||
Icons.history_rounded,
|
||||
Icons.history_rounded,
|
||||
// Icons.history_rounded,
|
||||
],
|
||||
nameListStr: <String>[
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
|
@ -149,6 +152,10 @@ class MenuComponentModel extends FlutterFlowModel<MenuComponentWidget> {
|
|||
ptText: 'Histórico\nde Visita',
|
||||
enText: 'Visit\nHistory',
|
||||
),
|
||||
// FFLocalizations.of(context).getVariableText(
|
||||
// ptText: 'Histórico\nde Mensagens',
|
||||
// enText: 'Message\nHistory',
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '/flutter_flow/flutter_flow_icon_button.dart';
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
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:google_fonts/google_fonts.dart';
|
||||
|
||||
|
|
|
@ -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 'message_well_component_widget.dart' show MessageWellComponentWidget;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MessageWellComponentModel
|
||||
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
|
||||
void initState(BuildContext context) {}
|
||||
|
||||
@override
|
||||
void dispose() {}
|
||||
void dispose() {
|
||||
unfocusNode.dispose();
|
||||
textFieldFocusNode?.dispose();
|
||||
textController?.dispose();
|
||||
|
||||
/// Dispose query cache managers for this widget.
|
||||
|
||||
clearGetLiberationsCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import '/flutter_flow/flutter_flow_theme.dart';
|
||||
import '/flutter_flow/flutter_flow_util.dart';
|
||||
import '/flutter_flow/flutter_flow_widgets.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/flutter_flow/flutter_flow_theme.dart';
|
||||
import 'package:f_r_e_hub/flutter_flow/internationalization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'message_well_component_model.dart';
|
||||
export 'message_well_component_model.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
class MessageWellComponentWidget extends StatefulWidget {
|
||||
const MessageWellComponentWidget({super.key});
|
||||
|
@ -14,105 +16,57 @@ class MessageWellComponentWidget extends StatefulWidget {
|
|||
_MessageWellComponentWidgetState();
|
||||
}
|
||||
|
||||
class _MessageWellComponentWidgetState
|
||||
extends State<MessageWellComponentWidget> {
|
||||
late MessageWellComponentModel _model;
|
||||
class _MessageWellComponentWidgetState extends State<MessageWellComponentWidget> {
|
||||
late ScrollController _listViewController;
|
||||
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
|
||||
void initState() {
|
||||
super.initState();
|
||||
_model = createModel(context, () => MessageWellComponentModel());
|
||||
_listViewController = ScrollController();
|
||||
_listViewController.addListener(_scrollListener); // Adicione esta linha
|
||||
// WidgetsBinding.instance?.addPostFrameCallback((_) {
|
||||
// context.read<MessageWellNotifier>().fetchMessages();
|
||||
// });
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_model.maybeDispose();
|
||||
|
||||
_listViewController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = context.watch<MessageWellNotifier>();
|
||||
final messages = state.getMessages();
|
||||
final theme = FlutterFlowTheme.of(context);
|
||||
return Align(
|
||||
alignment: const AlignmentDirectional(0.0, 0.0),
|
||||
alignment: Alignment.center,
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 40.0, 0.0, 0.0),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 167.0,
|
||||
decoration: const BoxDecoration(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 40.0),
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
FFLocalizations.of(context).getText(
|
||||
'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),
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildHandleMessageWell(context, theme),
|
||||
_buildMenuMessageWell(context, theme, dropdownValueNotifier),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0),
|
||||
child: Container(
|
||||
width: 464.0,
|
||||
height: 127.0,
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.rectangle,
|
||||
),
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
scrollDirection: Axis.vertical,
|
||||
children: const [],
|
||||
),
|
||||
child: NotificationListener<ScrollNotification>(
|
||||
onNotification: _buildScrollMessageListManager,
|
||||
child: ListView.builder(
|
||||
controller: _listViewController,
|
||||
itemCount: messages.length,
|
||||
shrinkWrap: true,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
var message = messages[index];
|
||||
return _buildMessageItem(context, message, index);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
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/message_history_page/message_history_page_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
@ -77,6 +78,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter(
|
|||
path: '/visitHistoryPage',
|
||||
builder: (context, params) => const VisitHistoryPageWidget(),
|
||||
),
|
||||
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()),
|
||||
FFRoute(
|
||||
name: 'registerVisitorPage',
|
||||
path: '/registerVisitorPage',
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
// import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
// import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
|
@ -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/menu_component/menu_component_widget.dart';
|
||||
import '/components/organism_components/message_well_component/message_well_component_widget.dart';
|
||||
|
|
|
@ -1098,6 +1098,7 @@ class _HomePageWidgetState extends State<HomePageWidget> {
|
|||
Wrap(
|
||||
spacing: 0.0,
|
||||
runSpacing: 0.0,
|
||||
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
direction: Axis.horizontal,
|
||||
|
@ -1112,12 +1113,20 @@ class _HomePageWidgetState extends State<HomePageWidget> {
|
|||
),
|
||||
Align(
|
||||
alignment: const AlignmentDirectional(0.0, 0.0),
|
||||
child: wrapWithModel(
|
||||
model: _model.messageWellComponentModel,
|
||||
updateCallback: () => setState(() {}),
|
||||
child: const MessageWellComponentWidget(),
|
||||
child: Provider<MessageWellNotifier>(
|
||||
create: (_) => MessageWellNotifier(),
|
||||
child: wrapWithModel(
|
||||
model: _model.messageWellComponentModel,
|
||||
updateCallback: () => setState(() {}),
|
||||
child: const MessageWellComponentWidget(),
|
||||
),
|
||||
),
|
||||
),
|
||||
//footer
|
||||
const SizedBox(
|
||||
height: 100,
|
||||
width: double.infinity,
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
48
pubspec.lock
48
pubspec.lock
|
@ -41,6 +41,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bloc
|
||||
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.1.4"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -366,6 +374,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -374,6 +390,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -483,6 +507,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -965,6 +997,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: riverpod
|
||||
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.1"
|
||||
rxdart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1074,6 +1114,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -41,6 +41,7 @@ dependencies:
|
|||
easy_debounce: 2.0.3
|
||||
equatable: 2.0.5
|
||||
file_picker: 8.0.5
|
||||
flutter_expandable_fab: ^2.1.0
|
||||
firebase_analytics: 11.0.1
|
||||
flutter_animate: 4.5.0
|
||||
flutter_cache_manager: 3.3.2
|
||||
|
@ -97,6 +98,8 @@ dependencies:
|
|||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.0
|
||||
flutter_bloc: ^8.1.6
|
||||
flutter_riverpod: ^2.5.1
|
||||
|
||||
dependency_overrides:
|
||||
http: 1.2.1
|
||||
|
|
Loading…
Reference in New Issue