Merge pull request #74 from FRE-Informatica/feat/fd-1023

FEAT/FD-1023 - Consulta de Agendamentos Provisórios
This commit is contained in:
Ivan Antunes 2024-12-11 16:00:13 -03:00 committed by GitHub
commit 6653137979
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 1432 additions and 913 deletions

View File

@ -0,0 +1,209 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hub/flutter_flow/random_data_util.dart';
import 'package:hub/initialization.dart';
import 'package:hub/main.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:integration_test/integration_test.dart';
late WidgetTester widget;
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group(
'Initialization',
() {
group('Navigation', () {
setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false')));
testWidgets('Test Welcome', (WidgetTester tester) async {
widget = tester;
await _testWelcome();
});
});
group('Terms of Use', () {
// Add tests for Terms of Use here
});
},
);
group('Authentication', () {
group('Sign in', () {
setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false')));
testWidgets('Test Sign In', (WidgetTester tester) async {
widget = tester;
await _testSignIn();
});
});
group('Sign up', () {
setUpAll(() async => await initializeApp().then((_) async => await StorageHelper().set(SecureStorageKey.isLogged.value, 'false')));
testWidgets('Test Sign Up', (WidgetTester tester) async {
widget = tester;
await _testSignUp();
});
});
group('Sign Out', () {
// Add tests for Sign Out here
});
group('Forgot Password', () {
// setUpAll(() async => await initializeApp().then((_) => StorageUtil().isLogged = false));
// testWidgets('Test Forgot Password', (WidgetTester tester) async {
// widget = tester;
// await _testForgotPassword();
// });
});
});
group('Localization', () {
// Add tests for Localization here
});
group('Networking', () {
// Add tests for Networking here
});
group('Functionality', () {
// Add tests for Functionality here
});
group('Usability', () {
// Add tests for Usability here
});
group('Performance', () {
// Add tests for Performance here
});
group('Security', () {
// Add tests for Security here
});
group('Accessibility', () {
// Add tests for Accessibility here
});
group('Compatibility', () {
// Add tests for Compatibility here
});
group('Internationalization', () {
// Add tests for Internationalization here
});
}
Future<void> _testWelcome() async {
await widget.pumpWidget(const App());
await widget.pumpAndSettle();
await _navigateToSignIn();
await _navigateToSignUp();
await widget.pumpAndSettle();
await widget.pumpWidget(const App());
await widget.pumpAndSettle();
await _navigateToSignUp();
await _navigateToSignIn();
await widget.pumpAndSettle();
}
Future<void> _testSignIn() async {
await widget.pumpWidget(const App());
await _navigateToSignIn();
await _auth({'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678'});
await _auth({'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'});
}
Future<void> _testSignUp() async {
await widget.pumpWidget(const App());
await _navigateToSignUp();
var credentials = {'nameTextFormField': 'app', 'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'};
await _auth(credentials);
var name = randomString(7, 7, true, true, true);
var email = '$name@example.com';
var password = '12345678';
credentials = {'nameTextFormField': name, 'emailTextFormField': email, 'passwordTextFormField': password};
await _navigateToSignUp();
await _auth(credentials);
credentials = {'emailTextFormField': email, 'passwordTextFormField': password};
await _auth(credentials);
}
Future<void> _testForgotPassword() async {
await widget.pumpWidget(const App());
await _navigateToSignIn();
await _recoveryPassword();
var addr = randomString(5, 5, true, true, true);
var credentials = {'recoveryTextFormField': '$addr@exemple.com'};
await _send(credentials);
await Future.delayed(const Duration(seconds: 2));
await _recoveryPassword();
credentials = {'recoveryTextFormField': 'email_app@exemple.com'};
await _send(credentials);
}
Future<void> _recoveryPassword() async {
await widget.pumpAndSettle();
final Finder forgotPassword = find.byKey(const ValueKey<String>('ForgotPassword'));
if (forgotPassword.evaluate().isNotEmpty) await widget.tap(forgotPassword);
await widget.ensureVisible(forgotPassword);
await widget.pumpAndSettle();
}
Future<void> _navigateBackUsingSystemGesture() async => IntegrationTestWidgetsFlutterBinding.instance.keyboard.isLogicalKeyPressed(LogicalKeyboardKey.escape);
Future<void> _navigateToSignUp() async {
await widget.pumpAndSettle();
final Finder navToSignUp = find.byKey(const ValueKey<String>('toggleSignUpPage'));
if (navToSignUp.evaluate().isNotEmpty) {
await widget.tap(navToSignUp);
await widget.pumpAndSettle();
}
}
Future<void> _navigateToSignIn() async {
await widget.pumpAndSettle();
final Finder navToSignIn = find.byKey(const ValueKey<String>('toggleSignInPage'));
expect(navToSignIn, findsOneWidget);
if (navToSignIn.evaluate().isNotEmpty) {
await widget.tap(navToSignIn);
await widget.pumpAndSettle();
}
}
Future<void> _auth(Map<String, dynamic> credentials) async {
await _enterCredentials(credentials);
await _submit('SubmitButtonWidget');
}
Future<void> _send(Map<String, dynamic> credentials) async {
await _enterCredentials(credentials);
await _submit('SendButtonWidget');
}
Future<void> _enterCredentials(Map<String, dynamic> credentials) async {
await widget.pumpAndSettle();
for (var entry in credentials.entries) {
final Finder field = find.byKey(ValueKey<String>(entry.key));
await widget.pumpAndSettle();
expect(field, findsOneWidget);
await widget.enterText(field, entry.value);
await widget.pumpAndSettle();
}
await widget.pumpAndSettle();
}
Future<void> _submit(String key) async {
await widget.pumpAndSettle();
final Finder submitButton = find.byKey(ValueKey<String>(key));
await widget.pumpAndSettle();
if (submitButton.evaluate().isNotEmpty) {
await widget.tap(submitButton);
await widget.pumpAndSettle();
}
final Finder throwExceptionWidget = find.byKey(const ValueKey<String>('ThrowExceptionWidget'));
await widget.pumpAndSettle();
if (throwExceptionWidget.evaluate().isNotEmpty) {
await widget.ensureVisible(throwExceptionWidget);
await widget.tap(throwExceptionWidget);
await widget.pumpAndSettle();
} else {
await _navigateBackUsingSystemGesture();
}
}

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/initialization.dart';
import 'package:hub/main.dart' as app;
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:integration_test/integration_test.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('ProvisionalHistoryPage Integration Test', () {
setUpAll(() async => await initializeApp().then((_) async {
await StorageHelper().set(SecureStorageKey.isLogged.value, 'true');
await StorageHelper().set(SecureStorageKey.haveLocal.value, 'true');
await StorageHelper().set(KeychainStorageKey.devUUID.value, 'b5c3818753e76d85');
await StorageHelper().set(KeychainStorageKey.userUUID.value, '649c45d7514a28.85876308');
await StorageHelper().set(KeychainStorageKey.clientUUID.value, '7');
}));
testWidgets('Filter Provisional History', (WidgetTester tester) async {
app.main();
await tester.pumpAndSettle();
final Finder menuButton = find.byIcon(Icons.person_search_outlined);
await tester.tap(menuButton);
await tester.pumpAndSettle();
final Finder filterButton = find.byIcon(Icons.filter_list);
await tester.tap(filterButton);
await tester.pumpAndSettle();
final Finder activeFilterOption = find.text('Active');
await tester.tap(activeFilterOption);
await tester.pumpAndSettle();
final Finder applyFilterButton = find.text('Apply');
await tester.tap(applyFilterButton);
await tester.pumpAndSettle();
expect(find.byType(CardItemTemplateComponentWidget), findsWidgets);
});
});
}

