Merge branch 'main' into fix/not_message

This commit is contained in:
Ivan Antunes 2024-08-13 09:39:11 -03:00
commit 4a40f6b6b3
19 changed files with 1452 additions and 1151 deletions

View File

@ -53,8 +53,8 @@
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6436409727A31CDC00820AF7 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6436409027A31CD400820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6436409227A31CDD00820AF7 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6436409B27A31CD600820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C1B4A503715BC7B0F8826983 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -303,8 +303,8 @@
6436409C27A31CD800820AF7 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
6436409727A31CDC00820AF7 /* pt */,
6436409027A31CD400820AF7 /* en */,
6436409227A31CDD00820AF7 /* pt */,
6436409B27A31CD600820AF7 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:hub/shared/utils/validator_util.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'api_manager.dart';
@ -1391,7 +1392,7 @@ class PostProvVisitSchedulingCall {
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'data': data,
'data': ValidatorUtil.toISO8601("dd/MM/yyyy HH:mm:ss", data!),
'motivo': motivo,
'nome': nome,
'proID': proID,
@ -1835,7 +1836,7 @@ class RespondeSolicitacaoCall {
}
class GetAccessCall {
Stream<ApiCallResponse> call({
Future<ApiCallResponse> call({
String? devUUID = '',
String? userUUID = '',
String? cliID = '',
@ -1845,43 +1846,31 @@ class GetAccessCall {
String? pesTipo = '',
}) {
final baseUrl = PhpGroup.getBaseUrl();
final StreamController<ApiCallResponse> controller = StreamController();
Future.microtask(() async {
try {
final response = await ApiManager.instance.makeApiCall(
callName: 'getAccess',
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,
'pesTipo': pesTipo,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
controller.add(response);
await controller.close();
} catch (e) {
controller.addError(e);
await controller.close();
}
});
return controller.stream;
return ApiManager.instance.makeApiCall(
callName: 'getAccess',
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,
'pesTipo': pesTipo,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
bool? error(dynamic response) => castToType<bool>(getJsonField(

View File

@ -13,6 +13,7 @@ import 'package:hub/app_state.dart';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/backend/api_requests/api_manager.dart';
import 'package:hub/components/templates_components/access_notification_modal_template_component/access_notification_modal_template_component_widget.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
@ -402,7 +403,7 @@ class NotificationHandler {
_getIdBasedOnUserType(message);
return Dialog(
backgroundColor: Colors.transparent,
child: VisitRequestTemplateComponentWidget(
child: DetailsComponentWidget(
buttons: [
FlutterFlowIconButton(
icon: const Icon(Icons.done),

View File

@ -1,3 +1,4 @@
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@ -7,7 +8,6 @@ import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
class OptModalWidget extends StatefulWidget {
final String defaultPersonType;
final String defaultAccessType;
@ -30,10 +30,6 @@ class _OptModalWidgetState extends State<OptModalWidget> {
{'title': 'zok7lu4w', 'value': 'E'},
{'title': 'oonqk812', 'value': 'O'},
];
final List<Map<String, String>> accessTypeOptions = [
{'title': '580z80ct', 'value': '0'},
{'title': '1nbwqtzs', 'value': '1'},
];
@override
void setState(VoidCallback callback) {
@ -65,7 +61,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
Map<String, String> filterResult = {
'personType': '',
'accessType': '',
'search': _model.textController?.text == ''
'search': _model.textController?.text == ''
? '.*'
: _model.textController!.text.toLowerCase(),
};
@ -89,7 +85,8 @@ class _OptModalWidgetState extends State<OptModalWidget> {
Navigator.pop(context, filterResult);
}
Widget _buildCheckboxListTile(String key, List<Map<String, String>> options) {
Widget _buildCheckboxListTile(
String key, List<Map<String, String>> options, double fontsize) {
return Column(
children: [
Row(
@ -97,14 +94,13 @@ class _OptModalWidgetState extends State<OptModalWidget> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0),
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 3.0, 0.0, 0.0),
child: Text(
FFLocalizations.of(context).getText('l7tw8b92'),
textAlign: TextAlign
.left, // Adiciona esta linha para alinhar o texto à esquerda
textAlign: TextAlign.left,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
fontSize: fontsize,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
@ -115,6 +111,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
],
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (context, index) {
@ -125,6 +122,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
fontSize: fontsize,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
@ -148,9 +146,10 @@ class _OptModalWidgetState extends State<OptModalWidget> {
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
enableFeedback: true,
side: BorderSide(
width: 10,
width: 5,
color: FlutterFlowTheme.of(context).secondaryText,
),
controlAffinity:
@ -178,157 +177,73 @@ class _OptModalWidgetState extends State<OptModalWidget> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Align(
alignment: const AlignmentDirectional(1.0, -1.0),
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return Center(
child: Container(
width: screenWidth * 0.75,
height: screenHeight * 0.35,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: BorderRadius.circular(24.0),
),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 50.0, 0.0),
child: Container(
width: 300.0,
height: 450.0,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: BorderRadius.circular(24.0),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
padding: const EdgeInsets.all(4.0),
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
10.0, 10.0, 0.0, 10.0),
child: Text(
FFLocalizations.of(context)
.getText('yfj9pd6k'), // Filtros
style: FlutterFlowTheme.of(context)
.headlineMedium
.override(
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
10.0, 10.0, 0.0, 10.0),
child: Text(
FFLocalizations.of(context)
.getText('yfj9pd6k'), // Filtros
style:
FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context)
.headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 16.0,
fontSize: 18.0,
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.headlineMediumFamily),
),
),
),
],
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
8.0, 0.0, 8.0, 0.0),
child: TextFormField(
controller: _model.textController,
focusNode: _model.textFieldFocusNode,
autofocus: false,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getText(
'0enrtljz' /* Pesquise aqui..... */,
),
labelStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.labelMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily),
),
hintStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.labelMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).alternate,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).primary,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
filled: true,
fillColor: FlutterFlowTheme.of(context).alternate,
suffixIcon: const Icon(
Icons.search_outlined,
),
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
),
validator:
_model.textControllerValidator.asValidator(context),
),
),
SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildCheckboxListTile(
'personType', personTypeOptions),
_buildCheckboxListTile(
'accessType', accessTypeOptions),
],
),
),
),
ElevatedButton(
onPressed: _applyFilter,
child:
Text(FFLocalizations.of(context).getText('88kshkph')),
style: ElevatedButton.styleFrom(
foregroundColor: FlutterFlowTheme.of(context).info,
backgroundColor: FlutterFlowTheme.of(context).primary,
),
),
],
),
),
Expanded(
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildCheckboxListTile(
'personType', personTypeOptions, 14),
],
),
),
),
),
ElevatedButton(
onPressed: _applyFilter,
style: ElevatedButton.styleFrom(
foregroundColor: FlutterFlowTheme.of(context).info,
backgroundColor: FlutterFlowTheme.of(context).primary,
),
child: Text(FFLocalizations.of(context).getText('88kshkph')),
),
],
),
),
),
);
}
}
}