View File

@ -63,36 +63,35 @@ class PhpGroup {
}
class GetProvSchedules {
Future<ApiCallResponse> call(final String page) async {
// final String baseUrl = PhpGroup.getBaseUrl();
// final String devUUID = (await StorageHelper().g(KeychainStorageKey.devUUID.value)) ?? '';
// final String userUUID = (await StorageHelper().g(KeychainStorageKey.userUUID.value)) ?? '';
// final String cliID = (await StorageHelper().g(KeychainStorageKey.clientUUID.value)) ?? '';
// const String atividade = 'getProvSchedules';
// const String pageSize = '10';
final String baseUrl = 'http://localhost:3000';
Future<ApiCallResponse> call(final String page, final String status) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String devUUID = (await StorageHelper().get(KeychainStorageKey.devUUID.value)) ?? '';
final String userUUID = (await StorageHelper().get(KeychainStorageKey.userUUID.value)) ?? '';
final String cliID = (await StorageHelper().get(KeychainStorageKey.clientUUID.value)) ?? '';
const String atividade = 'getAgendamentoProv';
const String pageSize = '10';
final bool isFiltered = status != '' && status != '.*';
// const String baseUrl = 'http://localhost:3000';
return await ApiManager.instance.makeApiCall(
callName: 'getProvSchedules',
apiUrl: '$baseUrl/getAgendamentoProv.php',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
params: {
"proId": "8",
"status": "AT",
"page": page,
"pageSize": "10"
// 'devUUID': devUUID,
// 'userUUID': userUUID,
// 'cliID': cliID,
// 'atividade': atividade,
// 'page': page,
// 'pageSize': pageSize,
if (isFiltered) 'status': status,
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'page': page,
'pageSize': pageSize,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
@ -194,7 +193,6 @@ class GetVehiclesByProperty {
static GetLicense getLicense = GetLicense();
}
class GetLicense {
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
@ -935,25 +933,27 @@ class GetLocalsCall {
final String devUUID = await StorageHelper().get(KeychainStorageKey.devUUID.value) ?? '';
final String userUUID = await StorageHelper().get(KeychainStorageKey.userUUID.value) ?? '';
return await ApiManager.instance.makeApiCall(
callName: 'getLocals',
apiUrl: '$baseUrl/getLocais.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
return await ApiManager.instance
.makeApiCall(
callName: 'getLocals',
apiUrl: '$baseUrl/getLocais.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
)
.timeout(const Duration(seconds: 30));
}
List? locais(dynamic response) => getJsonField(
@ -2639,8 +2639,7 @@ class ApiPagingParams {
});
@override
String toString() =>
'PagingParams(nextPageNumber: $nextPageNumber, numItems: $numItems, lastResponse: $lastResponse,)';
String toString() => 'PagingParams(nextPageNumber: $nextPageNumber, numItems: $numItems, lastResponse: $lastResponse,)';
}
String _toEncodable(dynamic item) {

View File

@ -1,31 +0,0 @@
import 'package:flutter/material.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/form_field_controller.dart';
import 'opt_modal_widget.dart' show OptModalWidget;
class OptModalModel extends FlutterFlowModel<OptModalWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
// State field(s) for Checkbox widget.
bool? checkboxValue1;
// State field(s) for Checkbox widget.
bool? checkboxValue2;
// State field(s) for CheckboxGroup widget.
FormFieldController<List<String>>? checkboxGroupValueController;
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
set checkboxGroupValues(List<String>? v) => checkboxGroupValueController?.value = v;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}

View File

@ -1,30 +0,0 @@
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/form_field_controller.dart';
import 'opt_modal_widget.dart' show OptModalWidget;
import 'package:flutter/material.dart';
class OptModalModel extends FlutterFlowModel<OptModalWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
// State field(s) for Checkbox widget.
bool? checkboxValue1;
// State field(s) for Checkbox widget.
bool? checkboxValue2;
// State field(s) for CheckboxGroup widget.
FormFieldController<List<String>>? checkboxGroupValueController;
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
set checkboxGroupValues(List<String>? v) => checkboxGroupValueController?.value = v;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}

View File

@ -1,302 +0,0 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_model.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
class OptModalWidget extends StatefulWidget {
final String defaultPersonType;
final String defaultAccessType;
const OptModalWidget({
super.key,
this.defaultPersonType = '.*',
this.defaultAccessType = '.*',
});
@override
_OptModalWidgetState createState() => _OptModalWidgetState();
}
class _OptModalWidgetState extends State<OptModalWidget> {
late OptModalModel _model;
late Map<String, dynamic> selected;
final List<Map<String, String>> personTypeOptions = [
{'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) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => OptModalModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
selected = {
'personType': widget.defaultPersonType == '.*' ? ['E', 'O'] : [widget.defaultPersonType],
'accessType': widget.defaultAccessType == '.*' ? ['0', '1'] : [widget.defaultAccessType],
'search': '.*',
};
}
void _applyFilter() {
Map<String, String> filterResult = {
'personType': '',
'accessType': '',
'search': _model.textController?.text == '' ? '.*' : _model.textController!.text.toLowerCase(),
};
if (selected['personType']!.isEmpty) {
filterResult['personType'] = '.*';
} else if (selected['personType']!.length > 1) {
filterResult['personType'] = '.*';
} else {
filterResult['personType'] = selected['personType']!.first;
}
if (selected['accessType']!.isEmpty) {
filterResult['accessType'] = '.*';
} else if (selected['accessType']!.length > 1) {
filterResult['accessType'] = '.*';
} else {
filterResult['accessType'] = selected['accessType']!.first;
}
// Navigator.pop(context, filterResult);
context.pop(filterResult);
}
Widget _buildCheckboxListTile(String key, List<Map<String, String>> options) {
return Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0),
child: Text(
FFLocalizations.of(context).getText('l7tw8b92'),
textAlign: TextAlign.left, // Adiciona esta linha para alinhar o texto à esquerda
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
),
],
),
ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (context, index) {
final option = options[index];
return CheckboxListTile(
title: Text(
FFLocalizations.of(context).getText(option['title']!),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
dense: true,
value: selected[key]!.contains(option['value']),
onChanged: (bool? value) {
setState(() {
if (value == true) {
if (!selected[key]!.contains(option['value'])) {
selected[key]!.add(option['value']);
}
} else {
selected[key]!.remove(option['value']);
}
});
},
activeColor: FlutterFlowTheme.of(context).primary,
checkColor: FlutterFlowTheme.of(context).info,
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
enableFeedback: true,
side: BorderSide(
width: 10,
color: FlutterFlowTheme.of(context).secondaryText,
),
controlAffinity: ListTileControlAffinity.leading, // Adiciona esta linha
);
},
),
],
);
}
void _updateSelection(String? value, String key) {
setState(() {
if (value == '.') {
selected[key] = [];
} else if (value != null) {
if (selected[key]!.contains(value)) {
selected[key]!.remove(value);
} else {
selected[key]!.add(value);
}
}
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Align(
alignment: const AlignmentDirectional(1.0, -1.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(
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(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 16.0,
letterSpacing: 0.0,
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,
style: ElevatedButton.styleFrom(
foregroundColor: FlutterFlowTheme.of(context).info,
backgroundColor: FlutterFlowTheme.of(context).primary,
),
child: Text(FFLocalizations.of(context).getText('88kshkph')),
),
],
),
),
),
),
),
);
}
}

View File

@ -79,7 +79,7 @@ class _CardItemTemplateComponentWidgetState extends State<CardItemTemplateCompon
Expanded(
child: Text(
text,
overflow: TextOverflow.ellipsis,
overflow: TextOverflow.fade,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
fontSize: limitedBodyTextSize,
@ -165,15 +165,13 @@ class _CardItemTemplateComponentWidgetState extends State<CardItemTemplateCompon
mainAxisSize: MainAxisSize.min,
children: [
..._generateLabels(),
SizedBox(height: 3),
Wrap(
spacing: 8,
runSpacing: 4,
children: _generateStatus(),
),
]
.addToEnd(const SizedBox(height: 5))
.divide(const SizedBox(height: 1))
.addToStart(const SizedBox(height: 5)),
].addToEnd(const SizedBox(height: 5)).divide(const SizedBox(height: 1)).addToStart(const SizedBox(height: 5)),
),
),
if (widget.imagePath != null) _generateImage(),

View File

@ -0,0 +1,2 @@
export 'local_data_sources/index.dart';
export 'remote_data_sources/index.dart';

View File

@ -0,0 +1,2 @@
export 'access_history_local_data_source.dart';
export 'provisional_history_local_data_source.dart';

View File

@ -0,0 +1,2 @@
export 'access_history_remote_data_source.dart';
export 'provisional_history_remote_data_source.dart';

View File

@ -0,0 +1,3 @@
export 'data_sources/index.dart';
export 'repositories/index.dart';
export 'models/index.dart';

View File

@ -0,0 +1,2 @@
export 'access_history_repository_impl.dart';
export 'provisional_history_repository_impl.dart';

View File

@ -0,0 +1,3 @@
export 'entities/index.dart';
export 'respositories/index.dart';
export 'usecases/index.dart';

View File

@ -0,0 +1 @@
export 'history_repository.dart';

View File

@ -0,0 +1,3 @@
export 'data/index.dart';
export 'domain/index.dart';
export 'presentation/index.dart';

View File

@ -1,9 +1,8 @@
import 'package:flutter/material.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/features/history/index.dart';
import 'package:hub/flutter_flow/flutter_flow_model.dart';
import 'package:hub/flutter_flow/request_manager.dart';
import 'package:hub/pages/acess_history_page/acess_history_page_widget.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
@ -44,24 +43,4 @@ class AcessHistoryPageModel extends FlutterFlowModel<AccessHistoryScreen> {
clearAccessHistoryCache();
}
Future toggleOptionsAction(BuildContext context) async {
await showModalBottomSheet(
isScrollControlled: true,
backgroundColor: Colors.transparent,
useSafeArea: true,
context: context,
builder: (context) {
return GestureDetector(
onTap: () => unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(unfocusNode)
: FocusScope.of(context).unfocus(),
child: Padding(
padding: MediaQuery.viewInsetsOf(context),
child: const OptModalWidget(),
),
);
},
);
}
}

View File

@ -0,0 +1,2 @@
export 'access_history_bloc.dart';
export 'provisional_history_bloc.dart';

View File

@ -0,0 +1,52 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
class ProvisionalHistoryEvent {}
class LoadProvisionalHistory extends ProvisionalHistoryEvent {}
class ProvisionalHistoryStateBloc {
final String devUUID;
final String userUUID;
final String cliUUID;
final bool isLoading;
ProvisionalHistoryStateBloc({
required this.devUUID,
required this.userUUID,
required this.cliUUID,
this.isLoading = false,
});
ProvisionalHistoryStateBloc copyWith({
String? devUUID,
String? userUUID,
String? cliUUID,
bool? isLoading,
}) {
return ProvisionalHistoryStateBloc(
devUUID: devUUID ?? this.devUUID,
userUUID: userUUID ?? this.userUUID,
cliUUID: cliUUID ?? this.cliUUID,
isLoading: isLoading ?? this.isLoading,
);
}
}
class ProvisionalHistoryBloc extends Bloc<ProvisionalHistoryEvent, ProvisionalHistoryStateBloc> {
ProvisionalHistoryBloc() : super(ProvisionalHistoryStateBloc(devUUID: '', userUUID: '', cliUUID: '')) {
on<LoadProvisionalHistory>(_onLoadProvisionalHistory);
}
Future<void> _onLoadProvisionalHistory(
LoadProvisionalHistory event,
Emitter<ProvisionalHistoryStateBloc> emit,
) async {
emit(state.copyWith(isLoading: true));
final devUUID = (await StorageHelper().get(KeychainStorageKey.devUUID.value)) ?? '';
final userUUID = (await StorageHelper().get(KeychainStorageKey.userUUID.value)) ?? '';
final cliUUID = (await StorageHelper().get(KeychainStorageKey.clientUUID.value)) ?? '';
emit(state.copyWith(devUUID: devUUID, userUUID: userUUID, cliUUID: cliUUID, isLoading: false));
}
}

View File

@ -0,0 +1,4 @@
export 'blocs/index.dart';
export 'widgets/index.dart';
export 'pages/index.dart';

View File