View File

@ -1,6 +1,8 @@
import 'dart:collection';
import 'dart:developer';
import 'package:auto_size_text/auto_size_text.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'package:cached_network_image/cached_network_image.dart';
@ -71,8 +73,16 @@ class _CardItemTemplateComponentWidgetState
}
}
String truncate(int cutoff, String mytext) {
return (mytext.length <= cutoff)
? mytext
: '${mytext.substring(0, cutoff)}...';
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
context.watch<FFAppState>();
return InkWell(
splashColor: Colors.transparent,
@ -137,7 +147,7 @@ class _CardItemTemplateComponentWidgetState
fontFamily:
FlutterFlowTheme.of(context)
.bodyMediumFamily,
fontSize: 12.5,
fontSize: screenWidth * 0.025,
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts: GoogleFonts
@ -148,7 +158,7 @@ class _CardItemTemplateComponentWidgetState
.bodyMediumFamily),
color:
FlutterFlowTheme.of(context)
.primaryText,
.customColor6,
),
),
const SizedBox(

View File

@ -18,7 +18,7 @@ Widget buildDetails(
BuildContext context,
Future<dynamic> Function(BuildContext, int, int, String, String)?
changeStatusAction) {
return VisitRequestTemplateComponentWidget(
return DetailsComponentWidget(
buttons: [
if (getStatus(visitaWrapItem['VAW_STATUS']) ==
status.active) // REJECT ACTION

View File

@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
class VisitRequestTemplateComponentModel
extends FlutterFlowModel<VisitRequestTemplateComponentWidget> {
class DetailsComponentModel extends FlutterFlowModel<DetailsComponentWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.

View File

@ -11,8 +11,8 @@ import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:provider/provider.dart';
class VisitRequestTemplateComponentWidget extends StatefulWidget {
const VisitRequestTemplateComponentWidget({
class DetailsComponentWidget extends StatefulWidget {
const DetailsComponentWidget({
Key? key,
required this.labelsHashMap,
required this.statusHashMap,
@ -28,13 +28,13 @@ class VisitRequestTemplateComponentWidget extends StatefulWidget {
final List<Widget> buttons;
@override
State<VisitRequestTemplateComponentWidget> createState() =>
_VisitRequestTemplateComponentWidgetState();
State<DetailsComponentWidget> createState() =>
_DetailsComponentWidgetState();
}
class _VisitRequestTemplateComponentWidgetState
extends State<VisitRequestTemplateComponentWidget> {
late VisitRequestTemplateComponentModel _model;
class _DetailsComponentWidgetState
extends State<DetailsComponentWidget> {
late DetailsComponentModel _model;
LinkedHashMap<String, String> get labelsLinkedHashMap =>
LinkedHashMap.from(widget.labelsHashMap ?? {});
@ -53,7 +53,7 @@ class _VisitRequestTemplateComponentWidgetState
@override
void initState() {
super.initState();
_model = createModel(context, () => VisitRequestTemplateComponentModel());
_model = createModel(context, () => DetailsComponentModel());
_model.textFieldFocusNodeStatus ??= FocusNode();
}

View File

@ -19,7 +19,7 @@ class ForgotPasswordTemplateComponentModel
BuildContext context, String? val) {
if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getText(
'3hqg8buh' /* E-mail é Obrigatório */,
'snnmkbyc' /* E-mail é Obrigatório */,
);
}

View File

@ -320,46 +320,74 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
},
// scheduleProvisionalVisitPage
{
'x7at46ur': {
'pt': 'Quais visitantes você deseja cadastrar?',
'en': 'Which visitors do you want to register?',
'uj8acuab': {
'pt': 'Preencha os Campos Abaixo:',
'en': 'Fill in the fields below:',
},
'shj19b2o': {
'pt': 'Qual o período de validade da visita?',
'en': 'Visit Validity Period',
'8d3679lf': {
'pt': 'Propriedade',
'en': 'Property',
},
'8zgsw5so': {
'pt': 'Ínicio da Visita',
'en': 'Start of the Visit',
},
'p16wm7kp': {
'pt': 'Quando a visitas se inicia?',
'en': 'When does the visit start?',
},
'3zfd7uf9': {
'pt': 'Qual o nome do visitante?',
'en': 'What is the visitor\'s name?',
'z6aawgqa': {
'pt': 'Dados da Visita',
'en': 'Visit Data',
},
'wehvxbz4': {
'pt': 'Nome do Visitante',
'en': 'Visitor Name',
'pt': 'Nome / Apelido do Visitante',
'en': 'Visitor\'s Name / Nickname',
},
'juh7f24w': {
'pt': 'Escreva o nome do visitante aqui',
'en': 'Write the visitor\'s name here',
'pt': '',
'en': '',
},
'jhss056s': {
'pt': 'Você tem alguma observação sobre está visita?',
'en': 'Do you have any observations about this visit?',
'8zgsw5so': {
'pt': 'Data / Hora Limite da Visita',
'en': 'Visit Limit Date / Time',
},
'p16wm7kp': {
'pt': '',
'en': '',
},
'cw8b3tbb': {
'pt': 'Observações da Visita',
'en': 'Visit Observations',
'pt': 'Observação da Visita',
'en': 'Notes Visit',
},
'k4qkbv1f': {
'pt': 'Escreva as suas observações aqui',
'pt': '',
'en': 'Write your observations here',
},
'bv5fg9sv': {
'pt': 'Enviar',
'en': 'Send',
},
'3hqg8buh': {
'pt': 'Nome é Obrigatório',
'en': 'Name is Required',
},
'l0b0zr50': {
'pt': 'Máximo 80 caracteres',
'en': 'Maximum 80 characters',
},
'1p76vmkn': {
'pt': 'Please choose an option from the dropdown',
'en': '',
},
'uzefkuf9': {
'pt': 'Data / Hora é Obrigatório',
'en': 'Date / Time is Required',
},
'sn6pj4tx': {
'pt': 'Please choose an option from the dropdown',
'en': '',
},
'j14it3wp': {
'pt': 'Field is required',
'en': '',
},
'ypo6pxie': {
'pt': 'Please choose an option from the dropdown',
'en': '',
},
'cifgwfxs': {
'pt': 'Agendamento Provisório',
'en': 'Provisional Scheduling',
@ -518,8 +546,8 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
// optModal
{
'0enrtljz': {
'pt': 'Pesquise aqui.....',
'en': 'Search here.....',
'pt': 'Pesquise aqui...',
'en': 'Search here...',
},
'l7tw8b92': {
'pt': 'Tipo de Pessoa',
@ -1047,7 +1075,7 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
'pt': '',
'en': '',
},
'3hqg8buh': {
'snnmkbyc': {
'pt': 'E-mail é Obrigatório',
'en': 'E-mail is Required',
},
@ -1055,7 +1083,7 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
'pt': 'E-mail Inválido',
'en': 'Invalid E-mail',
},
'1p76vmkn': {
'ph22karc': {
'pt': 'Please choose an option from the dropdown',
'en': '',
},
@ -1064,7 +1092,7 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
'en': 'Send',
},
},
// visitRequestTemplateComponent
// detailsComponent
{
'ivfw4j04': {
'pt': 'Nome',

View File

@ -57,16 +57,25 @@ Future<List<SelectedFile>?> selectMediaWithSourceBottomSheet({
bool includeDimensions = false,
bool includeBlurHash = false,
}) async {
createUploadMediaListTile(String label, MediaSource mediaSource) => ListTile(
title: Text(
label,
textAlign: TextAlign.center,
style: GoogleFonts.getFont(
pickerFontFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontWeight: FontWeight.w600,
fontSize: 20,
),
createUploadMediaListTile(
String label, MediaSource mediaSource, IconData icon) =>
ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: FlutterFlowTheme.of(context).primaryText),
const SizedBox(width: 5),
Text(
label,
textAlign: TextAlign.center,
style: GoogleFonts.getFont(
pickerFontFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontWeight: FontWeight.w600,
fontSize: 12,
),
),
],
),
tileColor: FlutterFlowTheme.of(context).primaryBackground,
dense: false,
@ -83,11 +92,22 @@ Future<List<SelectedFile>?> selectMediaWithSourceBottomSheet({
mainAxisSize: MainAxisSize.min,
children: [
if (!kIsWeb) ...[
Container(
margin: const EdgeInsets.only(top: 10),
width: 40,
height: 5,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(10),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 0),
child: ListTile(
title: Text(
'Choose Source',
FFLocalizations.of(context).getVariableText(
ptText: "Escolha uma das opções",
enText: "Choose one of the options"),
textAlign: TextAlign.center,
style: GoogleFonts.getFont(
pickerFontFamily,
@ -95,41 +115,61 @@ Future<List<SelectedFile>?> selectMediaWithSourceBottomSheet({
.primaryText
.withOpacity(0.65),
fontWeight: FontWeight.w500,
fontSize: 20,
fontSize: 14,
),
),
tileColor: FlutterFlowTheme.of(context).primaryBackground,
dense: true,
),
),
const Divider(),
],
if (allowPhoto && allowVideo) ...[
createUploadMediaListTile(
'Gallery (Photo)',
MediaSource.photoGallery,
),
const Divider(),
createUploadMediaListTile(
'Gallery (Video)',
MediaSource.videoGallery,
),
] else if (allowPhoto)
createUploadMediaListTile(
'Gallery',
MediaSource.photoGallery,
)
else
createUploadMediaListTile(
'Gallery',
MediaSource.videoGallery,
),
if (!kIsWeb) ...[
const Divider(),
createUploadMediaListTile('Camera', MediaSource.camera),
const Divider(),
],
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (allowPhoto && allowVideo) ...[
Expanded(
child: createUploadMediaListTile(
FFLocalizations.of(context).getVariableText(
ptText: "Galeria (Foto)",
enText: "Gallery (Photo)"),
MediaSource.photoGallery,
Icons.camera),
),
Expanded(
child: createUploadMediaListTile(
FFLocalizations.of(context).getVariableText(
ptText: "Galeria (Video)",
enText: "Gallery (Video)"),
MediaSource.videoGallery,
Icons.videocam),
)
] else if (allowPhoto)
Expanded(
child: createUploadMediaListTile(
FFLocalizations.of(context).getVariableText(
ptText: "Galeria", enText: "Gallery"),
MediaSource.photoGallery,
Icons.photo))
else
Expanded(
child: createUploadMediaListTile(
FFLocalizations.of(context).getVariableText(
ptText: "Galeria", enText: "Gallery"),
MediaSource.videoGallery,
Icons.videocam),
),
if (!kIsWeb) ...[
Expanded(
child: createUploadMediaListTile(
FFLocalizations.of(context).getVariableText(
ptText: "Camera", enText: "Camera"),
MediaSource.camera,
Icons.camera_alt),
)
],
],
),
const SizedBox(height: 15),
],
);
});

View File

@ -11,11 +11,11 @@ import 'package:hub/pages/liberation_history/liberation_history_model.dart';
class AcessHistoryPageModel extends FlutterFlowModel<AcessHistoryPageWidget> {
final unfocusNode = FocusNode();
final _accessHistoryManager = StreamRequestManager<ApiCallResponse>();
Stream<ApiCallResponse> accessHistory({
final _accessHistoryManager = FutureRequestManager<ApiCallResponse>();
Future<ApiCallResponse> accessHistory({
String? uniqueQueryKey,
bool? overrideCache,
required Stream<ApiCallResponse> Function() requestFn,
required Future<ApiCallResponse> Function() requestFn,
}) =>
_accessHistoryManager.performRequest(
uniqueQueryKey: uniqueQueryKey,

View File

@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
@ -7,9 +9,7 @@ import 'package:hub/app_state.dart';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/backend/api_requests/api_manager.dart';
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart';
import 'package:hub/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/flutter_flow/custom_functions.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
@ -17,6 +17,8 @@ import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/pages/acess_history_page/acess_history_page_model.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:rxdart/rxdart.dart';
@immutable
@ -40,8 +42,8 @@ class AccessHistoryItemWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
return const Padding(
padding: EdgeInsets.all(8.0),
child: Column(),
);
}
@ -53,6 +55,17 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
bool _isSubjectClosed = false;
final scaffoldKey = GlobalKey<ScaffoldState>();
late ScrollController _scrollController;
int _pageNumber = 1;
final int _pageSize = 10;
bool _hasData = false;
bool _loading = false;
String _personType = '.*';
late Future<void> _accessFuture;
List<dynamic> _accessWrap = [];
_AcessHistoryPageWidgetState(Map<String, String> opt)
: selectedTypeSubject = BehaviorSubject.seeded(opt) {
selectedTypeSubject.listen((value) {});
@ -62,6 +75,15 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
void initState() {
super.initState();
_model = createModel(context, () => AcessHistoryPageModel());
_accessFuture = fetchAccessHistoryService();
_scrollController = ScrollController()
..addListener(() {
if (_scrollController.position.atEdge &&
_scrollController.position.pixels != 0) {
_loadMoreAccess();
}
});
}
@override
@ -73,31 +95,28 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
@override
Widget build(BuildContext context) {
final theme = FlutterFlowTheme.of(context);
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: _appBarOrganismWidget(context),
body: _accessHistoryListOrganismWidget(context));
appBar: _appBar(context, theme),
body: _body(context));
}
// AppBar Widgets
PreferredSizeWidget _appBarOrganismWidget(BuildContext context) {
final theme = FlutterFlowTheme.of(context);
PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) {
return AppBar(
backgroundColor: theme.primaryBackground,
automaticallyImplyLeading: false,
leading: _appBarBackButtonAtomWidget(context, theme),
title: _appBarTitleMoleculeWidget(context, theme),
leading: _backButton(context, theme),
title: _title(context, theme),
centerTitle: true,
elevation: 0.0,
actions: [
_appBarFilterButtonAtomWidget(context),
],
actions: [_filterButton(context)],
);
}
Widget _appBarBackButtonAtomWidget(
BuildContext context, FlutterFlowTheme theme) {
Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
@ -112,8 +131,7 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
);
}
Widget _appBarTitleMoleculeWidget(
BuildContext context, FlutterFlowTheme theme) {
Widget _title(BuildContext context, FlutterFlowTheme theme) {
return Text(
FFLocalizations.of(context).getText('ch8qymga'),
style: theme.headlineMedium.override(
@ -127,31 +145,42 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
);
}
Widget _appBarFilterButtonAtomWidget(BuildContext context) {
Widget _filterButton(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: const Icon(Icons.filter_list),
padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
onPressed: () async {
final Map<String, String>? selectedFilter =
await showModalBottomSheet<Map<String, String>>(
isScrollControlled: true,
backgroundColor: Colors.transparent,
context: context,
builder: (context) => OptModalWidget(
defaultAccessType:
selectedTypeSubject.value['accessType'] ?? '.*',
defaultPersonType:
selectedTypeSubject.value['personType'] ?? '.*',
),
);
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 10, 0),
child: IconButton(
icon: const Icon(Icons.filter_list),
onPressed: () async {
final Map<String, String>? selectedFilter =
await showModalBottomSheet<Map<String, String>>(
isScrollControlled: true,
backgroundColor: Colors.transparent,
context: context,
builder: (context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Colors.transparent,
child: GestureDetector(
onTap: () {},
child: OptModalWidget(
defaultPersonType:
selectedTypeSubject.value['personType'] ??
'.*',
),
),
),
);
});
if (selectedFilter != null) {
_updateAccessHistoryAction(selectedFilter);
}
},
if (selectedFilter != null) {
_updateAccessHistoryAction(selectedFilter);
}
},
),
),
],
);
@ -170,96 +199,126 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
});
if (needsUpdate) {
selectedTypeSubject.add(updatedType);
fetchCardListViewService(updatedType);
safeSetState(() {});
}
}
}
Stream<ApiCallResponse> fetchAccessHistoryService(String selectedType) {
switch (selectedType) {
case 'E':
return _model.accessHistory(
requestFn: () => PhpGroup.getAccessCall.call(
devUUID: FFAppState().devUUID,
userUUID: FFAppState().userUUID,
cliID: FFAppState().cliUUID,
atividade: 'getAcessos',
pageSize: '100',
pageNumber: '1',
pesTipo: 'E',
),
);
case 'O':
return _model.accessHistory(
requestFn: () => PhpGroup.getAccessCall.call(
devUUID: FFAppState().devUUID,
userUUID: FFAppState().userUUID,
cliID: FFAppState().cliUUID,
atividade: 'getAcessos',
pageSize: '100',
pageNumber: '1',
pesTipo: 'O',
),
);
default:
return _model.accessHistory(
requestFn: () => PhpGroup.getAccessCall.call(
devUUID: FFAppState().devUUID,
userUUID: FFAppState().userUUID,
cliID: FFAppState().cliUUID,
atividade: 'getAcessos',
pageSize: '100',
pageNumber: '1',
pesTipo: 'T',
),
);
Future<ApiCallResponse?> fetchAccessHistoryService() async {
try {
setState(() => _loading = true);
var response = await PhpGroup.getAccessCall.call(
devUUID: FFAppState().devUUID,
userUUID: FFAppState().userUUID,
cliID: FFAppState().cliUUID,
atividade: 'getAcessos',
pageSize: _pageSize.toString(),
pageNumber: _pageNumber.toString(),
pesTipo: _personType != 'E' && _personType != 'O' ? 'T' : _personType,
);
final List<dynamic> accessHistory = response.jsonBody['acessos'] ?? [];
List<dynamic> filteredAccess = accessHistory.where((item) {
final personTypeMatches =
_personType == '.*' || item["PES_TIPO"].toString() == _personType;
return personTypeMatches;
}).toList();
if (filteredAccess != null && filteredAccess.isNotEmpty) {
setState(() {
_accessWrap.addAll(filteredAccess);
_hasData = true;
_loading = false;
});
return response;
}
_showNoMoreDataSnackbar(context);
setState(() {
_hasData = false;
_loading = false;
});
return null;
} catch (e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed('processRequest', "", "Busca Acesso", e, s);
setState(() {
_hasData = false;
_loading = false;
});
}
}
Widget _accessHistoryListOrganismWidget(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
StreamBuilder<Map<String, String>>(
stream: selectedTypeSubject.stream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
final selected = snapshot.data!;
return _cardListViewOrganismWidget(selected);
},
),
],
void _showNoMoreDataSnackbar(BuildContext context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Não há mais dados.", enText: "No more data."),
),
duration: const Duration(seconds: 3),
backgroundColor: FlutterFlowTheme.of(context).primary,
),
);
}
Future<List<dynamic>> fetchCardListViewService(
Map<String, String> select) async {
final response =
await fetchAccessHistoryService(select['personType']!).first;
final List<dynamic> accessHistory = response.jsonBody['acessos'] ?? [];
return accessHistory.where((item) {
final personTypeMatches = select['personType'] == '.*' ||
item["PES_TIPO"].toString() == select['personType'];
final accessTypeMatches = select['accessType'] == '.*' ||
item["ACE_TIPO"].toString() == select['accessType'];
final searchMatches = select['search'] == '.*' ||
item["PES_NOME"]
.toString()
.toLowerCase()
.contains(select['search']!.toLowerCase());
return personTypeMatches && accessTypeMatches && searchMatches;
}).toList();
Widget _body(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if (_hasData == false && _pageNumber <= 1 && _loading == false)
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Center(
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Nenhum histórico encontrado!",
enText: "No history found!"),
)),
],
),
)
else if (_hasData || _pageNumber >= 1)
Expanded(child: _cardListViewOrganismWidget()),
if (_hasData == true && _loading)
Container(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
)
],
);
}
Widget _cardListViewOrganismWidget(Map<String, String> selected) {
return FutureBuilder<List<dynamic>>(
future: fetchCardListViewService(selected),
void _loadMoreAccess() {
if (_hasData == true) {
_pageNumber++;
_accessFuture = fetchAccessHistoryService();
}
}
void fetchCardListViewService(Map<String, String> select) {
_personType = select['personType']!;
_accessWrap = [];
_pageNumber = 1;
_accessFuture = fetchAccessHistoryService();
}
Widget _cardListViewOrganismWidget() {
return FutureBuilder<void>(
future: _accessFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
if (snapshot.connectionState == ConnectionState.waiting &&
_accessWrap.isEmpty) {
return Center(
child: SizedBox(
width: 50.0,
@ -271,20 +330,23 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
),
);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
final accessHistory = snapshot.data!;
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: accessHistory.length,
itemBuilder: (context, index) {
final accessHistoryItem = accessHistory[index];
return _accessHistoryCardMoleculeWidget(
context, accessHistoryItem);
},
return Center(
child: Text(FFLocalizations.of(context).getVariableText(
ptText: "Falha ao efetuar operação!",
enText: "Failed to perform operation!")),
);
}
return ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
controller: _scrollController,
itemCount: _accessWrap.length,
itemBuilder: (context, index) {
final accessHistoryItem = _accessWrap[index];
return _accessHistoryCardMoleculeWidget(context, accessHistoryItem);
},
);
},
);
}
@ -344,3 +406,10 @@ class _AcessHistoryPageWidgetState extends State<AcessHistoryPageWidget> {
onTapCardItemAction: () async {});
}
}
String imageUrlAtomWidget(String document, String type) {
return valueOrDefault<String>(
"https://freaccess.com.br/freaccess/getImage.php?&cliID=${FFAppState().cliUUID}&atividade=getFoto&Documento=$document&tipo=$type",
"https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg",
);
}

View File

@ -337,7 +337,7 @@ Widget liberationHistoryItemCard(
builder: (context) {
return Dialog(
alignment: Alignment.center,
child: VisitRequestTemplateComponentWidget(
child: DetailsComponentWidget(
// vteName: liberationHistoryItem['VTE_NOME'],
// vteReason: liberationHistoryItem['NOT_MOTIVO'],
// vawDate: liberationHistoryItem['NOT_STATUS'] == 'S'

View File

@ -1,8 +1,11 @@
import 'dart:developer';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/people_on_the_property_page/people_on_the_property_page_model.dart';
@ -13,6 +16,9 @@ import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import '../../shared/utils/dialog_util.dart';
import '../../shared/utils/log_util.dart';
class PeopleOnThePropertyPageWidget extends StatefulWidget {
const PeopleOnThePropertyPageWidget({super.key});
@ -106,9 +112,30 @@ class _PeopleOnThePropertyPageWidgetState
),
);
}
if (snapshot.hasError || snapshot.data?.exception != null) {
if (snapshot.error != null && snapshot.stackTrace != null) {
LogUtil.requestAPIFailed('getPessoasLocal.php', "", 'Busca Pessoas no Local', snapshot.error, snapshot.stackTrace!);
}
return Center(
child: SizedBox(
width: double.infinity,
height: 100,
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Pessoas não encontradas",
enText: "Persons not found"
),
textAlign: TextAlign.center,
),
),
);
}
final columnGetPessoasLocalResponse = snapshot.data!;
final getPoepleProperty = PhpGroup.getPessoasLocalCall.pessoas(columnGetPessoasLocalResponse.jsonBody,)?.toList() ??
[];
final getPoepleProperty = PhpGroup.getPessoasLocalCall.pessoas(columnGetPessoasLocalResponse.jsonBody,)?.toList() ?? [];
return ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
shrinkWrap: true,

View File

@ -1587,7 +1587,7 @@ Widget scheduleVisit(
// updateToggleIdx: () async {},
// repeatVisitSchedule: () async {},
// ),
child: VisitRequestTemplateComponentWidget(
child: DetailsComponentWidget(
buttons: [
FlutterFlowIconButton(
icon: const Icon(Icons.done),

View File

@ -5,6 +5,8 @@ import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:flutter/material.dart';
import 'package:hub/pages/schedule_provisional_visit_page/schedule_provisional_visit_page_widget.dart';
import '../../flutter_flow/internationalization.dart';
class ScheduleProvisionalVisitPageModel
extends FlutterFlowModel<ScheduleProvisionalVisitPageWidget> {
/// Local state fields for this page.
@ -30,36 +32,65 @@ class ScheduleProvisionalVisitPageModel
/// State fields for stateful widgets in this page.
final unfocusNode = FocusNode();
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode1;
TextEditingController? textController1;
String? Function(BuildContext, String?)? textController1Validator;
final formKey = GlobalKey<FormState>();
// State field(s) for personName widget.
FocusNode? personNameFocusNode;
TextEditingController? personNameTextController;
String? Function(BuildContext, String?)? personNameTextControllerValidator;
String? _personNameTextControllerValidator(
BuildContext context, String? val) {
if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getText(
'3hqg8buh' /* Nome é Obrigatório */,
);
}
if (val.length > 80) {
return FFLocalizations.of(context).getText(
'l0b0zr50' /* Máximo 80 caracteres */,
);
}
return null;
}
// State field(s) for dateTime widget.
FocusNode? dateTimeFocusNode;
TextEditingController? dateTimeTextController;
String? Function(BuildContext, String?)? dateTimeTextControllerValidator;
String? _dateTimeTextControllerValidator(BuildContext context, String? val) {
if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getText(
'uzefkuf9' /* Data / Hora é Obrigatório */,
);
}
return null;
}
DateTime? datePicked;
// 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;
// Stores action output result for [Backend Call - API (postProvVisitScheduling)] action in sendContainer widget.
ApiCallResponse? provisionalVisitScheduling;
// State field(s) for notes widget.
FocusNode? notesFocusNode;
TextEditingController? notesTextController;
String? Function(BuildContext, String?)? notesTextControllerValidator;
// Stores action output result for [Backend Call - API (postProvVisitScheduling)] action in btnSend widget.
ApiCallResponse? provVisitSchedule;
@override
void initState(BuildContext context) {}
void initState(BuildContext context) {
personNameTextControllerValidator = _personNameTextControllerValidator;
dateTimeTextControllerValidator = _dateTimeTextControllerValidator;
}
@override
void dispose() {
unfocusNode.dispose();
textFieldFocusNode1?.dispose();
textController1?.dispose();
personNameFocusNode?.dispose();
personNameTextController?.dispose();
textFieldFocusNode2?.dispose();
textController2?.dispose();
dateTimeFocusNode?.dispose();
dateTimeTextController?.dispose();
textFieldFocusNode3?.dispose();
textController3?.dispose();
notesFocusNode?.dispose();
notesTextController?.dispose();
}
}

View File

@ -1,3 +1,5 @@
import 'package:intl/intl.dart';
class ValidatorUtil {
static bool isValidEmail(String email) {
if (RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(email)) {
@ -14,4 +16,11 @@ class ValidatorUtil {
return false;
}
}
static String toISO8601(String format, String value) {
DateFormat dateFormat = DateFormat(format);
DateTime dateTime = dateFormat.parse(value);
return dateTime.toIso8601String();
}
}