@ -4,12 +4,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/history/index.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/pages/acess_history_page/acess_history_page_model.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart';
@ -18,11 +17,8 @@ import 'package:rxdart/rxdart.dart';
@immutable
// ignore: must_be_immutable
class AccessHistoryScreen extends StatefulWidget {
late Map<String, String> opt = {
'personType': '.*',
'accessType': '.*',
'search': '.*',
};
late Map<String, String> opt = {'personType': '.*'};
AccessHistoryScreen({super.key, required this.opt});
@override
State<AccessHistoryScreen> createState() => _AccessHistoryState(opt);
@ -75,10 +71,11 @@ class _AccessHistoryState extends State<AccessHistoryScreen> {
final theme = FlutterFlowTheme.of(context);
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: _appBar(context, theme),
body: _body(context));
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: _appBar(context, theme),
body: _body(context),
);
}
PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) {
@ -141,8 +138,21 @@ class _AccessHistoryState extends State<AccessHistoryScreen> {
color: Colors.transparent,
child: GestureDetector(
onTap: () {},
child: OptModalWidget(
defaultPersonType: selectedTypeSubject.value['personType'] ?? '.*',
child: FilterWidget(
defaultSelections: selectedTypeSubject.value,
filterOptions: {
'personType': [
{
'title': FFLocalizations.of(context).getText('zok7lu4w'),
'value': 'E',
},
{
'title': FFLocalizations.of(context).getText('oonqk812'),
'value': 'O',
},
],
},
filterTitles: {'personType': ''},
),
),
),
@ -247,8 +257,7 @@ class _AccessHistoryState extends State<AccessHistoryScreen> {
children: [
Center(
child: Text(
FFLocalizations.of(context)
.getVariableText(ptText: "Nenhum histórico encontrado!", enText: "No history found!"),
FFLocalizations.of(context).getVariableText(ptText: "Nenhum histórico encontrado!", enText: "No history found!"),
)),
],
),
@ -301,8 +310,7 @@ class _AccessHistoryState extends State<AccessHistoryScreen> {
);
} else if (snapshot.hasError) {
return Center(
child: Text(FFLocalizations.of(context)
.getVariableText(ptText: "Falha ao efetuar operação!", enText: "Failed to perform operation!")),
child: Text(FFLocalizations.of(context).getVariableText(ptText: "Falha ao efetuar operação!", enText: "Failed to perform operation!")),
);
}

View File

@ -0,0 +1,2 @@
export 'acess_history_page_widget.dart';
export 'provisional_history_page.dart';

View File

@ -0,0 +1,424 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/history/index.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/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/snackbar_util.dart';
import 'package:rxdart/rxdart.dart';
@immutable
// ignore: must_be_immutable
class ProvisionalHistoryPage extends StatefulWidget {
Map<String, String> opt;
ProvisionalHistoryPage({super.key, Map<String, String>? opt}) : opt = opt ?? const {'AGP_STATUS': '.*'};
@override
State<ProvisionalHistoryPage> createState() => ProvisionalHistoryState(opt);
}
class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
final BehaviorSubject<Map<String, String>> selectedTypeSubject;
late ScrollController _scrollController;
final scaffoldKey = GlobalKey<ScaffoldState>();
bool _isSubjectClosed = false;
int _pageNumber = 1;
bool hasData = false;
bool _loading = false;
String status = '.*';
late Future<void> future;
List<dynamic> wrap = [];
ProvisionalHistoryState(Map<String, String> opt) : selectedTypeSubject = BehaviorSubject.seeded(opt) {
selectedTypeSubject.listen((value) {});
}
@override
void initState() {
super.initState();
future = fetchHistoryService();
_scrollController = ScrollController()
..addListener(() {
if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) {
_loadMore();
}
});
}
@override
void dispose() {
selectedTypeSubject.close();
_isSubjectClosed = true;
super.dispose();
}
@override
Widget build(BuildContext context) {
final theme = FlutterFlowTheme.of(context);
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: _appBar(context, theme),
body: _body(context),
);
}
PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) {
return AppBar(
backgroundColor: theme.primaryBackground,
automaticallyImplyLeading: false,
leading: _backButton(context, theme),
title: _title(context, theme),
centerTitle: true,
elevation: 0.0,
actions: [_filterButton(context)],
);
}
Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
return FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: theme.primaryText,
size: 30.0,
),
onPressed: () => Navigator.of(context).pop(),
);
}
Widget _title(BuildContext context, FlutterFlowTheme theme) {
return Text(
FFLocalizations.of(context).getVariableText(
ptText: 'Histórico Provisório',
enText: 'Provisional History',
),
style: theme.headlineMedium.override(
fontFamily: theme.headlineMediumFamily,
color: theme.primaryText,
fontSize: 16.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(theme.headlineMediumFamily),
),
);
}
Widget _filterButton(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
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: FilterWidget(
defaultSelections: selectedTypeSubject.value,
filterOptions: {
'AGP_STATUS': [
{
'title': FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
),
'value': 'AT',
},
{
'title': FFLocalizations.of(context).getVariableText(
ptText: 'Convidado',
enText: 'Guest',
),
'value': 'CO',
},
{
'title': FFLocalizations.of(context).getVariableText(
ptText: 'Inativo',
enText: 'Inactive',
),
'value': 'IN',
},
{
'title': FFLocalizations.of(context).getVariableText(
ptText: 'Aguardando Aprovação',
enText: 'Awaiting Approval',
),
'value': 'AA',
},
],
},
filterTitles: {'AGP_STATUS': ''},
),
),
),
);
});
if (selectedFilter != null) {
_updateHistoryAction(selectedFilter);
}
},
),
),
],
);
}
void _updateHistoryAction(Map<String, String> newType) {
if (!_isSubjectClosed) {
final currentType = selectedTypeSubject.value;
final updatedType = Map<String, String>.from(currentType);
bool needsUpdate = false;
newType.forEach((key, newValue) {
if (currentType[key] != newValue) {
updatedType[key] = newValue;
needsUpdate = true;
}
});
if (needsUpdate) {
selectedTypeSubject.add(updatedType);
fetchCardListViewService(updatedType);
safeSetState(() {});
}
}
}
Future<ApiCallResponse?> fetchHistoryService() async {
try {
setState(() => _loading = true);
var response = await PhpGroup.getProvSchedules(_pageNumber.toString(), status);
final List<dynamic> history = response.jsonBody['agendamento']['value'] ?? [];
if (history.isNotEmpty) {
setState(() {
wrap.addAll(history);
hasData = true;
_loading = false;
});
return response;
}
SnackBarUtil.showNoMoreDataSnackbar(context);
setState(() {
hasData = false;
_loading = false;
});
return null;
} catch (e, s) {
await DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed('processRequest', "", "Busca Acesso", e, s);
setState(() {
hasData = false;
_loading = false;
});
}
return null;
}
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,
),
),
),
)
],
);
}
void _loadMore() {
if (hasData == true) {
_pageNumber++;
future = fetchHistoryService();
}
}
void fetchCardListViewService(Map<String, String> select) {
status = select['AGP_STATUS']!;
wrap = [];
_pageNumber = 1;
future = fetchHistoryService();
}
Widget _cardListViewOrganismWidget() {
return FutureBuilder<void>(
future: future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting && wrap.isEmpty) {
return Center(
child: SizedBox(
width: 50.0,
height: 50.0,
child: SpinKitCircle(
color: FlutterFlowTheme.of(context).primary,
size: 50.0,
),
),
);
} else if (snapshot.hasError) {
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: wrap.length,
itemBuilder: (context, index) {
final historyItem = wrap[index];
return _historyCardMoleculeWidget(context, historyItem);
},
);
},
);
}
Widget _historyCardMoleculeWidget(BuildContext context, dynamic historyItem) {
return CardItemTemplateComponentWidget(
imagePath: null,
labelsHashMap: _buildLabelsHashMap(context, historyItem),
statusHashMap: _buildStatusHashMap(context, historyItem),
onTapCardItemAction: () async {},
);
}
String _imageUrlAtomWidget(String document, String type) {
return valueOrDefault<String>(
"https://freaccess.com.br/freaccess/getImage.php?&cliID=&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",
);
}
Map<String, String> _buildLabelsHashMap(BuildContext context, dynamic historyItem) {
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Nome:',
enText: 'Name:',
): historyItem['AGP_NOME'] ?? '',
FFLocalizations.of(context).getVariableText(
ptText: 'Data:',
enText: 'Data:',
): formatDate(historyItem['AGP_DT_VISITA']),
FFLocalizations.of(context).getVariableText(
ptText: 'Observação:',
enText: 'Observation:',
): formatObs(historyItem['AGP_OBSERVACAO']),
};
}
String formatObs(String? obs) {
if (obs == null || obs.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Não fornecida',
enText: 'No provided',
);
}
return obs;
}
String formatDate(String dateString) {
DateTime dateTime = DateTime.parse(dateString);
return "${dateTime.day.toString().padLeft(2, '0')}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.year} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}";
}
List<Map<String, Color>> _buildStatusHashMap(BuildContext context, dynamic historyItem) {
return [
{
FFLocalizations.of(context).getVariableText(
ptText: 'Visitante',
enText: 'Visitor',
): FlutterFlowTheme.of(context).alternate2,
},
_getStatusMap(context, historyItem['AGP_STATUS'])
];
}
Map<String, Color> _getStatusMap(BuildContext context, String status) {
switch (status) {
case 'AT':
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
): FlutterFlowTheme.of(context).success,
};
case 'CO':
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Convidado',
enText: 'Called',
): Colors.blue,
};
case 'IN':
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Inativo',
enText: 'Inactive',
): FlutterFlowTheme.of(context).error,
};
case 'AA':
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Aguardando Aprovação',
enText: 'Awaiting Approval',
): FlutterFlowTheme.of(context).warning,
};
default:
return {
FFLocalizations.of(context).getVariableText(
ptText: 'Desconhecido',
enText: 'Unknown',
): FlutterFlowTheme.of(context).alternate2,
};
}
}
}

View File

@ -1,27 +1,53 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_model.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/form_field_controller.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
class OptModalWidget extends StatefulWidget {
class AccessFilterModel extends FlutterFlowModel<AccessFilter> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
// State field(s) for Checkbox widget.
bool? checkboxValue1;
// State field(s) for Checkbox widget.
bool? checkboxValue2;
// State field(s) for CheckboxGroup widget.
FormFieldController<List<String>>? checkboxGroupValueController;
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
set checkboxGroupValues(List<String>? v) => checkboxGroupValueController?.value = v;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}
class AccessFilter extends StatefulWidget {
final String defaultPersonType;
final String defaultAccessType;
const OptModalWidget({
const AccessFilter({
super.key,
this.defaultPersonType = '.*',
this.defaultAccessType = '.*',
});
@override
_OptModalWidgetState createState() => _OptModalWidgetState();
_AccessFilterState createState() => _AccessFilterState();
}
class _OptModalWidgetState extends State<OptModalWidget> {
late OptModalModel _model;
class _AccessFilterState extends State<AccessFilter> {
late AccessFilterModel _model;
late Map<String, dynamic> selected;
final List<Map<String, String>> personTypeOptions = [
@ -39,7 +65,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
void initState() {
super.initState();
_model = createModel(context, () => OptModalModel());
_model = createModel(context, () => AccessFilterModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
@ -194,8 +220,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
fontSize: LimitedFontSizeUtil.getHeaderFontSize(context),
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts:
GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily),
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily),
),
),
),
@ -227,8 +252,7 @@ class _OptModalWidgetState extends State<OptModalWidget> {
fontSize: LimitedFontSizeUtil.getInputFontSize(context),
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts:
GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
)),
),
],

View File

@ -0,0 +1,2 @@
export 'access_filter_modal.dart';
export 'provisional_filter_modal.dart';

View File

@ -0,0 +1,235 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/form_field_controller.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
class FilterModel extends FlutterFlowModel<FilterWidget> {
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
bool? checkboxValue1;
bool? checkboxValue2;
FormFieldController<List<String>>? checkboxGroupValueController;
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
set checkboxGroupValues(List<String>? v) => checkboxGroupValueController?.value = v;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}
class FilterWidget extends StatefulWidget {
final Map<String, dynamic> defaultSelections;
final Map<String, List<Map<String, String>>> filterOptions;
final Map<String, String> filterTitles;
const FilterWidget({
super.key,
required this.defaultSelections,
required this.filterOptions,
required this.filterTitles,
});
@override
_FilterWidgetState createState() => _FilterWidgetState();
}
class _FilterWidgetState extends State<FilterWidget> {
late FilterModel _model;
late Map<String, dynamic> selected;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => FilterModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
selected = Map<String, dynamic>.from(widget.defaultSelections);
}
void _applyFilter() {
Map<String, String> filterResult = {
'search': _model.textController?.text == '' ? '.*' : _model.textController!.text.toLowerCase(),
};
widget.filterOptions.forEach((key, options) {
filterResult[key] = selected[key]!.isEmpty || selected[key]!.length < 1 ? '.*' : selected[key]!;
});
setState(() {
// Update the state with the new filter result
selected = filterResult;
});
context.pop(filterResult);
}
Widget _buildCheckboxListTile(String key, List<Map<String, String>> options, double fontsize) {
double limitedInputFontSize = LimitedFontSizeUtil.getInputFontSize(context);
return Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 3.0, 0.0, 0.0),
child: Text(
widget.filterTitles[key]!,
textAlign: TextAlign.left,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
fontSize: limitedInputFontSize,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
),
],
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (context, index) {
final option = options[index];
return CheckboxListTile(
title: Text(
option['title']!,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
fontSize: limitedInputFontSize,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
dense: true,
value: selected[key]!.contains(option['value']),
onChanged: (bool? value) {
setState(() {
if (value == true) {
if (!selected[key]!.contains(option['value'])) {
selected[key] = option['value'];
}
} else {
selected[key] = '';
}
});
},
activeColor: FlutterFlowTheme.of(context).primary,
checkColor: FlutterFlowTheme.of(context).info,
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
enableFeedback: true,
side: BorderSide(
width: 5,
color: FlutterFlowTheme.of(context).secondaryText,
),
controlAffinity: ListTileControlAffinity.leading,
);
},
),
],
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return Center(
child: Container(
width: screenWidth - (screenWidth * 0.35),
height: screenWidth,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: BorderRadius.circular(24.0),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
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).getVariableText(
ptText: 'Filtros',
enText: 'Filters',
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: LimitedFontSizeUtil.getHeaderFontSize(context),
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily),
),
),
),
],
),
Expanded(
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: widget.filterOptions.keys.map((key) {
return _buildCheckboxListTile(key, widget.filterOptions[key]!, 14);
}).toList(),
),
),
),
),
ElevatedButton(
onPressed: _applyFilter,
style: ElevatedButton.styleFrom(
foregroundColor: FlutterFlowTheme.of(context).info,
backgroundColor: FlutterFlowTheme.of(context).primary,
),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: 'Aplicar',
enText: 'Apply',
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
color: FlutterFlowTheme.of(context).info,
fontSize: LimitedFontSizeUtil.getInputFontSize(context),
letterSpacing: 0.0,
fontWeight: FontWeight.bold,
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
)),
),
],
),
),
),
);
}
}

View File

@ -1,16 +1,14 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/home/presentation/widgets/drawer_widget.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/shared/components/molecules/drawer/index.dart';
import 'package:hub/shared/components/molecules/locals/index.dart';
import 'package:hub/shared/components/molecules/menu/index.dart';
class HomePageWidget extends StatefulWidget {
const HomePageWidget(this.update, {super.key});
final Future<bool> Function(BuildContext context)? update;
@ -29,8 +27,8 @@ class _HomePageWidgetState extends State<HomePageWidget> with WidgetsBindingObse
WidgetsBinding.instance.addPostFrameCallback((_) async {
await LocalsRepositoryImpl().check(context);
if (widget.update != null) {
await widget.update!(context);
}
await widget.update!(context);
}
});
}
@ -40,7 +38,6 @@ class _HomePageWidgetState extends State<HomePageWidget> with WidgetsBindingObse
super.dispose();
}
@override
Widget build(BuildContext context) {
return Builder(
@ -49,13 +46,13 @@ class _HomePageWidgetState extends State<HomePageWidget> with WidgetsBindingObse
// context.read<LocalProfileBloc>().add(LocalProfileEvent());
// context.read<MenuBloc>().add(MenuEvent());
LocalsRepositoryImpl.license.add(true);
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
drawerEnableOpenDragGesture: true,
drawerDragStartBehavior: DragStartBehavior.start,
drawer: CustomDrawer(),
drawer: DrawerWidget(),
appBar: buildAppBar(context),
body: buildPage(context),
);

View File

@ -9,8 +9,8 @@ import 'package:hub/shared/components/molecules/locals/index.dart';
import 'package:hub/shared/components/molecules/menu/index.dart';
import 'package:hub/shared/components/molecules/modules/index.dart';
class CustomDrawer extends StatelessWidget {
const CustomDrawer({super.key});
class DrawerWidget extends StatelessWidget {
const DrawerWidget({super.key});
@override
Widget build(BuildContext context) {

View File

@ -3,12 +3,13 @@ import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/backend/schema/util/schema_util.dart';
import 'package:hub/features/history/index.dart';
import 'package:hub/features/home/index.dart';
import 'package:hub/features/property/index.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/acess_history_page/acess_history_page_widget.dart';
import 'package:hub/pages/delivery_schedule_page/delivery_schedule_widget.dart';
import 'package:hub/pages/fast_pass_page/fast_pass_page_widget.dart';
import 'package:hub/pages/forgot_password_page/forgot_password_screen.dart';
@ -32,6 +33,11 @@ import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart
import 'package:hub/pages/visits_on_the_property/visits_on_the_property_screen.dart';
import 'package:hub/pages/welcome_page/welcome_page_widget.dart';
import 'package:hub/shared/components/molecules/locals/data/repositories/locals_repository_impl.dart';
import 'package:hub/shared/components/molecules/locals/presentation/blocs/local_profile_bloc.dart';
import 'package:hub/shared/components/molecules/menu/domain/entities/menu_item.dart';
import 'package:hub/shared/components/molecules/menu/presentation/blocs/menu_bloc.dart';
import 'package:hub/shared/components/molecules/menu/presentation/mappers/menu_entry.dart';
import 'package:hub/shared/components/molecules/menu/presentation/widgets/menu_view/menu_list_view.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:hub/shared/utils/dialog_util.dart';
@ -92,7 +98,26 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
final bool haveDevUUID = (await StorageHelper().get(KeychainStorageKey.devUUID.value))?.isNotEmpty ?? false;
if (isLogged && haveDevUUID && haveUserUUID) {
return haveLocal ? HomePageWidget(LocalsRepositoryImpl().update) : const ReceptionPageWidget();
return haveLocal
? MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => MenuBloc(
style: MenuView.list_grid,
item: EnumMenuItem.button,
entries: MenuEntry.getEntriesByType(MenuEntryType.Home),
)..add(MenuEvent()),
),
BlocProvider<HomeBloc>(
create: (context) => HomeBloc()..add(HomeEvent()),
),
BlocProvider(
create: (context) => LocalProfileBloc()..add(LocalProfileEvent()),
),
],
child: HomePageWidget(key: UniqueKey(), LocalsRepositoryImpl().update),
)
: const ReceptionPageWidget();
} else {
return const WelcomePageWidget();
}
@ -123,11 +148,30 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
token: token,
);
}),
FFRoute(name: 'homePage', path: '/homePage', builder: (context, params) {
final Future<bool> Function(BuildContext context)? update = params.getParam('update', ParamType.Function);
return HomePageWidget(key: UniqueKey(), update);
}),
FFRoute(
name: 'homePage',
path: '/homePage',
builder: (context, params) {
final Future<bool> Function(BuildContext context)? update = params.getParam('update', ParamType.Function);
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => MenuBloc(
style: MenuView.list_grid,
item: EnumMenuItem.button,
entries: MenuEntry.getEntriesByType(MenuEntryType.Home),
)..add(MenuEvent()),
),
BlocProvider<HomeBloc>(
create: (context) => HomeBloc()..add(HomeEvent()),
),
BlocProvider(
create: (context) => LocalProfileBloc()..add(LocalProfileEvent()),
),
],
child: HomePageWidget(key: UniqueKey(), update),
);
}),
FFRoute(name: 'petsOnThePropertyPage', path: '/petsOnThePropertyPage', builder: (context, params) => Scaffold(body: const PetsHistoryScreen(isApp: true))),
FFRoute(name: 'vehiclesOnThePropertyPage', path: '/vehiclesOnThePropertyPage', builder: (context, params) => const VehicleOnTheProperty()),
FFRoute(name: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()),
@ -136,7 +180,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
FFRoute(name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', builder: (context, params) => const ScheduleCompleteVisitPageWidget()),
FFRoute(name: 'deliverySchedule', path: '/deliverySchedule', builder: (context, params) => const DeliverySchedule()),
FFRoute(name: 'provisionalSchedule', path: '/provisionalSchedule', builder: (context, params) => const ProvisionalSchedule()),
FFRoute(name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => /*const*/ FastPassPageWidget()),
FFRoute(name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => FastPassPageWidget()),
FFRoute(name: 'preferencesSettings', path: '/preferencesSettings', builder: (context, params) => PreferencesPageWidget()),
FFRoute(name: 'aboutProperty', path: '/aboutProperty', builder: (context, params) => AboutPropertyPage()),
FFRoute(name: 'residentsOnThePropertyPage', path: '/residentsOnThePropertyPage', builder: (context, params) => ResidentsOnTheProperty()),
@ -146,6 +190,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
name: 'acessHistoryPage',
path: '/acessHistoryPage',
builder: (context, params) => AccessHistoryScreen(opt: const {'personType': '.*', 'accessType': '.*', 'search': '.*'})),
FFRoute(name: 'provisionalHistoryPage', path: '/provisionalHistoryPage', builder: (context, params) => ProvisionalHistoryPage()),
FFRoute(name: 'liberationHistory', path: '/liberationHistory', builder: (context, params) => const LiberationHistoryWidget()),
FFRoute(name: 'signInPage', path: '/signInPage', builder: (context, params) => const SignInPageWidget()),
FFRoute(name: 'signUpPage', path: '/signUpPage', builder: (context, params) => const SignUpPageWidget()),

View File

@ -5,25 +5,18 @@ import 'dart:io';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hub/backend/notifications/notification_service.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/components/molecules/locals/index.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'package:hub/shared/services/deeplink/deep_link_service.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hub/shared/extensions/string_extensions.dart';
import 'backend/notifications/firebase_messaging_service.dart';
import 'features/home/index.dart';
import 'initialization.dart';
import 'shared/components/molecules/menu/index.dart';
import 'shared/components/molecules/modules/index.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@ -60,7 +53,7 @@ class App extends StatefulWidget {
static _AppState of(BuildContext context) => context.findAncestorStateOfType<_AppState>()!;
}
class _AppState extends State<App> {
class _AppState extends State<App> {
Locale? _locale = FFLocalizations.getStoredLocale();
ThemeMode _themeMode = FlutterFlowTheme.themeMode;
late AppStateNotifier _appStateNotifier;
@ -169,7 +162,7 @@ class _AppState extends State<App> {
@override
void initState() {
super.initState();
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
_appStateNotifier = AppStateNotifier.instance;
_router = createRouter(_appStateNotifier);
@ -187,38 +180,19 @@ class _AppState extends State<App> {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => MenuBloc(
style: MenuView.list_grid,
item: EnumMenuItem.button,
entries: MenuEntry.getEntriesByType(MenuEntryType.Home),
)..add(MenuEvent()),
),
BlocProvider<HomeBloc>(
create: (context) => HomeBloc()..add(HomeEvent()),
),
BlocProvider(
create: (context) => LocalProfileBloc()..add(LocalProfileEvent()),
),
],
child: MaterialApp.router(
key: navigatorKey,
title: 'FRE ACCESS HUB',
builder: builder,
localizationsDelegates: localizationsDelegates,
locale: _locale,
supportedLocales: supportedLocales,
theme: _theme,
darkTheme: _darkTheme,
themeMode: _themeMode,
routerConfig: _router,
),
return MaterialApp.router(
key: navigatorKey,
title: 'FRE ACCESS HUB',
builder: builder,
localizationsDelegates: localizationsDelegates,
locale: _locale,
supportedLocales: supportedLocales,
theme: _theme,
darkTheme: _darkTheme,
themeMode: _themeMode,
routerConfig: _router,
);
}
}

View File

@ -1 +0,0 @@
export 'drawer_widget.dart';

View File

@ -61,6 +61,16 @@ class MenuEntry implements BaseModule {
route: '/scheduleCompleteVisitPage',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-PROVISIONAL-HISTORY',
icon: Icons.person_search_outlined,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Consultar Agendas',
enText: 'Provisional History',
),
route: '/provisionalHistoryPage',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-RESIDENTS',
icon: Icons.groups,
@ -144,10 +154,7 @@ class MenuEntry implements BaseModule {
MenuEntry(
key: 'FRE-HUB-PETS',
icon: Icons.pets,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Cadastrar Pets',
enText: 'Pets Register'
),
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(ptText: 'Cadastrar Pets', enText: 'Pets Register'),
route: '/petsPage',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
@ -162,14 +169,14 @@ class MenuEntry implements BaseModule {
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-LIBERATIONS',
icon: Icons.how_to_reg_outlined,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Consultar Liberações',
enText: 'Liberations History',
),
route: '/liberationHistory',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
key: 'FRE-HUB-LIBERATIONS',
icon: Icons.how_to_reg_outlined,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Consultar Liberações',
enText: 'Liberations History',
),
route: '/liberationHistory',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-MESSAGES',
@ -191,7 +198,6 @@ class MenuEntry implements BaseModule {
route: '/aboutProperty',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-PEOPLE',
icon: Icons.groups,
@ -227,7 +233,4 @@ class MenuEntry implements BaseModule {
static List<MenuEntry> getEntriesByType(MenuEntryType type) {
return entries.where((entry) => entry.types.contains(type)).toList();
}
}

View File

@ -1,12 +1,9 @@
import 'package:hub/shared/extensions/string_extensions.dart';
import 'package:hub/shared/helpers/storage/base_storage.dart';
import 'package:hub/shared/helpers/storage/storage_helper.dart';
import 'module.dart';
enum LicenseKeys {
messages('FRE-HUB-MESSAGES'),
liberations('FRE-HUB-LIBERATIONS'),
@ -20,6 +17,7 @@ enum LicenseKeys {
completeSchedule('FRE-HUB-COMPLETE-SCHEDULE'),
providerSchedule('FRE-HUB-AGE-PROV-PREST'),
deliverySchedule('FRE-HUB-AGE-PROV-DELIVERY'),
provisionalHistory('FRE-HUB-PROVISIONAL-HISTORY'),
property('FRE-HUB-ABOUT-PROPERTY'),
fastPass('FRE-HUB-FASTPASS'),
visitors('FRE-HUB-VISITORS'),
@ -29,14 +27,10 @@ enum LicenseKeys {
settings('FRE-HUB-SETTINGS'),
logout('FRE-HUB-LOGOUT');
final String value;
const LicenseKeys(this.value);
}
class License {
final List<Module> modules;
@ -44,10 +38,9 @@ class License {
this.modules,
);
static Future<String> _processWithoutModule(LicenseKeys key) async {
switch(key) {
case LicenseKeys.reservations:
switch (key) {
case LicenseKeys.reservations:
return await _precessWpp();
case LicenseKeys.orders:
return await _precessWpp();
@ -68,171 +61,188 @@ class License {
static Future<String> _precessWpp() async {
final bool whatsapp = await StorageHelper().get(KeychainStorageKey.whatsapp.value).then((v) => v.toBoolean());
if (whatsapp) return ModuleStatus.active.key;
else return ModuleStatus.inactive.key;
if (whatsapp)
return ModuleStatus.active.key;
else
return ModuleStatus.inactive.key;
}
static Future<String> _processProvisional() async {
final bool provisional = await StorageHelper().get(KeychainStorageKey.provisional.value).then((v) => v.toBoolean());
if (provisional) return ModuleStatus.active.key;
else return ModuleStatus.inactive.key;
if (provisional)
return ModuleStatus.active.key;
else
return ModuleStatus.inactive.key;
}
static Future<String> _processPets() async {
final bool pets = await StorageHelper().get(KeychainStorageKey.pets.value).then((v) => v.toBoolean());
if (pets) return ModuleStatus.active.key;
else return ModuleStatus.inactive.key;
if (pets)
return ModuleStatus.active.key;
else
return ModuleStatus.inactive.key;
}
static getKeyByModule(String s) {
static getKeyByModule(String s) {}
}
/// Returns a [License] object with the modules and their status.
/// @param isNewVersion: Indica que é sistema novo que possui modularização.
static Future<License> getLicense(bool isNewVersionWithModule) async {
return License([
Module(
key: LicenseKeys.messages.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.liberations.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.reservations.value,
display: await _processWithoutModule(LicenseKeys.reservations),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.access.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.openedVisits.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.vehicles.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.residents.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.pets.value,
display: await _processWithoutModule(LicenseKeys.pets),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.orders.value,
display: await _processWithoutModule(LicenseKeys.orders),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.completeSchedule.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.providerSchedule.value,
display: await _processWithoutModule(LicenseKeys.providerSchedule),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.deliverySchedule.value,
display: await _processWithoutModule(LicenseKeys.deliverySchedule),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.fastPass.value,
display: await _processWithoutModule(LicenseKeys.fastPass),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.qrCode.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.visitors.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.property.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.people.value,
display: isNewVersionWithModule ? ModuleStatus.inactive.key : ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.petsHistory.value,
display: await _processWithoutModule(LicenseKeys.pets),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.settings.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.logout.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.messages.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.provisionalHistory.value,
display: ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.liberations.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.reservations.value,
display: await _processWithoutModule(LicenseKeys.reservations),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.access.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.access.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.openedVisits.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.vehicles.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.residents.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.pets.value,
display: await _processWithoutModule(LicenseKeys.pets),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.orders.value,
display: await _processWithoutModule(LicenseKeys.orders),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.completeSchedule.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.providerSchedule.value,
display: await _processWithoutModule(LicenseKeys.providerSchedule),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.deliverySchedule.value,
display: await _processWithoutModule(LicenseKeys.deliverySchedule),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.fastPass.value,
display: await _processWithoutModule(LicenseKeys.fastPass),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.qrCode.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.visitors.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.property.value,
display: isNewVersionWithModule ? ModuleStatus.active.key : ModuleStatus.inactive.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.people.value,
display: isNewVersionWithModule ? ModuleStatus.inactive.key : ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.petsHistory.value,
display: await _processWithoutModule(LicenseKeys.pets),
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.settings.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.logout.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
]);
}
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
import '../../flutter_flow/flutter_flow_theme.dart';
@ -22,4 +23,20 @@ class SnackBarUtil {
),
);
}
static 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."),
style: TextStyle(
color: Colors.white,
fontSize: LimitedFontSizeUtil.getBodyFontSize(context),
),
),
duration: const Duration(seconds: 3),
backgroundColor: FlutterFlowTheme.of(context).primary,
),
);
}
}

View File

@ -386,10 +386,10 @@ packages:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.1"
version: "7.0.0"
file_picker:
dependency: "direct main"
description:
@ -555,6 +555,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.4.1"
flutter_driver:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_inappwebview:
dependency: "direct main"
description:
@ -786,6 +791,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
glob:
dependency: transitive
description:
@ -938,6 +948,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
integration_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: "direct main"
description:
@ -1138,6 +1153,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
mockito:
dependency: "direct dev"
description:
name: mockito
sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
url: "https://pub.dev"
source: hosted
version: "5.4.4"
nested:
dependency: transitive
description:
@ -1310,10 +1333,10 @@ packages:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
version: "3.1.5"
plugin_platform_interface:
dependency: "direct main"
description:
@ -1330,6 +1353,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.1"
process:
dependency: transitive
description:
name: process
sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
provider:
dependency: "direct main"
description:
@ -1607,6 +1638,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
sync_http:
dependency: transitive
description:
name: sync_http
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
url: "https://pub.dev"
source: hosted
version: "0.3.1"
synchronized:
dependency: "direct main"
description:
@ -1799,6 +1838,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.1"
webdriver:
dependency: transitive
description:
name: webdriver
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
webview_flutter:
dependency: "direct main"
description:

View File

@ -114,11 +114,10 @@ dev_dependencies:
flutter_lints: ^5.0.0
image: ^4.3.0
lints: ^5.0.0
# build_runner: ^2.4.13
# mockito: ^5.4.4
# integration_test:
# sdk: flutter
# build_runner: ^2.4.13
mockito: ^5.4.4
integration_test:
sdk: flutter
flutter_test:
sdk: flutter
build_runner: ^2.4.13

View File

@ -1,210 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'package:flutter_test/flutter_test.dart';
// import 'package:hub/flutter_flow/random_data_util.dart';
// import 'package:hub/main.dart';
// import 'package:hub/shared/helpers/storage/base_storage.dart';
// import 'package:hub/shared/helpers/storage/storage_helper.dart';
// import 'package:integration_test/integration_test.dart';
// late WidgetTester widget;
// void main() {
// IntegrationTestWidgetsFlutterBinding.ensureInitialized();
// group('Initialization', () {
// group('Navigation', () {
// setUpAll(() async =>
// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false')));
// testWidgets('Test Welcome', (WidgetTester tester) async {
// widget = tester;
// await _testWelcome();
// });
// });
// group('Terms of Use', () {});
// });
// group('Authentication', () {
// group('Sign in', () {
// setUpAll(() async =>
// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false')));
// testWidgets('Test Sign In', (WidgetTester tester) async {
// widget = tester;
// await _testSignIn();
// });
// });
// group('Sign up', () {
// setUpAll(() async =>
// await initializeApp().then((_) async => await StorageHelper().s(SecureStorageKey.isLogged.value, 'false')));
// testWidgets('Test Sign Up', (WidgetTester tester) async {
// widget = tester;
// await _testSignUp();
// });
// });
// group('Sign Out', () {
// // Add tests for Sign Out here
// });
// group('Forgot Password', () {
// // setUpAll(() async => await initializeApp().then((_) => StorageUtil().isLogged = false));
// // testWidgets('Test Forgot Password', (WidgetTester tester) async {
// // widget = tester;
// // await _testForgotPassword();
// // });
// });
// });
// group('Localization', () {
// // Add tests for Localization here
// });
// group('Networking', () {
// // Add tests for Networking here
// });
// group('Functionality', () {
// // Add tests for Functionality here
// });
// group('Usability', () {
// // Add tests for Usability here
// });
// group('Performance', () {
// // Add tests for Performance here
// });
// group('Security', () {
// // Add tests for Security here
// });
// group('Accessibility', () {
// // Add tests for Accessibility here
// });
// group('Compatibility', () {
// // Add tests for Compatibility here
// });
// group('Internationalization', () {
// // Add tests for Internationalization here
// });
// }
// Future<void> _testWelcome() async {
// await widget.pumpWidget(const App());
// await widget.pumpAndSettle();
// await _navigateToSignIn();
// await _navigateToSignUp();
// await widget.pumpAndSettle();
// await widget.pumpWidget(const App());
// await widget.pumpAndSettle();
// await _navigateToSignUp();
// await _navigateToSignIn();
// await widget.pumpAndSettle();
// }
// Future<void> _testSignIn() async {
// await widget.pumpWidget(const App());
// await _navigateToSignIn();
// await _auth({'emailTextFormField': 'erro@exemplo.com', 'passwordTextFormField': '12345678'});
// await _auth({'emailTextFormField': 'email_app@exemplo.com', 'passwordTextFormField': '12345678'});
// }
// Future<void> _testSignUp() async {
// await widget.pumpWidget(const App());
// await _navigateToSignUp();
// var credentials = {
// 'nameTextFormField': 'app',
// 'emailTextFormField': 'email_app@exemplo.com',
// 'passwordTextFormField': '12345678'
// };
// await _auth(credentials);
// var name = randomString(7, 7, true, true, true);
// var email = '$name@example.com';
// var password = '12345678';
// credentials = {'nameTextFormField': name, 'emailTextFormField': email, 'passwordTextFormField': password};
// await _navigateToSignUp();
// await _auth(credentials);
// credentials = {'emailTextFormField': email, 'passwordTextFormField': password};
// await _auth(credentials);
// }
// Future<void> _testForgotPassword() async {
// await widget.pumpWidget(const App());
// await _navigateToSignIn();
// await _recoveryPassword();
// var addr = randomString(5, 5, true, true, true);
// var credentials = {'recoveryTextFormField': '$addr@exemple.com'};
// await _send(credentials);
// await Future.delayed(const Duration(seconds: 2));
// await _recoveryPassword();
// credentials = {'recoveryTextFormField': 'email_app@exemple.com'};
// await _send(credentials);
// }
// Future<void> _recoveryPassword() async {
// await widget.pumpAndSettle();
// final Finder forgotPassword = find.byKey(const ValueKey<String>('ForgotPassword'));
// if (forgotPassword.evaluate().isNotEmpty) await widget.tap(forgotPassword);
// await widget.ensureVisible(forgotPassword);
// await widget.pumpAndSettle();
// }
// Future<void> _navigateBackUsingSystemGesture() async =>
// IntegrationTestWidgetsFlutterBinding.instance.keyboard.isLogicalKeyPressed(LogicalKeyboardKey.escape);
// Future<void> _navigateToSignUp() async {
// await widget.pumpAndSettle();
// final Finder navToSignUp = find.byKey(const ValueKey<String>('toggleSignUpPage'));
// if (navToSignUp.evaluate().isNotEmpty) {
// await widget.tap(navToSignUp);
// await widget.pumpAndSettle();
// }
// }
// Future<void> _navigateToSignIn() async {
// await widget.pumpAndSettle();
// final Finder navToSignIn = find.byKey(const ValueKey<String>('toggleSignInPage'));
// expect(navToSignIn, findsOneWidget);
// if (navToSignIn.evaluate().isNotEmpty) {
// await widget.tap(navToSignIn);
// await widget.pumpAndSettle();
// }
// }
// Future<void> _auth(Map<String, dynamic> credentials) async {
// await _enterCredentials(credentials);
// await _submit('SubmitButtonWidget');
// }
// Future<void> _send(Map<String, dynamic> credentials) async {
// await _enterCredentials(credentials);
// await _submit('SendButtonWidget');
// }
// Future<void> _enterCredentials(Map<String, dynamic> credentials) async {
// await widget.pumpAndSettle();
// for (var entry in credentials.entries) {
// final Finder field = find.byKey(ValueKey<String>(entry.key));
// await widget.pumpAndSettle();
// expect(field, findsOneWidget);
// await widget.enterText(field, entry.value);
// await widget.pumpAndSettle();
// }
// await widget.pumpAndSettle();
// }
// Future<void> _submit(String key) async {
// await widget.pumpAndSettle();
// final Finder submitButton = find.byKey(ValueKey<String>(key));
// await widget.pumpAndSettle();
// if (submitButton.evaluate().isNotEmpty) {
// await widget.tap(submitButton);
// await widget.pumpAndSettle();
// }
// final Finder throwExceptionWidget = find.byKey(const ValueKey<String>('ThrowExceptionWidget'));
// await widget.pumpAndSettle();
// if (throwExceptionWidget.evaluate().isNotEmpty) {
// await widget.ensureVisible(throwExceptionWidget);
// await widget.tap(throwExceptionWidget);
// await widget.pumpAndSettle();
// } else {
// await _navigateBackUsingSystemGesture();
// }
// }