Merge pull request #99 from FRE-Informatica/feat/fd-465

FEAT/FD-465: Documentação no APP
This commit is contained in:
Ivan Antunes 2025-02-27 10:26:24 -03:00 committed by GitHub
commit fb5f755d70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
102 changed files with 3470 additions and 639 deletions

16
.vscode/launch.json vendored
View File

@ -4,26 +4,34 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "flutter-freaccesss-hub",
"request": "launch",
"type": "dart",
"args": [
"--no-enable-impeller"
"--no-enable-impeller",
" --enable-experiment=macros"
]
},
{
"name": "flutter-freaccesss-hub (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
"flutterMode": "profile",
"args": [
"--no-enable-impeller",
" --enable-experiment=macros"
]
},
{
"name": "flutter-freaccesss-hub (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
"flutterMode": "release",
"args": [
"--no-enable-impeller",
" --enable-experiment=macros"
]
}
]
}

View File

@ -2,3 +2,4 @@ description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
- provider: true
- patrol: true

BIN
flutter_01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

0
hx Normal file
View File

View File

@ -1,5 +1,5 @@
import 'dart:collection';
import 'dart:math';
import 'dart:developer';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_core/firebase_core.dart';
@ -26,7 +26,6 @@ import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart
import 'package:integration_test/integration_test.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:patrol/patrol.dart';
import 'app_test.dart';
import 'fuzzer/fuzzer.dart';

View File

@ -48,11 +48,11 @@ class AuthenticationTest {
await _navigateToSignIn($);
for (var credential in credentials) {
print('Função: ${credential.functionName}');
print('Entradas: ${credential.inputs}');
print('Saída: ${credential.output}');
print('Mensagem: ${credential.message}');
print('---');
log('Função: ${credential.functionName}');
log('Entradas: ${credential.inputs}');
log('Saída: ${credential.output}');
log('Mensagem: ${credential.message}');
log('---');
await _auth(credential.output, $, throwsException);
}
@ -156,11 +156,11 @@ class AuthenticationTest {
await $.pumpWidgetAndSettle(const App());
for (var credential in credentials) {
print('Função: ${credential.functionName}');
print('Entradas: ${credential.inputs}');
print('Saída: ${credential.output}');
print('Mensagem: ${credential.message}');
print('---');
log('Função: ${credential.functionName}');
log('Entradas: ${credential.inputs}');
log('Saída: ${credential.output}');
log('Mensagem: ${credential.message}');
log('---');
await _navigateToSignUp($);
await _auth(credential.output, $, throwsException);
@ -255,10 +255,3 @@ Future<void> _submit(
_navigateBackUsingSystemGesture();
}
}
String _generateRandomString(int length) {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
final rand = Random();
return List.generate(length, (index) => chars[rand.nextInt(chars.length)])
.join();
}

View File

@ -68,8 +68,8 @@ class MenuTest {
route = entry.key;
title = entry.value;
print('route: $route');
print('title: $title');
log('route: $route');
log('title: $title');
if (route == '/petsPage') continue;
if (route == '/fastPassPage') continue;
@ -326,7 +326,6 @@ class MenuTest {
final Key? widgetKey = entry.key;
expect(widgetKey, isNotNull);
print('WIDGETKEY = $widgetKey');
if (widgetKey == ValueKey<String>('FRE-HUB-FASTPASS')) continue;
if (widgetKey == ValueKey<String>('FRE-HUB-QRCODE')) continue;
if (widgetKey == ValueKey<String>('FRE-HUB-RESERVATIONS')) continue;

View File

@ -25,7 +25,7 @@ Future<void> _loggedWithMultiLocalsAccount(
.set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO');
await PhpGroup //
await FreAccessWSGlobal //
.resopndeVinculo
.call(tarefa: 'A');
await LicenseRepositoryImpl() //
@ -58,7 +58,7 @@ Future<void> _loggedWithSomeoneLocalAccount(
.set(ProfileStorageKey.ownerUUID.key, '7');
await StorageHelper() //
.set(ProfileStorageKey.clientName.key, 'FRE ACCESS DEMO');
await PhpGroup //
await FreAccessWSGlobal //
.resopndeVinculo
.call(tarefa: 'A');
await LicenseRepositoryImpl() //

View File

@ -33,7 +33,7 @@ class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
@override
Widget build(BuildContext context) {
double limitedInputTextSize = LimitedFontSizeUtil.getInputFontSize(context);
bool _isLoading = false;
bool isLoading = false;
return Builder(
builder: (context) {
@ -72,7 +72,7 @@ class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
child: GestureDetector(
onTap: () async {
setState(() {
_isLoading = true;
isLoading = true;
});
final selectedMedia =
await selectMediaWithSourceBottomSheet(
@ -120,7 +120,7 @@ class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
showUploadMessage(context, message);
} else {
setState(() {
_isLoading = false;
isLoading = false;
});
final message = FFLocalizations.of(context)
.getVariableText(
@ -131,7 +131,7 @@ class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
}
} else {
setState(() {
_isLoading = false;
isLoading = false;
});
}
},
@ -150,7 +150,7 @@ class _MediaUploadButtonUtilState extends State<MediaUploadButtonUtil> {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_isLoading
isLoading
? SizedBox(
width: 30.0,
height: 30.0,

View File

@ -14,6 +14,7 @@ import 'package:hub/shared/utils/log_util.dart';
import '/flutter_flow/flutter_flow_theme.dart';
// ignore: must_be_immutable
class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget {
BottomArrowLinkedLocalsComponentWidget({super.key, required this.response});
ApiCallResponse? response;
@ -76,7 +77,7 @@ class _BottomArrowLinkedLocalsComponentWidgetState
Future<ApiCallResponse?> _fetchLocals() async {
try {
setState(() => _loading = true);
widget.response = await PhpGroup.getLocalsCall.call();
widget.response = await FreAccessWSGlobal.getLocalsCall.call();
final bool isError = widget.response?.jsonBody['error'];
if (isError) {
@ -148,7 +149,8 @@ class _BottomArrowLinkedLocalsComponentWidgetState
Future<dynamic> _fetchResponseLink(String status, String cliID) async {
try {
await StorageHelper().set(ProfileStorageKey.clientUUID.key, cliID);
var response = await PhpGroup.resopndeVinculo.call(tarefa: status);
var response =
await FreAccessWSGlobal.resopndeVinculo.call(tarefa: status);
if (response.jsonBody['error'] == false) {
return {
@ -204,7 +206,6 @@ class _BottomArrowLinkedLocalsComponentWidgetState
}
Widget _item(BuildContext context, dynamic local) {
log('local: ${local['CLI_NOME']}');
return CardItemTemplateComponentWidget(
key: ValueKey<String>(local['CLI_NOME']),
imagePath: _imagePath(local),

View File

@ -781,7 +781,7 @@ class _ScheduleVisitDetailWidgetState extends State<ScheduleVisitDetailWidget> {
IconButton(
onPressed: () async {
_model.postScheduleVisit =
await PhpGroup.postScheduleVisitCall.call(
await FreAccessWSGlobal.postScheduleVisitCall.call(
devDesc: widget.visitObsStr,
idVisitante: widget.visitorStrList,
dtInicio:
@ -793,13 +793,14 @@ class _ScheduleVisitDetailWidgetState extends State<ScheduleVisitDetailWidget> {
obs: widget.visitObsStr,
);
if (PhpGroup.postScheduleVisitCall.error(
if (FreAccessWSGlobal.postScheduleVisitCall.error(
(_model.postScheduleVisit?.jsonBody ?? ''),
) ==
false) {
context.pop();
} else {
final String? msg = PhpGroup.postScheduleVisitCall.errorMsg(
final String? msg =
FreAccessWSGlobal.postScheduleVisitCall.errorMsg(
(_model.postScheduleVisit?.jsonBody ?? ''),
);
await DialogUtil.error(context, msg!)

View File

@ -75,7 +75,7 @@ class _UpArrowLinkedLocalsComponentWidgetState
),
),
child: FutureBuilder<ApiCallResponse>(
future: PhpGroup.getLocalsCall.call(),
future: FreAccessWSGlobal.getLocalsCall.call(),
builder: (context, snapshot) {
// Customize what your widget looks like when it's loading.
if (!snapshot.hasData) {
@ -94,7 +94,7 @@ class _UpArrowLinkedLocalsComponentWidgetState
return Builder(
builder: (context) {
final eachLocals = (PhpGroup.getLocalsCall
final eachLocals = (FreAccessWSGlobal.getLocalsCall
.locais(
gridViewGetLocalsResponse.jsonBody,
)

View File

@ -63,14 +63,14 @@ class AccessNotificationModalTemplateComponentModel
}) async {
ApiCallResponse? visitRequest;
visitRequest = await PhpGroup.respondeSolicitacaoCall.call(
visitRequest = await FreAccessWSGlobal.respondeSolicitacaoCall.call(
referencia: refUUID,
tarefa: actionValue,
resposta: responseValue,
idVisitante: vteUUID,
);
if (PhpGroup.respondeSolicitacaoCall.error(
if (FreAccessWSGlobal.respondeSolicitacaoCall.error(
(visitRequest.jsonBody ?? ''),
) ==
false) {

View File

@ -5,7 +5,6 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
import 'package:material_symbols_icons/symbols.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
@ -159,6 +158,7 @@ class _CardItemTemplateComponentWidgetState
}
Widget _generateImage() {
log('img: ${widget.imagePath ?? ''}');
// CachedNetworkImage.evictFromCache(widget.imagePath ?? '');
return ClipRRect(
borderRadius: BorderRadius.circular(20),

View File

@ -67,7 +67,9 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
// CachedNetworkImage.evictFromCache(widget.imagePath ?? '');
final double limitedBodyFontSize =
LimitedFontSizeUtil.getBodyFontSize(context);
return Container(
return Material(
type: MaterialType.transparency,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width,
maxHeight: MediaQuery.of(context).size.height,
@ -143,7 +145,8 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
fontWeight: FontWeight.bold,
color: FlutterFlowTheme.of(context).info,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
useGoogleFonts:
GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily,
),
@ -156,7 +159,8 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
.labelMediumFamily,
color: FlutterFlowTheme.of(context).info,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
useGoogleFonts:
GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily,
),
@ -179,7 +183,8 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
color: FlutterFlowTheme.of(context).info,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).labelMediumFamily,
FlutterFlowTheme.of(context)
.labelMediumFamily,
),
fontSize: limitedBodyFontSize,
),
@ -295,6 +300,7 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
],
),
),
),
);
}
}

View File

@ -60,7 +60,6 @@ class _MessageNotificationModalTemplateComponentWidgetState
@override
Widget build(BuildContext context) {
double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
double limitedSubHeaderFontSize =
LimitedFontSizeUtil.getSubHeaderFontSize(context);
return Container(

View File

@ -951,7 +951,8 @@ class _ScheduleProvisionalVisitPageWidgetState
? null
: () async {
try {
model.provVisitSchedule = await PhpGroup
model.provVisitSchedule =
await FreAccessWSGlobal
.postProvVisitSchedulingCall
.call(
data: DateFormat('dd/MM/yyyy HH:mm:ss')
@ -964,7 +965,8 @@ class _ScheduleProvisionalVisitPageWidgetState
nome: model.personNameTextController.text,
proID: model.ownerUUID,
);
if (PhpGroup.postProvVisitSchedulingCall
if (FreAccessWSGlobal
.postProvVisitSchedulingCall
.error((model.provVisitSchedule
?.jsonBody ??
'')) ==
@ -982,7 +984,7 @@ class _ScheduleProvisionalVisitPageWidgetState
model.notesTextController?.clear();
});
} else {
var message = PhpGroup
var message = FreAccessWSGlobal
.postProvVisitSchedulingCall
.msg((model.provVisitSchedule
?.jsonBody ??

View File

@ -46,7 +46,7 @@ class RegisiterVistorTemplateComponentModel
Future<bool> getVisitanteByDocument(
String document, BuildContext context) async {
final response = await PhpGroup.getVisitorByDocCall.call(
final response = await FreAccessWSGlobal.getVisitorByDocCall.call(
documento: document,
);

View File

@ -15,7 +15,6 @@ import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/flutter_flow_widgets.dart';
import '/flutter_flow/form_field_controller.dart';
import '/flutter_flow/upload_data.dart';
import 'regisiter_vistor_template_component_model.dart';
export 'regisiter_vistor_template_component_model.dart';
@ -43,10 +42,6 @@ class _RegisiterVistorTemplateComponentWidgetState
final _formKey = GlobalKey<FormState>();
void _resetForm() {
_formKey.currentState?.reset();
}
@override
void initState() {
super.initState();
@ -766,7 +761,7 @@ class _RegisiterVistorTemplateComponentWidgetState
_model.uploadedLocalFile,
);
_model.scheduleVisitor =
await PhpGroup.postScheduleVisitorCall
await FreAccessWSGlobal.postScheduleVisitorCall
.call(
documento: _model.textController2.text,
nome: _model.textController1.text,
@ -781,7 +776,7 @@ class _RegisiterVistorTemplateComponentWidgetState
.onError((e, s) async {
return await DialogUtil.errorDefault(context);
});
if (PhpGroup.postScheduleVisitorCall.error(
if (FreAccessWSGlobal.postScheduleVisitorCall.error(
(_model.scheduleVisitor?.jsonBody ?? ''),
) ==
false) {
@ -828,8 +823,8 @@ class _RegisiterVistorTemplateComponentWidgetState
} else {
return await DialogUtil.error(
context,
PhpGroup.postScheduleVisitorCall.errorMsg(
_model
FreAccessWSGlobal.postScheduleVisitorCall
.errorMsg(_model
.scheduleVisitor?.jsonBody) ==
null
? FFLocalizations.of(context)
@ -838,7 +833,8 @@ class _RegisiterVistorTemplateComponentWidgetState
'Erro ao se conectar com o servidor',
enText: 'Error connecting to server',
)
: PhpGroup.postScheduleVisitorCall
: FreAccessWSGlobal
.postScheduleVisitorCall
.errorMsg(
_model.scheduleVisitor?.jsonBody)
.toString());

View File

@ -107,9 +107,9 @@ class _SignUpTemplateComponentWidgetState
@override
Widget build(BuildContext context) {
final MediaQueryData mediaQuery = MediaQuery.of(context);
final double screenWidth = mediaQuery.size.width;
final double screenHeight = mediaQuery.size.height;
// final MediaQueryData mediaQuery = MediaQuery.of(context);
// final double screenWidth = mediaQuery.size.width;
// final double screenHeight = mediaQuery.size.height;
double limitedHeaderFontSize =
LimitedFontSizeUtil.getHeaderFontSize(context);

View File

@ -818,11 +818,11 @@ class _ViewVisitDetailWidgetState extends State<ViewVisitDetailWidget> {
),
onPressed: () async {
_model.deleteVisit =
await PhpGroup.deleteVisitCall.call(
await FreAccessWSGlobal.deleteVisitCall.call(
idVisita: widget.visitIdStr,
);
if (PhpGroup.deleteVisitCall.error(
if (FreAccessWSGlobal.deleteVisitCall.error(
(_model.deleteVisit?.jsonBody ?? ''),
) ==
false) {

View File

@ -406,23 +406,23 @@ class _VisitorSearchModalTemplateComponentWidgetState
_model.textController?.selection =
TextSelection.collapsed(offset: _model.textController!.text.length);
});
_model.getVisitorByDoc = await PhpGroup.getVisitorByDocCall.call(
_model.getVisitorByDoc = await FreAccessWSGlobal.getVisitorByDocCall.call(
documento: _model.textController.text.replaceFirst(RegExp(r'^0+'), ''));
if (PhpGroup.getVisitorByDocCall
if (FreAccessWSGlobal.getVisitorByDocCall
.vistanteId((_model.getVisitorByDoc?.jsonBody ?? '')) !=
'0' &&
PhpGroup.getVisitorByDocCall
FreAccessWSGlobal.getVisitorByDocCall
.error((_model.getVisitorByDoc?.jsonBody ?? '')) ==
false &&
PhpGroup.getVisitorByDocCall
FreAccessWSGlobal.getVisitorByDocCall
.vistanteId((_model.getVisitorByDoc?.jsonBody ?? '')) !=
null) {
String newDoc =
_model.textController.text.replaceFirst(RegExp(r'^0+'), '');
bool existDoc = _model.docs.contains(newDoc);
if (existDoc == false) {
_model.addToVisitors(PhpGroup.getVisitorByDocCall
_model.addToVisitors(FreAccessWSGlobal.getVisitorByDocCall
.visitante((_model.getVisitorByDoc?.jsonBody ?? '')));
safeSetState(() {});
_model.addToDocs(

View File

@ -14,7 +14,7 @@ import '../../../flutter_flow/random_data_util.dart';
class AuthenticationService {
static Future<void> login(BuildContext context) async {
try {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall;
final response = await callback.call();
if (response.jsonBody['error']) {
@ -46,7 +46,7 @@ class AuthenticationService {
}) async {
try {
final ApiCallResponse? response;
final LoginCall callback = PhpGroup.loginCall;
final LoginCall callback = FreAccessWSGlobal.loginCall;
String deviceDescription = randomString(10, 10, true, false, false);
await StorageHelper()
.set(SecureStorageKey.deviceDescription.value, deviceDescription);
@ -111,7 +111,7 @@ class AuthenticationService {
if ((email != null && email != '') &&
(passwd != null && passwd != '' && passwd.length > 7) &&
(name != null && name != '')) {
response = await PhpGroup.registerCall.call(
response = await FreAccessWSGlobal.registerCall.call(
name: name,
password: passwd,
email: email,
@ -137,7 +137,7 @@ class AuthenticationService {
}
static Future<void> signOut(BuildContext context) async {
await PhpGroup.unregisterDevice.call();
await FreAccessWSGlobal.unregisterDevice.call();
final Map<String, dynamic> extra = <String, dynamic>{
kTransitionInfoKey: const TransitionInfo(
hasTransition: true,
@ -158,7 +158,7 @@ class AuthenticationService {
static Future<bool> forgotPassword(BuildContext context, String email) async {
try {
final ApiCallResponse? response;
final ForgotPasswordCall callback = PhpGroup.forgotPasswordCall;
final ForgotPasswordCall callback = FreAccessWSGlobal.forgotPasswordCall;
final String message = FFLocalizations.of(context).getVariableText(
enText: "Send E-mail Successful!",
ptText: "E-mail Enviado com Sucesso!");
@ -183,7 +183,8 @@ class AuthenticationService {
static Future<bool> changePassword(
BuildContext context, String email, String password, String token) async {
try {
final ApiCallResponse response = await PhpGroup.changePasswordCall
final ApiCallResponse response = await FreAccessWSGlobal
.changePasswordCall
.call(email: email, psswd: password, token: token);
if (response.jsonBody['error'] == false) {
@ -209,7 +210,7 @@ class AuthenticationService {
static Future<void> deleteAccount(BuildContext context) async {
String content;
try {
await PhpGroup.deleteAccount.call().then((value) async {
await FreAccessWSGlobal.deleteAccount.call().then((value) async {
if (value.jsonBody['error'] == false) {
content = FFLocalizations.of(context).getVariableText(
enText: 'Account deleted successfully',

View File

@ -1,13 +1,17 @@
// ignore_for_file: unused_element
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:hub/features/documents/documents.dart' as doc;
import 'package:hub/features/notification/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:hub/shared/utils/validator_util.dart';
import 'package:hub/shared/widgets.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'api_manager.dart';
@ -22,7 +26,9 @@ abstract class Api {
GetLicense getLicense = GetLicense();
}
class PhpGroup extends Api {
abstract interface class Endpoint {}
class FreAccessWSGlobal extends Api {
static String getBaseUrl() => 'https://freaccess.com.br/freaccess';
static Map<String, String> headers = {};
static LoginCall loginCall = LoginCall();
@ -73,6 +79,9 @@ class PhpGroup extends Api {
static UpdateVehicle updateVehicle = UpdateVehicle();
static DeleteVehicle deleteVehicle = DeleteVehicle();
static CancelDeleteVehicle cancelDelete = CancelDeleteVehicle();
static GetPDF getPDF = GetPDF();
static GetCategories getCategories = GetCategories();
static GetDocuments getDocuments = GetDocuments();
}
class CancelDeleteVehicle {
@ -82,7 +91,7 @@ class CancelDeleteVehicle {
required final String model,
required final String color,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -124,7 +133,7 @@ class DeleteVehicle {
required final String model,
required final String color,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -167,7 +176,7 @@ class RegisterVehicle {
final String? color,
final String? model,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -211,7 +220,7 @@ class UpdateVehicle {
final String? color,
final String? model,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -246,11 +255,115 @@ class UpdateVehicle {
alwaysAllowBody: false,
);
}
static GetCategories getCategories = GetCategories();
static GetDocuments getDocuments = GetDocuments();
}
class GetProvSchedules {
class GetPDF extends Endpoint {
Future<Uri> call(final int id) async {
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
final String cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
const String atividade = 'visualizarDocumento';
const String callname = 'getDocumento.php';
return Uri.parse(
"$baseUrl/$callname?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=$atividade&documentId=$id");
}
}
class GetCategories extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
final String cliID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
const String atividade = 'listaCategoriasDocumentos';
const String pageSize = '10';
// final bool isFiltered = filter != '' && filter != '.*';
return await ApiManager.instance.makeApiCall(
callName: 'listaCategoriasDocumentos',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
params: {
// if (isFiltered) 'filter': filter,
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'pageSize': pageSize,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
}
class GetDocuments extends Endpoint {
@override
Future<ApiCallResponse> call(
final dynamic page,
final Query query,
) async {
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
final String cliID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
const String atividade = 'listaDocumentos';
const String pageSize = '10';
// final bool isFiltered = filter != '' && filter != '.*';
// final isCategory = !category;
// final isDescription = !desc.isNullOrEmpty;
return await ApiManager.instance.makeApiCall(
callName: 'listaDocumentos',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
params: {
// if (isFiltered) 'filter': filter,
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'page': page.toString(),
'pageSize': pageSize,
if (query is doc.Category) 'categoryId': query.id,
if (query is doc.Document) 'searh': query.description,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
}
class GetProvSchedules extends Endpoint {
@override
Future<ApiCallResponse> call(final String page, final String status) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -286,9 +399,10 @@ class GetProvSchedules {
}
}
class GetOpenedVisits {
class GetOpenedVisits extends Endpoint {
@override
Future<ApiCallResponse> call(final String page) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -321,9 +435,10 @@ class GetOpenedVisits {
}
}
class GetResidentsByProperty {
class GetResidentsByProperty extends Endpoint {
@override
Future<ApiCallResponse> call(final String page) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
await StorageHelper().get(ProfileStorageKey.devUUID.key) ?? '';
final String userUUID =
@ -355,9 +470,10 @@ class GetResidentsByProperty {
}
}
class GetVehiclesByProperty {
class GetVehiclesByProperty extends Endpoint {
@override
Future<ApiCallResponse> call(final String page) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -391,9 +507,10 @@ class GetVehiclesByProperty {
static GetLicense getLicense = GetLicense();
}
class GetLicense {
class GetLicense extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -425,9 +542,10 @@ class GetLicense {
}
}
class UnregisterDevice {
class UnregisterDevice extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -455,9 +573,10 @@ class UnregisterDevice {
}
}
class DeletePet {
class DeletePet extends Endpoint {
@override
Future<ApiCallResponse> call({final int? petID = 0}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -491,7 +610,8 @@ class DeletePet {
}
}
class UpdatePet {
class UpdatePet extends Endpoint {
@override
Future<ApiCallResponse> call({
final int? petID,
final String? image,
@ -504,7 +624,7 @@ class UpdatePet {
final String? size,
final String? notes,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -550,12 +670,13 @@ class UpdatePet {
}
}
class GetPets {
class GetPets extends Endpoint {
@override
Future<ApiCallResponse> call({
final int? page,
final int? pageSize,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -590,9 +711,10 @@ class GetPets {
}
}
class GetPetPhoto {
class GetPetPhoto extends Endpoint {
@override
Future<ApiCallResponse> call({final int? petId}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -626,7 +748,8 @@ class GetPetPhoto {
}
}
class RegisterPet {
class RegisterPet extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? image,
final String? name,
@ -638,7 +761,7 @@ class RegisterPet {
final String? size,
final String? notes,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -683,7 +806,8 @@ class RegisterPet {
}
}
class BuscaEnconcomendas {
class BuscaEnconcomendas extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? page,
final String? pageSize,
@ -698,7 +822,7 @@ class BuscaEnconcomendas {
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
const String atividade = 'getEncomendas';
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
return await ApiManager.instance.makeApiCall(
callName: 'getEncomendas',
@ -727,7 +851,8 @@ class BuscaEnconcomendas {
}
}
class CancelaVisita {
class CancelaVisita extends Endpoint {
@override
Future<ApiCallResponse> call({
final int? idDestino,
final int? idVisita,
@ -735,7 +860,7 @@ class CancelaVisita {
final String? UsuEmail,
final String? DevDesc,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -772,14 +897,15 @@ class CancelaVisita {
}
}
class DeleteAccount {
class DeleteAccount extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
return await ApiManager.instance.makeApiCall(
callName: 'deleteAccount',
apiUrl: '$baseUrl/deleteAccount.php',
@ -802,11 +928,12 @@ class DeleteAccount {
}
}
class ChangePanic {
class ChangePanic extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? newSenhaPanico,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -841,11 +968,12 @@ class ChangePanic {
}
}
class ChangePass {
class ChangePass extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? newSenha,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -880,11 +1008,12 @@ class ChangePass {
}
}
class RespondeVinculo {
class RespondeVinculo extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? tarefa,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -917,11 +1046,12 @@ class RespondeVinculo {
}
}
class ChangeNotifica {
class ChangeNotifica extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? notifica,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -956,9 +1086,10 @@ class ChangeNotifica {
}
}
class UpdateIDE {
class UpdateIDE extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -995,9 +1126,10 @@ class UpdateIDE {
}
}
class UpdToken {
class UpdToken extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1028,9 +1160,10 @@ class UpdToken {
}
}
class LoginCall {
class LoginCall extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String email =
@ -1078,7 +1211,8 @@ class LoginCall {
}
}
class RegisterCall {
class RegisterCall extends Endpoint {
@override
Future<ApiCallResponse> call({
required final String name,
required final String email,
@ -1088,7 +1222,7 @@ class RegisterCall {
required final String tipo,
required final String descricao,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
return await ApiManager.instance.makeApiCall(
callName: 'register',
@ -1117,13 +1251,14 @@ class RegisterCall {
}
}
class ChangePasswordCall {
class ChangePasswordCall extends Endpoint {
@override
Future<ApiCallResponse> call({
required final String email,
required final String token,
required final String psswd,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
final String userUUID =
@ -1157,11 +1292,12 @@ class ChangePasswordCall {
}
}
class ForgotPasswordCall {
class ForgotPasswordCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? email,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
return await ApiManager.instance.makeApiCall(
callName: 'forgotPassword',
@ -1184,9 +1320,10 @@ class ForgotPasswordCall {
}
}
class GetLocalsCall {
class GetLocalsCall extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
await StorageHelper().get(ProfileStorageKey.devUUID.key) ?? '';
@ -1223,14 +1360,15 @@ class GetLocalsCall {
) as List?;
}
class PostScheduleVisitorCall {
class PostScheduleVisitorCall extends Endpoint {
@override
Future<ApiCallResponse> call({
required final String documento,
required final String nome,
required final String tipo,
required final String foto,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1277,7 +1415,8 @@ class PostScheduleVisitorCall {
));
}
class PostScheduleVisitCall {
class PostScheduleVisitCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? devDesc,
final String? idVisitante,
@ -1288,7 +1427,7 @@ class PostScheduleVisitCall {
final int? idNAC,
final String? obs,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1339,13 +1478,14 @@ class PostScheduleVisitCall {
));
}
class GetScheduleVisitCall {
class GetScheduleVisitCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final int? pageSize,
final int? pageNumber,
final String? chaveBusca,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1620,9 +1760,10 @@ class GetScheduleVisitCall {
));
}
class GetDadosCall {
class GetDadosCall extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1866,11 +2007,12 @@ class GetDadosCall {
));
}
class GetVisitorByDocCall {
class GetVisitorByDocCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? documento,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1922,12 +2064,13 @@ class GetVisitorByDocCall {
));
}
class GetFotoVisitanteCall {
class GetFotoVisitanteCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? documento,
final String? tipo,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -1962,14 +2105,15 @@ class GetFotoVisitanteCall {
}
}
class PostProvVisitSchedulingCall {
class PostProvVisitSchedulingCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? data,
final String? motivo,
final String? nome,
final String? proID,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2016,12 +2160,13 @@ class PostProvVisitSchedulingCall {
));
}
class GetVisitsCall {
class GetVisitsCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final int? pageSize,
final int? pageNumber,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2283,11 +2428,12 @@ class GetVisitsCall {
.toList();
}
class DeleteVisitCall {
class DeleteVisitCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? idVisita,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2331,9 +2477,10 @@ class DeleteVisitCall {
));
}
class GetPessoasLocalCall {
class GetPessoasLocalCall extends Endpoint {
@override
Future<ApiCallResponse> call() async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2396,14 +2543,15 @@ class GetPessoasLocalCall {
.toList();
}
class RespondeSolicitacaoCall {
class RespondeSolicitacaoCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? referencia,
final String? tarefa,
final String? resposta,
final String? idVisitante,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2450,13 +2598,14 @@ class RespondeSolicitacaoCall {
));
}
class GetAccessCall {
class GetAccessCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? pageSize,
final String? pageNumber,
final String? pesTipo,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
@ -2704,9 +2853,10 @@ class GetAccessCall {
.toList();
}
class GetLiberationsCall {
class GetLiberationsCall extends Endpoint {
@override
Stream<ApiCallResponse> call() {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final StreamController<ApiCallResponse> controller = StreamController();
Future.microtask(() async {
@ -2897,13 +3047,14 @@ class GetLiberationsCall {
.toList();
}
class GetMessagesCall {
class GetMessagesCall extends Endpoint {
@override
Future<ApiCallResponse> call({
final String? pageSize,
final String? pageNumber,
final String? tipoDestino,
}) async {
final String baseUrl = PhpGroup.getBaseUrl();
final String baseUrl = FreAccessWSGlobal.getBaseUrl();
final String devUUID =
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';

View File

@ -1,6 +1,5 @@
import 'dart:convert';
import 'dart:core';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';

View File

@ -0,0 +1,788 @@
import 'dart:developer';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/shared/extensions.dart';
import 'package:hub/shared/utils.dart';
import 'package:hub/shared/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_rx_bloc/flutter_rx_bloc.dart';
import 'package:rx_bloc/rx_bloc.dart';
import 'package:rxdart/rxdart.dart' as rx;
part 'documents.rxb.g.dart';
/// -----------------------------------------------
/// [TypeDefs] -----------------------------------
/// -----------------------------------------------
typedef DocumentKey = GlobalKey<DocumentPageState>;
/// -----------------------------------------------
/// [Extensions] ---------------------------------
/// -----------------------------------------------
extension ExplicitRxdartStartWithExtension<T> on Stream<T?> {
Stream<T?> rxdartStartWith(T? value) =>
rx.StartWithExtension(this).startWith(value);
}
/// -----------------------------------------------
/// [Pages] ---------------------------------------
/// -----------------------------------------------
class DocumentPage extends StatefulPage {
const DocumentPage({super.key});
@override
State<DocumentPage> createState() => DocumentPageState();
}
class DocumentPageState extends PageState<DocumentPage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return RxBlocMultiBuilder2<DocumentPageBlocType, bool, (Document, Uri)?>(
state1: (bloc) => bloc.states.isDocumentSelected,
state2: (bloc) => bloc.states.currentDocument,
bloc: context.read<DocumentPageBloc>(),
builder: (context, isSelect, current, bloc) {
if (isSelect.hasData && isSelect.data!) {
return _buildDocumentViewScreen(current, bloc);
} else {
return _buildDocumentManagerScreen();
}
},
);
}
Widget _buildDocumentManagerScreen() {
final model = context.read<DocumentPageBloc>().model;
return DocumentManagerScreen(
model: model,
state: this,
);
}
Widget _buildDocumentViewScreen(
AsyncSnapshot<(Document, Uri)?> snapshot, DocumentPageBlocType bloc) {
if (snapshot.hasData) {
return DocumentViewerScreen(
doc: snapshot.data!,
bloc: bloc,
);
} else {
return const Center(child: CircularProgressIndicator());
}
}
}
/// -----------------------------------------------
/// [Screens] ------------------------------------
/// -----------------------------------------------
class DocumentManagerScreen extends StatelessScreen {
final DocumentModel model;
final DocumentPageState state;
const DocumentManagerScreen({
super.key,
required this.model,
required this.state,
});
@override
Widget build(BuildContext context) {
final String title = FFLocalizations.of(context).getVariableText(
enText: 'Documents',
ptText: 'Documentos',
);
final theme = FlutterFlowTheme.of(context);
action() => Navigator.pop(context);
return Scaffold(
backgroundColor: theme.primaryBackground,
appBar: buildAppBar(title, context, action),
body: buildBody(context),
);
}
Widget buildBody(BuildContext context) {
const SizedBox space = SizedBox(height: 10);
final controller = EnhancedListViewController(
headerBuilder: model.itemHeaderBuilder<SearchField>,
bodyBuilder: model.itemBodyBuilder<Document>,
footerBuilder: model.itemFooterBuilder<Category>,
);
final repository = EnhancedListViewRepository(
fetchHeader: model.generateHeaderItems<SearchField>,
fetchBody: model.generateBodyItems<Document, Query>,
fetchFooter: model.generateFooterItems<Category>,
);
return Column(
children: [
Expanded(
child: EnhancedListView<Document, SearchField, Category, Query>(
key: model.enhancedListViewKey,
controller: controller,
repository: repository,
),
),
] //
.addToStart(space)
.addToEnd(space),
);
}
}
class DocumentViewerScreen extends StatefulScreen {
const DocumentViewerScreen({
super.key,
required this.doc,
required this.bloc,
});
final (Document, Uri) doc;
final DocumentPageBlocType bloc;
@override
ScreenState<DocumentViewerScreen> createState() =>
_DocumentViewerScreenState();
}
class _DocumentViewerScreenState extends ScreenState<DocumentViewerScreen> {
@override
void initState() {
super.initState();
}
backAction() => widget.bloc.events.unselectDocument();
@override
Widget build(BuildContext context) {
final String title = widget.doc.$1.description;
final theme = FlutterFlowTheme.of(context);
final locale = FFLocalizations.of(context);
infoAction() => DetailsComponentWidget(
buttons: [],
statusHashMap: [
Map<String, Color>.from({
widget.doc.$1.description: widget.doc.$1.category.color,
})
],
labelsHashMap: Map<String, String>.from({
locale.getVariableText(
enText: 'Description',
ptText: 'Descrição',
): widget.doc.$1.description,
locale.getVariableText(
enText: 'Category',
ptText: 'Categoria',
): widget.doc.$1.category.title,
if (widget.doc.$1.person.isNotEmpty)
locale.getVariableText(
enText: 'Person',
ptText: 'Pessoa',
): widget.doc.$1.person,
if (widget.doc.$1.property.isNotEmpty)
locale.getVariableText(
enText: 'Property',
ptText: 'Propriedade',
): widget.doc.$1.property,
locale.getVariableText(
enText: 'Created At',
ptText: 'Criado em',
): ValidatorUtil.toLocalDateTime(
'yyyy-MM-dd', widget.doc.$1.createdAt),
locale.getVariableText(
enText: 'Updated At',
ptText: 'Atualizado em',
): ValidatorUtil.toLocalDateTime(
'yyyy-MM-dd', widget.doc.$1.updatedAt),
}),
);
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) => backAction(),
child: Scaffold(
backgroundColor: theme.primaryBackground,
appBar: buildAppBar(title, context, backAction, infoAction),
body: buildBody(context),
),
);
}
Widget buildBody(BuildContext context) {
return ReadView(
title: widget.doc.$1.description,
url: widget.doc.$2.toString(),
onError: backAction,
);
}
}
/// -----------------------------------------------
/// [Models] --------------------------------------
/// -----------------------------------------------
class DocumentModel extends FlutterFlowModel<DocumentPage> {
final DocumentPageBlocType bloc;
DocumentModel(this.bloc);
late EnhancedListViewKey<Document, SearchField, Category, Query>
enhancedListViewKey;
late EnhancedCarouselViewKey<Category> carouselViewKey;
late DocumentKey vehicleScreenViewer;
/// ------------
@override
void initState(BuildContext context) {
enhancedListViewKey =
EnhancedListViewKey<Document, SearchField, Category, Query>();
carouselViewKey = EnhancedCarouselViewKey<Category>();
vehicleScreenViewer = DocumentKey();
}
@override
void dispose() {
enhancedListViewKey.currentState?.dispose();
carouselViewKey.currentState?.dispose();
vehicleScreenViewer.currentState?.dispose();
}
/// ------------
/// [Body]
void onView(Document document, BuildContext context) async {
bloc.events.selectDocument(document);
}
Widget itemBodyBuilder<T extends Document>(
BuildContext context, T item, int index) {
log('ItemBuilder -> $index');
return DocumentComponent(
document: item,
onPressed: onView,
);
}
Future<List<T?>> generateBodyItems<T extends Document, Q extends Query>(
int pageKey, int pageSize, Q query) async {
final List<T?> error = [null];
log('Query: ${query is Document}');
final GetDocuments getDocuments = FreAccessWSGlobal.getDocuments;
final ApiCallResponse newItems = await getDocuments.call(pageKey, query);
if (newItems.jsonBody == null) return error;
if (newItems.jsonBody['error'] == true) return error;
final List<dynamic> list = newItems.jsonBody['value']['list'];
late final List<Document> docs = [];
for (var item in list) {
final String description = item['description'];
final String type = item['type'];
final String category = item['category']['description'];
final String color = item['category']['color'];
final String person = item['person'] ?? '';
final String property = item['property'] ?? '';
final String createdAt = item['createdAt'];
final String updatedAt = item['updatedAt'];
final int categoryId = item['category']['id'];
final int documentId = item['id'];
final doc = Document(
id: documentId,
description: description,
type: type,
category: Category(
id: categoryId,
color: color.toColor(),
title: category,
),
person: person,
property: property,
createdAt: createdAt,
updatedAt: updatedAt,
);
docs.add(doc);
}
return docs as List<T?>;
}
/// [Footer]
Widget itemFooterBuilder<T extends Category>(
Future<List<T?>> Function() fetchData) =>
Builder(builder: (context) {
CategoryComponent categoryItemBuilder<T>(T? item, bool isSelected) {
return CategoryComponent(
category: item! as Category, isSelected: isSelected);
}
return EnhancedCarouselView<T>(
key: carouselViewKey,
dataProvider: fetchData,
itemBuilder: categoryItemBuilder,
filter: filterByCategory<T>,
showIndicator: true,
);
});
Future<List<T?>> generateFooterItems<T extends Category>() async {
final List<T?> error = [null];
final GetCategories getCategories = FreAccessWSGlobal.getCategories;
final ApiCallResponse newItems = await getCategories.call();
if (newItems.jsonBody['error'] == true) return error;
if (newItems.jsonBody == null) return error;
final list = newItems.jsonBody['value'] as List<dynamic>;
late final List<Category> cats = [];
for (var item in list) {
final String color = item['color'];
final String title = item['description'];
final int id = item['id'];
final cat = Category(
id: id,
color: color.toColor(),
title: title,
);
cats.add(cat);
}
return cats as List<T?>;
}
/// [Header]
Widget itemHeaderBuilder<T extends SearchField>(
Future<List<T?>> Function() generateHeaderItems) {
return Builder(builder: (context) {
final theme = FlutterFlowTheme.of(context);
final locale = FFLocalizations.of(context);
TextEditingController editingController = TextEditingController();
return TextFormField(
controller: editingController,
onChanged: (value) => EasyDebounce.debounce(
'_model.keyTextFieldTextController',
const Duration(milliseconds: 500),
() => filterBySearchBar(Document.from(value), context),
),
cursorColor: theme.primaryText,
showCursor: false,
cursorWidth: 2.0,
cursorRadius: Radius.circular(100),
style: TextStyle(
color: theme.primaryText,
fontSize: 16.0,
decorationColor: Colors.amber,
),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.search,
autocorrect: true,
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search, color: theme.primary),
labelText: locale.getVariableText(
ptText: 'Pesquisar',
enText: 'Search',
),
labelStyle: TextStyle(
color: theme.primaryText,
fontSize: 16.0,
),
hintText: locale.getVariableText(
ptText: 'Digite sua pesquisa',
enText: 'Enter your search',
),
hintStyle: TextStyle(
color: theme.accent2,
fontSize: 14.0,
),
filled: true,
fillColor: Colors.transparent,
helperStyle: TextStyle(
color: theme.primaryText,
decorationColor: theme.primaryText,
),
focusColor: theme.primaryText,
contentPadding:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
enabledBorder: UnderlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: theme.primaryText),
),
focusedBorder: UnderlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: theme.primaryText),
),
errorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: theme.primaryText),
),
focusedErrorBorder: UnderlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: theme.primaryText, width: 2.0),
),
),
);
});
}
Future<List<T?>> generateHeaderItems<T extends SearchField>() async {
final SearchField item = SearchField();
return [item] as List<T?>;
}
/// [Filter]
void filterBySearchBar<T>(T query, BuildContext context) {
final enhancedListViewState = enhancedListViewKey.currentState;
return enhancedListViewState?.filterBodyItems(query);
}
void filterByCategory<T>(T? query, BuildContext context) {
final enhancedListViewState = enhancedListViewKey.currentState;
enhancedListViewState?.filterBodyItems(query);
}
/// [Exception]
void onFetchError(Object e, StackTrace s) {
DialogUtil.errorDefault(vehicleScreenViewer.currentContext!);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículo", e, s);
}
}
/// -----------------------------------------------
/// [BLoCs] ---------------------------------------
/// -----------------------------------------------
abstract class DocumentPageBlocEvents {
void selectDocument(Document document);
void unselectDocument();
}
abstract class DocumentPageBlocStates {
Stream<bool> get isDocumentSelected;
Stream<(Document, Uri)?> get currentDocument;
}
@RxBloc()
class DocumentPageBloc extends $DocumentPageBloc {
late final DocumentModel model;
DocumentPageBloc(BuildContext context) {
model = DocumentModel(this);
model.initState(context);
}
@override
Stream<(Document, Uri)?> _mapToCurrentDocumentState() => _$selectDocumentEvent
.switchMap((event) async* {
final uri = await GetPDF().call(event.id);
yield (event, uri);
})
.rxdartStartWith(null)
.mergeWith([_$unselectDocumentEvent.map((_) => null)]);
@override
Stream<bool> _mapToIsDocumentSelectedState() => _mapToCurrentDocumentState()
.map((document) => document != null)
.rxdartStartWith(false)
.map((isSelected) => isSelected ?? false);
}
/// -----------------------------------------------
/// [Interfaces] ---------------------------------
/// -----------------------------------------------
abstract interface class Archive extends Entity {}
interface class SearchField extends Archive {
SearchField();
}
interface class Document extends Archive {
final int id;
final String description;
final String type;
final Category category;
final String person;
final String property;
String createdAt;
String updatedAt;
Document({
required this.id,
required this.description,
required this.type,
required this.category,
required this.person,
required this.property,
required this.createdAt,
required this.updatedAt,
});
factory Document.from(String desc) => Document(
id: 0,
description: desc,
type: '',
category: Category.fromDesc(''),
person: '',
property: '',
createdAt: '',
updatedAt: '',
);
}
interface class Category extends Archive {
final int id;
final Color color;
final String title;
Category({
required this.id,
required this.color,
required this.title,
});
factory Category.fromDesc(String desc) {
return Category(
id: 0,
color: Colors.transparent,
title: desc,
);
}
static Color isSelected() => Colors.black;
}
/// -----------------------------------------------
/// [Components] -------------------------------------
/// -----------------------------------------------
// ignore: must_be_immutable
class DocumentComponent extends StatelessComponent {
final Document document;
void Function(Document, BuildContext) onPressed;
DocumentComponent({
super.key,
required this.document,
required this.onPressed,
});
Tooltip _buildTooltip(String text, Color color, BuildContext context,
BoxConstraints constraints) {
final Color textColor = FlutterFlowTheme.of(context).info;
final area = (MediaQuery.of(context).size.height +
MediaQuery.of(context).size.width) /
2;
final double boxHeight = area * 0.033;
final double boxWidth = area * 0.19;
return Tooltip(
message: text,
child: Container(
width: boxWidth,
height: boxHeight,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: AutoText(
text,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: textColor,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
@override
Widget build(BuildContext context) {
final Color primaryText = FlutterFlowTheme.of(context).primaryText;
final Color primaryColor = FlutterFlowTheme.of(context).primary;
final TextStyle textStyleMajor = TextStyle(
color: primaryText,
fontWeight: FontWeight.bold,
);
final TextStyle textStyleMinor = TextStyle(
color: primaryText,
fontWeight: FontWeight.normal,
fontStyle: FontStyle.italic,
);
return Padding(
padding: const EdgeInsets.all(8),
child: LayoutBuilder(
builder: (context, constraints) {
final double boxHeight = constraints.maxHeight > 350
? MediaQuery.of(context).size.height * 0.07
: MediaQuery.of(context).size.height * 2;
final color = document.category.color;
// final color = FlutterFlowTheme.of(context).primary;
final icon = Icons.description;
const space = SizedBox(width: 10);
final description = document.description;
final title = document.category.title;
const double size = 20;
final date = ValidatorUtil.toLocalDateTime(
'yyyy-MM-dd',
document.updatedAt,
);
return Tooltip(
message: description,
child: InkWell(
onTap: () => onPressed(document, context),
enableFeedback: true,
overlayColor: WidgetStateProperty.all<Color>(primaryColor),
borderRadius: BorderRadius.circular(10),
child: SizedBox(
height: boxHeight,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
spacing: size,
children: [
// const SizedBox(width: 10),
Icon(icon, color: color),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Tooltip(
message: description,
child: AutoText(
description,
style: textStyleMajor,
overflow: TextOverflow.ellipsis,
),
),
Tooltip(
message: date,
child: AutoText(
date,
style: textStyleMinor,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
_buildTooltip(title, color, context, constraints),
],
),
),
// const SizedBox(width: 10),
Center(
child: Icon(
Icons.arrow_right,
color: primaryText,
),
),
] //
.addToStart(space)
.addToEnd(space),
),
),
),
);
},
),
);
}
DocumentComponent copyWith({
Document? document,
}) {
return DocumentComponent(
document: document ?? this.document,
onPressed: onPressed,
);
}
}
class CategoryComponent extends StatelessComponent {
final Category category;
final bool isSelected;
const CategoryComponent({
super.key,
required this.category,
this.isSelected = false,
});
@override
Widget build(BuildContext context) {
final backgroundTheme = FlutterFlowTheme.of(context).primaryBackground;
final textTheme = FlutterFlowTheme.of(context).primaryText;
final color = isSelected ? category.color.highlight : category.color;
return ColoredBox(
color: backgroundTheme,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
child: Icon(
Icons.folder,
color: Colors.white,
size: 40,
),
),
const SizedBox(height: 8),
Text(
category.title,
style: TextStyle(
color: textTheme,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
],
),
),
);
}
}

View File

@ -0,0 +1,70 @@
// dart format width=80
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// Generator: RxBlocGeneratorForAnnotation
// **************************************************************************
part of 'documents.dart';
/// Used as a contractor for the bloc, events and states classes
/// @nodoc
abstract class DocumentPageBlocType extends RxBlocTypeBase {
DocumentPageBlocEvents get events;
DocumentPageBlocStates get states;
}
/// [$DocumentPageBloc] extended by the [DocumentPageBloc]
/// @nodoc
abstract class $DocumentPageBloc extends RxBlocBase
implements
DocumentPageBlocEvents,
DocumentPageBlocStates,
DocumentPageBlocType {
final _compositeSubscription = rx.CompositeSubscription();
/// Тhe [Subject] where events sink to by calling [selectDocument]
final _$selectDocumentEvent = rx.PublishSubject<Document>();
/// Тhe [Subject] where events sink to by calling [unselectDocument]
final _$unselectDocumentEvent = rx.PublishSubject<void>();
/// The state of [isDocumentSelected] implemented in
/// [_mapToIsDocumentSelectedState]
late final Stream<bool> _isDocumentSelectedState =
_mapToIsDocumentSelectedState();
/// The state of [currentDocument] implemented in [_mapToCurrentDocumentState]
late final Stream<(Document, Uri)?> _currentDocumentState =
_mapToCurrentDocumentState();
@override
void selectDocument(Document document) => _$selectDocumentEvent.add(document);
@override
void unselectDocument() => _$unselectDocumentEvent.add(null);
@override
Stream<bool> get isDocumentSelected => _isDocumentSelectedState;
@override
Stream<(Document, Uri)?> get currentDocument => _currentDocumentState;
Stream<bool> _mapToIsDocumentSelectedState();
Stream<(Document, Uri)?> _mapToCurrentDocumentState();
@override
DocumentPageBlocEvents get events => this;
@override
DocumentPageBlocStates get states => this;
@override
void dispose() {
_$selectDocumentEvent.close();
_$unselectDocumentEvent.close();
_compositeSubscription.dispose();
super.dispose();
}
}

View File

@ -201,7 +201,7 @@ class _AccessHistoryState extends State<AccessHistoryScreen> {
Future<ApiCallResponse?> fetchAccessHistoryService() async {
try {
setState(() => _loading = true);
var response = await PhpGroup.getAccessCall.call(
var response = await FreAccessWSGlobal.getAccessCall.call(
pageSize: _pageSize.toString(),
pageNumber: _pageNumber.toString(),
pesTipo: _personType != 'E' && _personType != 'O' ? 'T' : _personType,

View File

@ -222,8 +222,8 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
Future<ApiCallResponse?> fetchHistoryService() async {
try {
setState(() => _loading = true);
var response =
await PhpGroup.getProvSchedules(_pageNumber.toString(), status);
var response = await FreAccessWSGlobal.getProvSchedules(
_pageNumber.toString(), status);
final List<dynamic> history =
response.jsonBody['agendamento']['value'] ?? [];
@ -350,6 +350,7 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
);
}
// ignore: unused_element
String _imageUrlAtomWidget(String document, String type) {
return valueOrDefault<String>(
"https://freaccess.com.br/freaccess/getImage.php?&cliID=&atividade=getFoto&Documento=$document&tipo=$type",
@ -404,6 +405,7 @@ class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
}
Map<String, Color> _getStatusMap(BuildContext context, dynamic json) {
// ignore: unused_local_variable
late Map<String, Color> statusColorMap;
log(DateTime.parse(json['AGP_DT_VISITA']).toString());
log(DateTime.now().toString());

View File

@ -187,6 +187,7 @@ class _AccessFilterState extends State<AccessFilter> {
);
}
// ignore: unused_element
void _updateSelection(String? value, String key) {
setState(() {
if (value == '.') {

View File

@ -1,6 +1,5 @@
import 'dart:developer';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@ -8,8 +7,6 @@ import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';

View File

@ -136,6 +136,7 @@ class DrawerWidget extends StatelessWidget {
);
}
// ignore: unused_element
Padding _buildSearchBar(BuildContext context, HomeState state) {
final theme = FlutterFlowTheme.of(context);
final errorColor = theme.error;

View File

@ -1,6 +1,5 @@
import 'dart:developer';
import 'package:hub/features/storage/constants/locals_constants.dart';
import 'package:hub/features/storage/index.dart';
import 'package:sqflite/sqflite.dart';
@ -75,7 +74,7 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource {
await DatabaseService.database
.delete(LocalsConstants.tableLocalsKeychain);
} catch (e, s) {
log('() => clearAll keychain: $e', stackTrace: s);
log('() => clearAll keychain: $e stackTrace: $s');
}
}
}

View File

@ -32,22 +32,15 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
@override
Future<void> linkLocal(BuildContext context) async {
try {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall;
var response = await callback.call();
final bool? isError = response.jsonBody['error'];
if (response.jsonBody == null) return;
final bool? isError = response.jsonBody['error'];
if (isError == true) {
LocalUtil.handleError(context, response.jsonBody['error_msg']);
return;
}
if (response.jsonBody == null) {
final String errorMsg = FFLocalizations.of(context).getVariableText(
enText: 'Verify your connection',
ptText: 'Verifique sua conexão',
);
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response));
return;
}
final List<dynamic> locals = response.jsonBody['locais'] ?? [];
final bool isEmpty = locals.isEmpty;
@ -70,9 +63,9 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
@override
Future<bool> processLocals(BuildContext context) async {
log('() => processLocals');
log('-> processLocals');
try {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall;
final ApiCallResponse response = await callback.call();
final bool? isError = response.jsonBody['error'];
@ -82,10 +75,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
return false;
}
if (response.jsonBody == null) {
final String errorMsg = FFLocalizations.of(context).getVariableText(
enText: 'Verify your connection',
ptText: 'Verifique sua conexão',
);
// final String errorMsg = FFLocalizations.of(context).getVariableText(
// enText: 'Verify your connection',
// ptText: 'Verifique sua conexão',
// );
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response));
return false;
}
@ -114,36 +107,35 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
} else if (isEnabled) {
return await LocalUtil.handleEnabled(context, locals[0]);
} else if (isUnselected) {
log('() => isUnselected');
log('-> isUnselected');
return await selectLocal(context, response);
} else if (isSelected) {
log('() => isSelected');
log('-> isSelected');
return await processProperty(context).then((v) async {
if (v == true) return await LicenseRepositoryImpl().updateLicense();
return v;
});
} else if (isAvailable) {
log('() => isAvailable');
log('-> isAvailable');
return await processProperty(context).then((v) async {
if (v == true) return await LicenseRepositoryImpl().updateLicense();
return v;
});
} else {
if (!isUnique && !isActive) log('() => not unique and not active');
if (!isUnique && isInactived) log('() => not unique and inactived');
if (!isUnique && isPending) log('() => not unique and pending');
if (!isUnique && isBlocked) log('() => not unique and blocked');
log('() => else');
if (!isUnique && !isActive) log('-> not unique and not active');
if (!isUnique && isInactived) log('-> not unique and inactived');
if (!isUnique && isPending) log('-> not unique and pending');
if (!isUnique && isBlocked) log('-> not unique and blocked');
log('-> else');
return await selectLocal(context, response);
}
} catch (e, s) {
log('() => stack: $s');
log('() => catch: $e', stackTrace: s);
log('-> catch: $e', stackTrace: s);
// return await selectLocal(context);
final String errorMsg = FFLocalizations.of(context).getVariableText(
enText: 'Error getting locals, verify your connection',
ptText: 'Erro ao obter locais, verifique sua conexão',
);
// final String errorMsg = FFLocalizations.of(context).getVariableText(
// enText: 'Error getting locals, verify your connection',
// ptText: 'Erro ao obter locais, verifique sua conexão',
// );
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null));
return false;
}
@ -163,25 +155,25 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
@override
Future<bool> processProperty(BuildContext context) async {
try {
final GetDadosCall callback = PhpGroup.getDadosCall;
final GetDadosCall callback = FreAccessWSGlobal.getDadosCall;
ApiCallResponse? response = await callback.call();
if (response.jsonBody == null) {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall;
response = await callback.call();
final String errorMsg = FFLocalizations.of(context).getVariableText(
enText: 'Verify your connection',
ptText: 'Verifique sua conexão',
);
// final String errorMsg = FFLocalizations.of(context).getVariableText(
// enText: 'Verify your connection',
// ptText: 'Verifique sua conexão',
// );
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response));
return false;
}
final bool? isError = response.jsonBody['error'];
if (isError == true) {
final GetLocalsCall callback = PhpGroup.getLocalsCall;
final GetLocalsCall callback = FreAccessWSGlobal.getLocalsCall;
response = await callback.call();
final String errorMsg =
response.jsonBody['error_msg'] ?? 'Local indisponível';
// final String errorMsg =
// response.jsonBody['error_msg'] ?? 'Local indisponível';
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response));
return false;
} else {
@ -189,11 +181,11 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
return true;
}
} catch (e, s) {
log('() => error processData: $e', stackTrace: s);
final String errorMsg = FFLocalizations.of(context).getVariableText(
enText: 'Error getting data, verify your connection',
ptText: 'Erro ao obter dados, verifique sua conexão',
);
log('-> error processData: $e', stackTrace: s);
// final String errorMsg = FFLocalizations.of(context).getVariableText(
// enText: 'Error getting data, verify your connection',
// ptText: 'Erro ao obter dados, verifique sua conexão',
// );
// await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null));
return false;
}
@ -231,8 +223,9 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource {
enText: 'Device unlinked successfully',
ptText: 'Dispositivo desvinculado com sucesso',
);
final bool status =
await PhpGroup.resopndeVinculo.call(tarefa: 'I').then((value) async {
final bool status = await FreAccessWSGlobal.resopndeVinculo
.call(tarefa: 'I')
.then((value) async {
if (value.jsonBody['error'] == false) {
await StorageHelper().set(ProfileStorageKey.clientName.key, '');
await StorageHelper().set(ProfileStorageKey.ownerName.key, '');

View File

@ -106,6 +106,7 @@ class LocalsRepositoryImpl implements LocalsRepository {
await DialogUtil.error(context, errorMsg);
}
// ignore: unused_element
Future<void> _notifyBlocs(BuildContext context) async {
context.read<LocalProfileBloc>().add(LocalProfileEvent());
context.read<MenuBloc>().add(MenuEvent());

View File

@ -52,7 +52,7 @@ class LocalUtil {
await StorageHelper()
.set(ProfileStorageKey.ownerName.key, locals[0]['CLU_OWNER_DSC']);
var response = await PhpGroup.resopndeVinculo.call(tarefa: 'A');
var response = await FreAccessWSGlobal.resopndeVinculo.call(tarefa: 'A');
if (response.jsonBody['error'] == true) {
await StorageHelper().set(ProfileStorageKey.clientUUID.key, '');
await StorageHelper().set(ProfileStorageKey.ownerUUID.key, '');

View File

@ -37,7 +37,8 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
}
Future<void> _onMenuEvent(MenuEvent event, Emitter<MenuState> emit) async {
await LicenseRemoteDataSourceImpl(PhpGroup()).waitForSaveCompletion();
await LicenseRemoteDataSourceImpl(FreAccessWSGlobal())
.waitForSaveCompletion();
final List<MenuItem?> newEntries =
await MenuRepositoryImpl().entries2Items(entries, item);

View File

@ -204,6 +204,16 @@ class MenuEntry implements BaseModule {
route: '/messageHistoryPage',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-DOCUMENT',
icon: Icons.description,
name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText(
ptText: 'Documentos',
enText: 'Documents',
),
route: '/documentPage',
types: [MenuEntryType.Home, MenuEntryType.Drawer],
),
MenuEntry(
key: 'FRE-HUB-ABOUT-PROPERTY',
icon: Icons.home,

View File

@ -17,7 +17,7 @@ class LicenseRepositoryImpl implements LicenseRepository {
LicenseRepositoryImpl([Database? database, Api? api])
: database = database ?? DatabaseService.database,
api = api ?? PhpGroup() {
api = api ?? FreAccessWSGlobal() {
localDataSource = LicenseLocalDataSourceImpl(this.database);
remoteDataSource = LicenseRemoteDataSourceImpl(this.api);
}

View File

@ -26,7 +26,8 @@ enum LicenseKeys {
people('FRE-HUB-PEOPLE'),
petsHistory('FRE-HUB-PETS-HISTORY'),
settings('FRE-HUB-SETTINGS'),
logout('FRE-HUB-LOGOUT');
logout('FRE-HUB-LOGOUT'),
document('FRE-HUB-DOCUMENT');
final String value;
const LicenseKeys(this.value);
@ -138,6 +139,13 @@ class License {
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.document.value,
display: ModuleStatus.active.key,
expirationDate: '',
startDate: '',
quantity: 0,
),
Module(
key: LicenseKeys.openedVisits.value,
display: isNewVersionWithModule

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'package:hub/features/storage/index.dart';
@ -21,7 +22,7 @@ class DeepLinkService {
if (_isInitialized) return;
try {
_appLinks = AppLinks();
print('initDeepLinks');
log('initDeepLinks');
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
if (!StorageHelper().isRecovered) {
await _handleDeepLink(uri);
@ -29,25 +30,25 @@ class DeepLinkService {
});
_isInitialized = true;
} catch (e) {
print('Error initializing deep links: $e');
log('Error initializing deep links: $e');
}
}
Future<void> _handleDeepLink(Uri uri) async {
try {
print('Handling deep link: $uri');
log('Handling deep link: $uri');
if (StorageHelper().isRecovered) return;
StorageHelper().isRecovered = true;
final email = uri.queryParameters['email'] ?? '';
final token = uri.queryParameters['token'] ?? '';
print('email: $email, token: $token');
log('email: $email, token: $token');
if (email.isNotEmpty && token.isNotEmpty) {
await _showForgotPasswordScreen(email, token);
}
} catch (e, s) {
print('Error handling deep link: $e, $s');
log('Error handling deep link: $e, $s');
}
}
@ -72,11 +73,11 @@ class DeepLinkService {
enableDrag: true,
).whenComplete(() {
StorageHelper().isRecovered = false;
print('showModalBottomSheet completed');
log('showModalBottomSheet completed');
});
});
} catch (e, s) {
print('Error showing forgot password screen: $e, $s');
log('Error showing forgot password screen: $e, $s');
}
}

View File

@ -48,7 +48,7 @@ class FirebaseMessagingService {
await StorageHelper().set(SecureStorageKey.token.value, deviceToken);
final ApiCallResponse? response;
response = await PhpGroup.updToken.call();
response = await FreAccessWSGlobal.updToken.call();
if (response.jsonBody['error'] == false) {
log('Token Atualizado com Sucesso!');

View File

@ -25,7 +25,8 @@ Future<void> onMessageReceived(
required String? response,
required String? id}) async {
final ApiCallResponse? respondeSolicitacaoCall;
final RespondeSolicitacaoCall callback = PhpGroup.respondeSolicitacaoCall;
final RespondeSolicitacaoCall callback =
FreAccessWSGlobal.respondeSolicitacaoCall;
respondeSolicitacaoCall = await callback.call(
referencia: ref,

View File

@ -9,8 +9,6 @@ extension SharedPreferencesKeyExtension on SharedPreferencesKey {
switch (this) {
case SharedPreferencesKey.isFirstRun:
return 'fre_isFirstRun';
default:
return '';
}
}
}

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:hub/features/module/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:sqflite/sqflite.dart';
@ -33,29 +35,29 @@ class DatabaseService {
onOpen: _onOpen,
onConfigure: _onConfigure,
);
print('Database initialized');
log('Database initialized');
await LicenseRepositoryImpl().updateLicense();
isInitialized = true;
}
Future<void> _onConfigure(Database database) async {
print('Configuring database...');
log('Configuring database...');
}
Future<void> _onOpen(Database database) async {
print('Opening database...');
log('Opening database...');
await _executePragmas(database);
}
Future<void> _onCreate(Database database, int version) async {
print('Creating database...');
log('Creating database...');
await database.execute(createKeychainTable);
await _onUpgrade(database, 1, _dbVersion);
}
Future<void> _onUpgrade(
Database database, int oldVersion, int newVersion) async {
print('Upgrading database from version $oldVersion to $newVersion...');
log('Upgrading database from version $oldVersion to $newVersion...');
if (oldVersion < 2 && newVersion >= 2) {
await database.execute(LicenseConstants.createLicenseTable);
await database.execute(LicenseConstants.updatePetsHistoryTrigger);
@ -70,7 +72,7 @@ class DatabaseService {
Future<void> _onDowngrade(
Database database, int oldVersion, int newVersion) async {
print('Downgrading database from version $oldVersion to $newVersion...');
log('Downgrading database from version $oldVersion to $newVersion...');
if (oldVersion >= 2 && newVersion < 2) {
await database.execute(LicenseConstants.deleteLicenseTable);
await database.execute(LicenseConstants.dropPeopleDisplayTrigger);

View File

@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:math' as math;
import 'dart:developer' as dev;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@ -50,7 +51,7 @@ Future<Map<String, String>> stringToMap(String v) async {
}),
));
} catch (e) {
print('Error parsing string to map: $e');
dev.log('Error parsing string to map: $e');
return Future.value({});
}
}

View File

@ -158,7 +158,7 @@ class LightModeTheme extends FlutterFlowTheme {
late Color primary = const Color(0xFF1AAB5F);
late Color secondary = const Color(0xFFB59E9E);
late Color tertiary = const Color(0xFF984BB6);
late Color tertiary = const Color(0xFF000000);
late Color alternate = const Color(0xFFF2F2F2);
late Color alternate2 = const Color(0xFF232323);
late Color primaryText = const Color(0xFF000000);
@ -192,7 +192,7 @@ class DarkModeTheme extends FlutterFlowTheme {
late Color primary = const Color(0xFF1AAB5F);
late Color secondary = const Color(0xFF18AA99);
late Color tertiary = const Color(0xFF984BB6);
late Color tertiary = const Color(0xFF000000);
late Color alternate = const Color(0xFF232323);
late Color alternate2 = const Color(0xFF171717);
late Color primaryText = const Color(0xFFFFFFFF);

View File

@ -3,7 +3,9 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_rx_bloc/flutter_rx_bloc.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/features/documents/documents.dart';
import 'package:hub/features/history/index.dart';
import 'package:hub/features/home/index.dart';
import 'package:hub/features/local/index.dart';
@ -298,6 +300,29 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
return PetsPageWidget(pet: pet);
},
),
FFRoute(
name: 'documentPage',
path: '/documentPage',
builder: (context, params) {
return RxBlocProvider<DocumentPageBloc>(
create: (context) => DocumentPageBloc(context),
child: DocumentPage(),
);
},
),
// FFRoute(
// name: 'documentViewerScreen',
// path: '/documentViewerScreen',
// builder: (context, params) {
// final Document doc = params.getParam('doc', ParamType.Function);
// final Uri uri = params.getParam('uri', ParamType.Function);
// return DocumentViewScreen(
// key: UniqueKey(),
// doc: (doc,
// uri: uri,
// );
// },
// ),
// FFRoute(name: 'settingsPage', path: '/settingsPage', builder: (context, params) => params.isEmpty ? const NavBarPage(initialPage: 'settingsPage') : const SettingsPageWidget())
].map((r) => r.toRoute(appStateNotifier)).toList(),
);

View File

@ -218,9 +218,6 @@ dynamic deserializeParam<T>(
case ParamType.Enum:
return deserializeEnum<T>(param);
default:
return null;
}
} catch (e) {
return null;

View File

@ -44,21 +44,21 @@ Future<void> _initializeAppTrackingTransparency() async {
}
Future<void> _initializeFirebase() async {
print('Initializing Firebase...');
log('Initializing Firebase...');
await Firebase.initializeApp();
print('Firebase initialized');
log('Firebase initialized');
}
Future<void> _initializeNotificationService() async {
print('Initializing Notification Service...');
log('Initializing Notification Service...');
await NotificationService.initialize();
print('Notification Service initialized');
log('Notification Service initialized');
}
Future<void> _initializeUrlStrategy() async {
print('Initializing URL Strategy...');
setUrlStrategy(PathUrlStrategy());
print('URL Strategy initialized');
log('URL Strategy initialized');
}
Future<void> _initializeSystemSettings() async {
@ -71,7 +71,18 @@ Future<void> _initializeSystemSettings() async {
print('Debug mode');
await crashlyticsInstance.setCrashlyticsCollectionEnabled(false);
} else {
print('Release mode');
log('Release mode');
// bool unsentReports =
// await FirebaseCrashlytics.instance.checkForUnsentReports();
// if (unsentReports) {
// // Existem relatórios não enviados
// await crashlyticsInstance.sendUnsentReports();
// log('Existem relatórios de falhas não enviados.');
// } else {
// // Não existem relatórios não enviados
// log('Todos os relatórios de falhas foram enviados.');
// }
await crashlyticsInstance.setCrashlyticsCollectionEnabled(true);
if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
@ -94,15 +105,15 @@ Future<void> _initializeSystemSettings() async {
}
Future<void> _initializeFlutterFlow() async {
print('Initializing FlutterFlow...');
log('Initializing FlutterFlow...');
await FlutterFlowTheme.initialize();
await FFLocalizations.initialize();
print('FlutterFlow initialized');
log('FlutterFlow initialized');
}
Future<void> _initializeNav() async {
print('Initializing Nav...');
log('Initializing Nav...');
GoRouter.optionURLReflectsImperativeAPIs = true;
usePathUrlStrategy();
print('Nav initialized');
log('Nav initialized');
}

View File

@ -7,6 +7,7 @@ import 'dart:io';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -21,6 +22,15 @@ import 'initialization.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
class CustomScrollBehavior extends MaterialScrollBehavior {
// Override behavior methods and getters like dragDevices
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
void main() async {
await initializeBindings();
runApp(const ProviderScope(child: App()));
@ -65,38 +75,6 @@ class _AppState extends State<App> {
late GoRouter _router;
bool displaySplashImage = true;
final ThemeData _darkTheme = ThemeData(
brightness: Brightness.dark,
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: WidgetStateProperty.all(false),
interactive: false,
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.dragged)) {
return const Color(0xff1aab5f);
}
if (states.contains(WidgetState.hovered)) {
return const Color(0xff1aab5f);
}
return const Color(0xff1aab5f);
}),
),
);
final ThemeData _theme = ThemeData(
brightness: Brightness.light,
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: WidgetStateProperty.all(false),
interactive: false,
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.dragged)) {
return const Color(0xff1aab5f);
}
if (states.contains(WidgetState.hovered)) {
return const Color(0xff1aab5f);
}
return const Color(0xff1aab5f);
}),
),
);
final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates =
const [
FFLocalizationsDelegate(),
@ -192,15 +170,49 @@ class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
final themeSchema = FlutterFlowTheme.of(context);
final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: WidgetStateProperty.all(false),
interactive: false,
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.dragged)) return themeSchema.primary;
if (states.contains(WidgetState.hovered)) return themeSchema.primary;
return themeSchema.primary;
}),
),
);
final ThemeData lightTheme = ThemeData(
brightness: Brightness.light,
textSelectionTheme: TextSelectionThemeData(
cursorColor: themeSchema.primaryText, // Cor do cursor
selectionColor: themeSchema.accent2, // Cor da seleção de texto
selectionHandleColor:
themeSchema.primaryText, // Cor do manipulador de seleção
),
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: WidgetStateProperty.all(false),
interactive: false,
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.dragged)) return themeSchema.primary;
if (states.contains(WidgetState.hovered)) return themeSchema.primary;
return themeSchema.primary;
}),
),
);
return MaterialApp.router(
scrollBehavior: CustomScrollBehavior(),
key: navigatorKey,
title: 'FRE ACCESS HUB',
builder: builder,
localizationsDelegates: localizationsDelegates,
locale: _locale,
supportedLocales: supportedLocales,
theme: _theme,
darkTheme: _darkTheme,
theme: lightTheme,
darkTheme: darkTheme,
themeMode: _themeMode,
routerConfig: _router,
);

View File

@ -50,7 +50,8 @@ class LiberationHistoryModel extends FlutterFlowModel<LiberationHistoryWidget> {
required String? response,
required String? id}) async {
final ApiCallResponse? respondeSolicitacaoCall;
final RespondeSolicitacaoCall callback = PhpGroup.respondeSolicitacaoCall;
final RespondeSolicitacaoCall callback =
FreAccessWSGlobal.respondeSolicitacaoCall;
respondeSolicitacaoCall = await callback.call(
referencia: ref,

View File

@ -333,7 +333,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
Future<ApiCallResponse?> _fetchRequests() async {
try {
safeSetState(() => _loading = true);
var response = await PhpGroup.getLiberationsCall.call().first;
var response = await FreAccessWSGlobal.getLiberationsCall.call().first;
final List<dynamic> requests = response.jsonBody['solicitacoes'] ?? [];

View File

@ -97,7 +97,7 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
try {
setState(() => _loading = true);
var response = await PhpGroup.getMessagesCall.call(
var response = await FreAccessWSGlobal.getMessagesCall.call(
pageSize: _pageSize.toString(),
pageNumber: _pageNumber.toString(),
tipoDestino: _destinyType,

View File

@ -97,7 +97,7 @@ class _PackageOrderPage extends State<PackageOrderPage> {
try {
setState(() => _loading = true);
var response = await PhpGroup.buscaEnconcomendas.call(
var response = await FreAccessWSGlobal.buscaEnconcomendas.call(
pageSize: _pageSize.toString(),
page: _pageNumber.toString(),
adresseeType: _adresseeType == '.*' ? 'TOD' : _adresseeType,
@ -314,7 +314,7 @@ class _PackageOrderPage extends State<PackageOrderPage> {
}
String _imagePath(dynamic order) {
return '${PhpGroup.getBaseUrl()}/getImage.php?cliID=$cliUUID&atividade=getFotoEncomenda&orderId=${order['id'] ?? ''}';
return '${FreAccessWSGlobal.getBaseUrl()}/getImage.php?cliID=$cliUUID&atividade=getFotoEncomenda&orderId=${order['id'] ?? ''}';
}
Map<String, String> _labelsHashMap(dynamic order) {

View File

@ -82,7 +82,7 @@ class _PeopleOnThePropertyPageState extends State<PeopleOnThePropertyPage> {
body: SafeArea(
top: true,
child: FutureBuilder<ApiCallResponse>(
future: PhpGroup.getPessoasLocalCall.call(),
future: FreAccessWSGlobal.getPessoasLocalCall.call(),
builder: (context, snapshot) {
// Customize what your widget looks like when it's loading.
if (!snapshot.hasData) {
@ -123,7 +123,7 @@ class _PeopleOnThePropertyPageState extends State<PeopleOnThePropertyPage> {
}
final columnGetPessoasLocalResponse = snapshot.data!;
final getPoepleProperty = PhpGroup.getPessoasLocalCall
final getPoepleProperty = FreAccessWSGlobal.getPessoasLocalCall
.pessoas(
columnGetPessoasLocalResponse.jsonBody,
)

View File

@ -100,7 +100,7 @@ class _PetsHistoryScreenState extends State<PetsHistoryScreen>
try {
setState(() => _loading = true);
var response = await PhpGroup.getPets.call(
var response = await FreAccessWSGlobal.getPets.call(
pageSize: _pageSize,
page: _pageNumber,
);

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
@ -163,8 +164,10 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
// updateImage!();
(() async {
Response response = await get(Uri.parse(
'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId'));
final String url =
'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId';
log('img: $url');
Response response = await get(Uri.parse(url));
String base64 = base64Encode(response.bodyBytes);
uploadedTempFile = await ImageUtils.convertToUploadFile(base64);
updateImage?.call();
@ -280,7 +283,8 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
img = "base64;jpeg,$img";
final url =
'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&userUUID=$userUUID&cliID=$cliUUID&atividade=consultaFotoPet&petId=$petId';
final response = await PhpGroup.updatePet.call(
log('img: $url');
final response = await FreAccessWSGlobal.updatePet.call(
petID: petId,
image: img,
birthdayDate: textControllerData!.text,
@ -323,7 +327,7 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
Future<void> registerPet() async {
var img = await ImageUtils.convertImageFileToBase64(uploadedLocalFile!);
img = "base64;jpeg,$img";
final response = await PhpGroup.registerPet.call(
final response = await FreAccessWSGlobal.registerPet.call(
image: img,
birthdayDate: textControllerData!.text,
color: textControllerColor!.text,
@ -464,7 +468,7 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
enText: 'Are you sure you want to delete this pet?',
), () async {
int id = item['id'];
await PhpGroup.deletePet
await FreAccessWSGlobal.deletePet
.call(
petID: id,
)

View File

@ -62,7 +62,7 @@ class PreferencesPageModel with ChangeNotifier {
onConfirm() async {
String content;
String value = !isNotify ? 'S' : 'N';
await PhpGroup.changeNotifica
await FreAccessWSGlobal.changeNotifica
.call(notifica: value)
.then((value) async {
if (value.jsonBody['error'] == false) {
@ -109,7 +109,7 @@ class PreferencesPageModel with ChangeNotifier {
);
onConfirm() async {
String content;
await PhpGroup.updateIDE.call().then((value) async {
await FreAccessWSGlobal.updateIDE.call().then((value) async {
if (value.jsonBody['error'] == false) {
notifyListeners();
content = FFLocalizations.of(context).getVariableText(
@ -141,7 +141,7 @@ class PreferencesPageModel with ChangeNotifier {
Future<void> toggleAccess(BuildContext context) async {
onChange(String key) async {
await StorageHelper().set(SecureStorageKey.accessPass.value, key);
await PhpGroup.changePass
await FreAccessWSGlobal.changePass
.call(newSenha: key)
.then((value) async {
final String content;
@ -180,7 +180,7 @@ class PreferencesPageModel with ChangeNotifier {
Future<void> togglePanic(BuildContext context) async {
onChange(String key) async {
await StorageHelper().set(SecureStorageKey.panicPass.value, key);
await PhpGroup.changePanic
await FreAccessWSGlobal.changePanic
.call(newSenhaPanico: key)
.then((value) async {
final String content;

View File

@ -103,7 +103,6 @@ class _QrCodePageWidgetState extends State<QrCodePageWidget>
screenWidth < screenHeight ? screenWidth : screenHeight;
double dimension = smallerDimension * 0.75;
double totalTimeInSeconds = 100.0;
double limitedHeaderTextSize =
LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16);
double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);

View File

@ -29,9 +29,7 @@ class _ReceptionPageWidgetState extends State<ReceptionPageWidget>
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
() async {
final lifecycle = await AwesomeNotifications().getAppLifeCycle();
}();
() async {}();
FirebaseMessagingService().updateDeviceToken();
LocalsRepositoryImpl().validateLocal(context);
@ -183,7 +181,7 @@ class _ReceptionPageWidgetState extends State<ReceptionPageWidget>
padding: const EdgeInsets.fromLTRB(60, 0, 60, 25),
child: FFButtonWidget(
onPressed: () async {
PhpGroup.unregisterDevice();
FreAccessWSGlobal.unregisterDevice();
AuthenticationService.signOut(context);
setState(() {});
},

View File

@ -175,8 +175,8 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty>
try {
setState(() => _loading = true);
var response =
await PhpGroup.getResidentsByProperty.call(_pageNumber.toString());
var response = await FreAccessWSGlobal.getResidentsByProperty
.call(_pageNumber.toString());
final List<dynamic> residents = response.jsonBody['residents'] ?? [];
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);

View File

@ -361,7 +361,7 @@ class ScheduleCompleteVisitPageModel
required String? accessKey,
required String? email}) async {
final ApiCallResponse? response;
final CancelaVisita callback = PhpGroup.cancelaVisita;
final CancelaVisita callback = FreAccessWSGlobal.cancelaVisita;
response = await callback.call(
idDestino: idDestino,

View File

@ -90,6 +90,7 @@ class _ScheduleCompleteVisitPageWidgetState
}
}
// ignore: unused_element
void _scrollListener() {
if (_visitHistoryController.position.pixels ==
_visitHistoryController.position.maxScrollExtent) {
@ -1071,7 +1072,8 @@ class _ScheduleCompleteVisitPageWidgetState
height: scaledSizedBoxSize * 0.5,
decoration: const BoxDecoration(),
child: FutureBuilder<ApiCallResponse>(
future: PhpGroup.getDadosCall.call(),
future:
FreAccessWSGlobal.getDadosCall.call(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
@ -1088,11 +1090,12 @@ class _ScheduleCompleteVisitPageWidgetState
);
}
final reasonsJsonList =
PhpGroup.getDadosCall.reasonsJsonList(
snapshot.data!.jsonBody);
final reasonsOptionLabels = PhpGroup
final reasonsJsonList = FreAccessWSGlobal
.getDadosCall
.reasonsJsonList(
snapshot.data!.jsonBody);
final reasonsOptionLabels =
FreAccessWSGlobal.getDadosCall
.reasonsMotDescStrList(
snapshot.data!.jsonBody);
@ -1195,7 +1198,8 @@ class _ScheduleCompleteVisitPageWidgetState
height: scaledSizedBoxSize * 0.5,
decoration: const BoxDecoration(),
child: FutureBuilder<ApiCallResponse>(
future: PhpGroup.getDadosCall.call(),
future:
FreAccessWSGlobal.getDadosCall.call(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
@ -1212,11 +1216,12 @@ class _ScheduleCompleteVisitPageWidgetState
);
}
final lavelsJsonList =
PhpGroup.getDadosCall.levelJsonList(
snapshot.data!.jsonBody);
final lavelsOptionLabels = PhpGroup
final lavelsJsonList = FreAccessWSGlobal
.getDadosCall
.levelJsonList(
snapshot.data!.jsonBody);
final lavelsOptionLabels =
FreAccessWSGlobal.getDadosCall
.levelNACDescricaoStrList(
snapshot.data!.jsonBody);
model.processDropDown2(lavelsJsonList!);
@ -1556,7 +1561,7 @@ class _ScheduleCompleteVisitPageWidgetState
onPressed: model.isValid()
? () async {
Future<void> scheduleVisit() async {
await PhpGroup.postScheduleVisitCall
await FreAccessWSGlobal.postScheduleVisitCall
.call(
devDesc: model.textController3.text,
idVisitante: model.visitorStrList,
@ -1572,7 +1577,7 @@ class _ScheduleCompleteVisitPageWidgetState
.catchError((e) async =>
await DialogUtil.errorDefault(context))
.then((value) async {
if (PhpGroup.postScheduleVisitCall.error(
if (FreAccessWSGlobal.postScheduleVisitCall.error(
(value.jsonBody ?? ''),
) ==
false) {

View File

@ -76,7 +76,7 @@ class _VisitHistoryWidgetState extends State<VisitHistoryWidget>
setState(() => _loading = true);
var response = await ScheduleCompleteVisitPageModel().visitHistory(
requestFn: () => PhpGroup.getVisitsCall.call(
requestFn: () => FreAccessWSGlobal.getVisitsCall.call(
pageSize: _pageSize,
pageNumber: _pageNumber,
),

View File

@ -10,7 +10,7 @@ class VehicleHistoryScreen extends StatefulWidget {
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
with Pageable {
final apiCall = PhpGroup.getVehiclesByProperty;
final apiCall = FreAccessWSGlobal.getVehiclesByProperty;
int totalOwnerVehicles = 0;
final PagingController<int, dynamic> _pagingController =
PagingController<int, dynamic>(firstPageKey: 1);

View File

@ -7,8 +7,8 @@ import 'package:hub/features/backend/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart';
import 'package:hub/shared/extensions/index.dart';
import 'package:hub/shared/utils/index.dart';
import 'package:hub/shared/extensions.dart';
import 'package:hub/shared/utils.dart';
/// [VehicleModel] is a class that contains the business logic of the vehicle page.
class VehicleModel extends FlutterFlowModel<VehiclePage>
@ -196,7 +196,7 @@ mixin class _BaseVehiclePage {
/// [_VehicleRegisterScreenModel] is a mixin that contains the business logic of the vehicle register page.
mixin _VehicleRegisterScreenModel on _BaseVehiclePage {
Future<void> registerVehicle() async {
final response = await PhpGroup.registerVehicle.call(
final response = await FreAccessWSGlobal.registerVehicle.call(
licensePlate: textFieldControllerLicensePlate!.text,
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
@ -218,7 +218,7 @@ mixin _VehicleRegisterScreenModel on _BaseVehiclePage {
/// [_VehicleUpdateScreenModel] is a mixin that contains the business logic of the vehicle update page.
mixin _VehicleUpdateScreenModel on _BaseVehiclePage {
Future<void> updateVehicle() async {
final response = await PhpGroup.updateVehicle.call(
final response = await FreAccessWSGlobal.updateVehicle.call(
licensePlate: textFieldControllerLicensePlate!.text,
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
@ -403,7 +403,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
Future<bool> processDeleteRequest(dynamic item) async {
log('processDeleteRequest -> item[$item]');
bool result = await PhpGroup.deleteVehicle
bool result = await FreAccessWSGlobal.deleteVehicle
.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
@ -493,7 +493,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
}
Future<ApiCallResponse> processCancelDeleteRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
return await FreAccessWSGlobal.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
@ -502,7 +502,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
}
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
return await FreAccessWSGlobal.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
@ -511,7 +511,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
}
Future<ApiCallResponse> processCancelCreateRequest(dynamic item) async {
return await PhpGroup.cancelDelete.call(
return await FreAccessWSGlobal.cancelDelete.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],

View File

@ -13,7 +13,7 @@ import 'package:hub/features/backend/index.dart';
import 'package:hub/features/module/index.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicle_model.dart';
import 'package:hub/shared/extensions/index.dart';
import 'package:hub/shared/extensions.dart';
import 'package:hub/shared/mixins/pageable_mixin.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/license_util.dart';

View File

@ -54,8 +54,8 @@ class _VisitsOnThePropertyState extends State<VisitsOnTheProperty>
@override
Widget build(BuildContext context) {
late final limitedBodyTextSize =
LimitedFontSizeUtil.getBodyFontSize(context);
// late final limitedBodyTextSize =
// LimitedFontSizeUtil.getBodyFontSize(context);
late final limitedHeaderTextSize =
LimitedFontSizeUtil.getHeaderFontSize(context);
@ -176,7 +176,7 @@ class _VisitsOnThePropertyState extends State<VisitsOnTheProperty>
setState(() => _loading = true);
var response =
await PhpGroup.getOpenedVisits.call(_pageNumber.toString());
await FreAccessWSGlobal.getOpenedVisits.call(_pageNumber.toString());
final List<dynamic> visits = response.jsonBody['visitas'] ?? [];
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);

View File

View File

@ -1 +0,0 @@

1
lib/shared/enums.dart Normal file
View File

@ -0,0 +1 @@
export 'enums/enum_throw_exception.dart';

View File

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

View File

@ -0,0 +1,3 @@
export 'extensions/dialog_extensions.dart';
export 'extensions/flutter_secure_storage_extensions.dart';
export 'extensions/string_extensions.dart';

View File

@ -1,3 +0,0 @@
export 'dialog_extensions.dart';
export 'flutter_secure_storage_extensions.dart';
export 'string_extensions.dart';

View File

@ -1,3 +1,5 @@
import 'dart:ui';
extension StringNullableExtensions on String? {
bool get toBoolean {
if (this == null) return false;
@ -24,3 +26,16 @@ extension StringExtensions on String {
}
extension StringExtension on String? {}
extension HexColor on String {
Color toColor() {
final hexCode = replaceAll('#', '');
final buffer = StringBuffer();
if (hexCode.length == 6) {
buffer
.write('ff'); // Adiciona opacidade total caso não esteja especificada
}
buffer.write(hexCode);
return Color(int.parse(buffer.toString(), radix: 16));
}
}

0
lib/shared/helpers.dart Normal file
View File

View File

@ -1 +0,0 @@

4
lib/shared/mixins.dart Normal file
View File

@ -0,0 +1,4 @@
export 'mixins/pegeable_mixin.dart';
export 'mixins/status_mixin.dart';
export 'mixins/switcher_mixin.dart';
export 'mixins/template_mixin.dart';

View File

@ -1,2 +0,0 @@
export 'status_mixin.dart';
export 'switcher_mixin.dart';

View File

@ -0,0 +1,139 @@
// import 'package:flutter/material.dart';
// import 'package:hub/flutter_flow/index.dart';
// import 'package:hub/shared/utils/limited_text_size.dart';
// import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
// extension PagedListViewExtension<PageKeyType, ItemType>
// on PagedSliverList<PageKeyType, ItemType> {}
// typedef PaginatedListViewHeaderBuilder<T> = Widget Function<T>(
// Future<List<T?>> Function() gen);
// typedef PaginatedListViewBodyBuilder<T> = Widget Function(BuildContext, T, int);
// mixin Pageable<T extends StatefulWidget> on State<T> {
// Expanded buildPaginatedListView<PageKeyType, BodyType, HeaderType>(
// String noDataFound,
// PagingController<PageKeyType, BodyType> pg,
// Future<List<HeaderType?>> Function() headerItems,
// PaginatedListViewHeaderBuilder<BodyType> headerBuilder,
// PaginatedListViewBodyBuilder<BodyType> bodyBuilder) {
// final theme = FlutterFlowTheme.of(context);
// return Expanded(
// child: RefreshIndicator(
// backgroundColor: theme.primaryBackground,
// color: theme.primary,
// onRefresh: () async => pg.refresh(),
// child: PagedListView<PageKeyType, BodyType>(
// pagingController: pg,
// builderDelegate: PagedChildBuilderDelegate<BodyType>(
// animateTransitions: true,
// itemBuilder: (context, item, int index) {
// return Column(children: [
// if (index == 0) headerBuilder(headerItems),
// bodyBuilder(context, item, index),
// ]);
// },
// newPageProgressIndicatorBuilder: (context) =>
// buildLoadingIndicator(context),
// firstPageProgressIndicatorBuilder: (context) =>
// buildLoadingIndicator(context),
// noItemsFoundIndicatorBuilder: (context) =>
// buildNoDataFound<HeaderType>(
// context, noDataFound, headerItems, headerBuilder),
// firstPageErrorIndicatorBuilder: (context) => const Placeholder(),
// newPageErrorIndicatorBuilder: (context) => const Placeholder(),
// ),
// ),
// ),
// );
// }
// Future<void> showError(PagingStatus status, PagingController pg) async {
// if (status == PagingStatus.subsequentPageError) {
// final message = FFLocalizations.of(context).getVariableText(
// enText: 'Something went wrong while fetching a new page.',
// ptText: 'Algo deu errado ao buscar uma nova página.',
// );
// final retry = FFLocalizations.of(context).getVariableText(
// enText: 'Retry',
// ptText: 'Recarregar',
// );
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(message),
// action: SnackBarAction(
// label: retry,
// onPressed: () => pg.retryLastFailedRequest(),
// ),
// ),
// );
// }
// }
// Future<void> fetchPage({
// required Future<(bool, dynamic)> Function() dataProvider,
// required void Function(dynamic data) onDataAvailable,
// required void Function() onDataUnavailable,
// required void Function(Object error, StackTrace stackTrace) onFetchError,
// }) async {
// try {
// final (bool isDataAvailable, dynamic data) = await dataProvider();
// if (isDataAvailable) {
// onDataAvailable(data);
// } else {
// onDataUnavailable();
// }
// } catch (error, stackTrace) {
// onFetchError(error, stackTrace);
// }
// }
// void showNoMoreDataSnackBar(BuildContext context) {
// final message = FFLocalizations.of(context).getVariableText(
// ptText: "Não há mais dados.",
// enText: "No more data.",
// );
// showSnackbar(context, message, true);
// }
// Widget buildNoDataFound<T>(
// BuildContext context,
// String title,
// Future<List<T?>> Function() items,
// Widget Function<T>(Future<List<T?>> Function() items) headerBuilder,
// ) {
// final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context);
// // final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
// return Column(
// children: [
// headerBuilder(items),
// Expanded(
// child: Center(
// child: Text(
// title,
// style: TextStyle(
// fontFamily: 'Nunito',
// fontSize: headerFontSize,
// ),
// ),
// ),
// ),
// ],
// );
// }
// Widget buildLoadingIndicator(BuildContext context) {
// return Container(
// padding: const EdgeInsets.symmetric(vertical: 15),
// child: Center(
// child: CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(
// FlutterFlowTheme.of(context).primary,
// ),
// ),
// ),
// );
// }
// }

View File

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
mixin Template {
PreferredSizeWidget buildAppBar(
String title,
BuildContext context, [
dynamic Function()? backAction,
dynamic Function()? frontAction,
]) {
final theme = FlutterFlowTheme.of(context);
return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false,
title: Text(
title,
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 16.0,
fontWeight: FontWeight.bold,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).headlineMediumFamily),
),
),
leading: _backButton(context, theme, backAction),
centerTitle: true,
elevation: 0.0,
actions: _frontButton(context, theme, frontAction),
);
}
List<Widget> _frontButton(BuildContext context, FlutterFlowTheme theme,
dynamic Function()? action) {
if (action == null) return [];
return [
IconButton(
onPressed: () async => await showModalBottomSheet(
context: context,
builder: (context) => action(),
),
icon: Icon(
Symbols.info_i_rounded,
color: FlutterFlowTheme.of(context).primaryText,
),
)
];
}
Widget? _backButton(BuildContext context, FlutterFlowTheme theme,
dynamic Function()? onPressed) {
if (onPressed == null) return null;
return FlutterFlowIconButton(
key: ValueKey<String>('BackNavigationAppBar'),
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: theme.primaryText,
size: 30.0,
),
onPressed: onPressed,
);
}
}

0
lib/shared/services.dart Normal file
View File

View File

@ -1 +0,0 @@

15
lib/shared/utils.dart Normal file
View File

@ -0,0 +1,15 @@
export 'utils/biometric_util.dart';
export 'utils/device_util.dart';
export 'utils/dialog_util.dart';
export 'utils/image_util.dart';
export 'utils/limited_text_size.dart';
export 'utils/loading_util.dart';
export 'utils/log_util.dart';
export 'utils/path_util.dart';
export 'utils/share_util.dart';
export 'utils/snackbar_util.dart';
export 'utils/string_util.dart';
export 'utils/text_util.dart';
export 'utils/validator_util.dart';
export 'utils/webview_util.dart';
export 'utils/color_util.dart';

View File

@ -0,0 +1,48 @@
import 'dart:ui';
import 'package:flutter/material.dart';
class ColorUtil {
static Color getContrastColor(Color a, Color b) {
double luminance(Color color) {
return (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255;
}
double contrastRatio(Color a, Color b) {
final lumA = luminance(a) + 0.05;
final lumB = luminance(b) + 0.05;
return lumA > lumB ? lumA / lumB : lumB / lumA;
}
if (contrastRatio(a, b) < 4.5) {
// Find a color with higher contrast within the same hue
final hsv = HSVColor.fromColor(a);
double hue = hsv.hue;
double saturation = hsv.saturation;
double brightness = hsv.value;
// Increase brightness to ensure higher contrast
brightness = brightness > 0.5 ? brightness - 0.5 : brightness + 0.5;
return HSVColor.fromAHSV(1.0, hue, saturation, brightness).toColor();
}
return b;
}
static Color getSelfContrastColor(Color color) {
final hsv = HSVColor.fromColor(color);
double hue = hsv.hue;
double saturation = hsv.saturation;
double brightness = hsv.value;
// Increase brightness to ensure higher contrast
brightness = brightness > 0.5 ? brightness - 0.5 : brightness + 0.5;
return HSVColor.fromAHSV(1.0, hue, saturation, brightness).toColor();
}
}
extension ColorUtilExtension on Color {
Color get highlight => ColorUtil.getSelfContrastColor(this);
}

View File

@ -1,14 +0,0 @@
export 'biometric_util.dart';
export 'device_util.dart';
export 'dialog_util.dart';
export 'image_util.dart';
export 'limited_text_size.dart';
export 'loading_util.dart';
export 'log_util.dart';
export 'path_util.dart';
export 'share_util.dart';
export 'snackbar_util.dart';
export 'string_util.dart';
export 'text_util.dart';
export 'validator_util.dart';
export 'webview_util.dart';

View File

@ -6,7 +6,7 @@ import 'package:hub/features/backend/index.dart';
class LogUtil {
static void requestAPIFailed(String url, String body, String reason,
dynamic error, StackTrace stack) async {
final fullUrl = "${PhpGroup.getBaseUrl()}/$url";
final fullUrl = "${FreAccessWSGlobal.getBaseUrl()}/$url";
log("URL: $fullUrl");
log("Body: $body");
log("Reason: $reason");

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:intl/intl.dart';
class ValidatorUtil {
@ -34,10 +36,16 @@ class ValidatorUtil {
}
static String toLocalDateTime(String format, String value) {
try {
if (value.isEmpty) return '';
DateFormat dateFormat = DateFormat(format);
DateTime dateTime = dateFormat.parse(value);
return DateFormat('dd/MM/yyyy HH:mm:ss').format(dateTime);
DateTime? dateTime = dateFormat.tryParse(value);
if (dateTime == null) return '';
return dateFormat.format(dateTime);
} catch (e, s) {
log(e.toString(), stackTrace: s);
return '';
}
}
static String formatDateTimePicker(String dateTime) {

18
lib/shared/widgets.dart Normal file
View File

@ -0,0 +1,18 @@
/// [Base]
library;
export 'widgets/page.dart';
export 'widgets/component.dart';
export 'widgets/screen.dart';
export 'widgets/model.dart';
export 'widgets/entity.dart';
/// [View]'s
export 'widgets/list_view.dart';
export 'widgets/read_view.dart';
export 'widgets/enhanced_carousel_view.dart';
export 'widgets/enhanced_list_view.dart';
export 'widgets/enhanced_search_view.dart';
/// [Component]'s
export 'widgets/text.dart';

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:hub/shared/widgets.dart';
/// [ComponentWidget]
abstract class ComponentWidget<T> extends Widget {
const ComponentWidget({super.key});
}
abstract class ModelComponent<T> extends ModelWidget
implements ComponentWidget<T> {
const ModelComponent({super.key});
}
abstract class StatelessComponent<T> extends StatelessWidget
implements ComponentWidget<T> {
const StatelessComponent({super.key});
}
abstract class StatefulComponent<T> extends StatefulWidget
implements ComponentWidget<T> {
const StatefulComponent({super.key});
}
abstract class ComponentState<T extends StatefulComponent> extends State<T> {}

View File

@ -0,0 +1,124 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/shared/utils.dart';
typedef EnhancedCarouselViewKey<T> = GlobalKey<_EnhancedCarouselViewState<T>>;
class EnhancedCarouselView<T> extends StatefulWidget {
final Future<List<T?>> Function() dataProvider;
final void Function(T?, BuildContext) filter;
final Widget Function<T>(T? item, bool isSelected) itemBuilder;
final bool showIndicator;
const EnhancedCarouselView({
super.key,
required this.dataProvider,
required this.filter,
required this.itemBuilder,
this.showIndicator = false,
});
@override
_EnhancedCarouselViewState<T> createState() =>
_EnhancedCarouselViewState<T>();
}
class _EnhancedCarouselViewState<T> extends State<EnhancedCarouselView<T>> {
T? selectedCategory;
bool itemIsSelected(T item) {
return selectedCategory == item;
}
@override
Widget build(BuildContext context) {
final theme = FlutterFlowTheme.of(context);
final backgroundColor = theme.primary;
final overlayColor = WidgetStateProperty.all(Colors.transparent);
return Stack(
children: [
Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(15, 0, 50, 0),
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: 'Suas Categorias',
enText: 'Your Categories',
),
style: TextStyle(
color: FlutterFlowTheme.of(context).primaryText,
fontSize: LimitedFontSizeUtil.getHeaderFontSize(context),
),
),
),
FutureBuilder<List<T?>>(
future: widget.dataProvider(),
builder: (context, snapshot) {
if (!snapshot.hasData) return SizedBox();
final items = snapshot.data!
.map((item) =>
widget.itemBuilder(item, itemIsSelected(item as T)))
.toList();
return SizedBox(
height: 130, // Set a specific height
child: CarouselView(
itemExtent: 140,
enableSplash: true,
itemSnapping: true,
controller: CarouselController(initialItem: 1),
backgroundColor: backgroundColor,
overlayColor: overlayColor,
padding: EdgeInsets.zero,
elevation: 0,
reverse: true,
shrinkExtent: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
onTap: (index) async {
log('Selected: ${snapshot.data![index]}');
log('Selected Category: $selectedCategory');
final bool isSame =
itemIsSelected(snapshot.data![index]!);
setState(() {
if (isSame) {
selectedCategory = null;
} else {
selectedCategory = snapshot.data![index] as T;
}
});
if (isSame)
widget.filter(null, context);
else
widget.filter(snapshot.data![index] as T, context);
},
children: items,
),
);
},
),
],
),
if (widget.showIndicator)
Positioned(
left: 0,
top: 50,
child: Icon(Icons.arrow_left, size: 30, color: Colors.grey),
),
if (widget.showIndicator)
Positioned(
right: 0,
top: 50,
child: Icon(Icons.arrow_right, size: 30, color: Colors.grey),
),
],
);
}
}

View File

@ -0,0 +1,616 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:rx_bloc/rx_bloc.dart';
import 'package:rx_bloc_list/rx_bloc_list.dart';
import 'package:rxdart/rxdart.dart';
/// [TypeDefs] ----------------------------------------------------
typedef EnhancedListViewKey<BodyType, HeaderType, FooterType, QueryType>
= GlobalKey<
EnhancedListViewState<BodyType, HeaderType, FooterType, QueryType>>;
typedef HeaderTileBuilder<HeaderType> = Widget Function(
Future<List<HeaderType?>> Function() headerItems);
typedef BodyTileBuilder<BodyType> = Widget Function(
BuildContext context, BodyType item, int index);
typedef FooterTileBuilder<FooterType> = Widget Function(
Future<List<FooterType?>> Function() footerItems);
typedef Query<QueryType> = QueryType?;
typedef BodyRetrievalUseCase<BodyType, QueryType> = Future<List<BodyType?>>
Function(int page, int pageSize, QueryType query);
typedef HeaderRetrievalUseCase<HeaderType> = Future<List<HeaderType?>>
Function();
typedef FooterRetrievalUseCase<FooterType> = Future<List<FooterType?>>
Function();
/// [Extensions] ----------------------------------------------------
///
extension PaginatedListMergeExtensions<T>
on Stream<Result<EnhancedPaginatedList<T>>> {
Stream<EnhancedPaginatedList<T>> mergeWithPaginatedList(
BehaviorSubject<EnhancedPaginatedList<T>> currentList) {
return map(
(result) {
final current = currentList.value;
if (result is ResultSuccess<EnhancedPaginatedList<T>>) {
final newPaginated = result.data;
return current.items.isEmpty
? newPaginated
: current.copyWith(
list: [...current.items, ...newPaginated.items],
currentPage: newPaginated.currentPage,
totalCount: newPaginated.totalCount,
error: newPaginated.error,
);
} else if (result is ResultError<EnhancedPaginatedList<T>>) {
return current.copyWith(error: result.error);
} else {
return current;
}
},
);
}
}
extension PublishSubjectExtensions<T> on PublishSubject<T> {
Stream<T> startWith(T initial) => Rx.concat([Stream.value(initial), this]);
}
extension StreamStartWithExtension<T> on Stream<T> {
Stream<T> startWith(T initial) => Rx.concat([Stream.value(initial), this]);
}
extension QueryBlocStreamExtensions<T> on Stream<bool> {
// Stream<Result<EnhancedPaginatedList<T>>> fetchData(
// EnhancedListViewRepository<T> repository,
// PaginatedListViewBodyBuilder<T> builder,
// BehaviorSubject<EnhancedPaginatedList<T>> paginatedList,
// ) =>
// switchMap((reset) {
// if (reset) {
// paginatedList.add(paginatedList.value.resetAll());
// }
// final nextPage = paginatedList.value.currentPage + 1;
// return repository
// .fetchPage(nextPage, paginatedList.value.pageSize, builder)
// .asResultStream();
// });
}
/// [Interfaces] ----------------------------------------------------
interface class EnhancedPaginatedList<T> extends PaginatedList<T> {
@override
final Exception? error;
final bool isInitialized;
@override
final bool isLoading;
final List<T> items;
@override
final int pageSize;
@override
final int? totalCount;
final int currentPage;
EnhancedPaginatedList({
required this.items,
required this.pageSize,
this.currentPage = 0,
this.totalCount,
required this.error,
required this.isInitialized,
required this.isLoading,
}) : super(
error: error,
isInitialized: isInitialized,
isLoading: isLoading,
list: items,
pageSize: pageSize,
totalCount: totalCount,
);
EnhancedPaginatedList<T> resetAll() => EnhancedPaginatedList<T>(
error: null,
isInitialized: false,
isLoading: false,
items: const [],
pageSize: pageSize,
totalCount: null,
currentPage: 0,
);
@override
EnhancedPaginatedList<T> copyWith({
List<T>? list,
bool? isLoading,
int? totalCount,
Exception? error,
int? pageSize,
bool? isInitialized,
int? currentPage,
}) =>
EnhancedPaginatedList<T>(
error: error ?? this.error,
isInitialized: isInitialized ?? this.isInitialized,
isLoading: isLoading ?? this.isLoading,
items: list ?? this.items,
pageSize: pageSize ?? this.pageSize,
totalCount: totalCount ?? this.totalCount,
currentPage: currentPage ?? this.currentPage,
);
@override
int get itemCount => items.length;
@override
T? getItem(int index) => index < items.length ? items[index] : null;
Future<void> awaitLoad() async => Future.value();
}
abstract interface class EnhancedListViewBase<BodyType, HeaderType, FooterType,
QueryType> extends StatefulWidget {
const EnhancedListViewBase({super.key});
}
abstract interface class EnhancedListViewBaseState<BodyType, HeaderType,
FooterType, QueryType>
extends State<
EnhancedListViewBase<BodyType, HeaderType, FooterType, QueryType>> {}
/// [Mixins] ----------------------------------------------------
mixin EnhancedListViewMixin<BodyType, HeaderType, FooterType, QueryType> {
late EnhancedListViewBloc<BodyType, HeaderType, FooterType, QueryType> bloc;
void filterBodyItems(QueryType query) => bloc.filterBodyItems(query);
void filterHeaderItems(QueryType query) => bloc.filterHeaderItems(query);
void filterFooterItems(QueryType query) => bloc.filterFooterItems(query);
}
/// [Widgets] ----------------------------------------------------
class EnhancedListView<BodyType, HeaderType, FooterType, QueryType>
extends EnhancedListViewBase<BodyType, HeaderType, FooterType, QueryType> {
final EnhancedListViewRepository<BodyType, HeaderType, FooterType, QueryType>
repository;
final EnhancedListViewController<BodyType, HeaderType, FooterType, QueryType>
controller;
const EnhancedListView({
Key? key,
required this.repository,
required this.controller,
}) : super(key: key);
@override
EnhancedListViewState<BodyType, HeaderType, FooterType, QueryType>
createState() =>
EnhancedListViewState<BodyType, HeaderType, FooterType, QueryType>();
}
class EnhancedListViewState<ItemType, HeaderType, FooterType, QueryType>
extends State<EnhancedListView<ItemType, HeaderType, FooterType, QueryType>>
with EnhancedListViewMixin<ItemType, HeaderType, FooterType, QueryType> {
@override
void initState() {
super.initState();
bloc = EnhancedListViewBloc<ItemType, HeaderType, FooterType, QueryType>(
bodyItemsBuilder: widget.repository.fetchBody,
headerItemsBuilder: widget.repository.fetchHeader ?? () async => [],
footerItemsBuilder: widget.repository.fetchFooter ?? () async => [],
);
bloc.events.loadBodyItems();
bloc.events.loadHeaderItems();
bloc.events.loadFooterItems();
}
@override
Widget build(BuildContext context) {
final String defaultMessage = FFLocalizations.of(context).getVariableText(
ptText: 'Nenhum item encontrado',
enText: 'No items found',
);
final header = StreamBuilder<List<HeaderType>>(
stream: bloc.states.headerItems.cast<List<HeaderType>>(),
builder: (context, headerSnapshot) {
if (headerSnapshot.connectionState == ConnectionState.waiting) {
return const EnhancedProgressIndicator();
} else if (headerSnapshot.hasError) {
return EnhancedErrorWidget(error: headerSnapshot.error);
} else if (!headerSnapshot.hasData || headerSnapshot.data!.isEmpty) {
return const SizedBox.shrink();
} else {
return widget
.controller.headerBuilder!(() async => headerSnapshot.data!);
}
},
);
final footer = StreamBuilder<List<FooterType>>(
stream: bloc.states.footerItems.cast<List<FooterType>>(),
builder: (context, footerSnapshot) {
if (footerSnapshot.connectionState == ConnectionState.waiting) {
return const EnhancedProgressIndicator();
} else if (footerSnapshot.hasError) {
return EnhancedErrorWidget(error: footerSnapshot.error);
} else if (!footerSnapshot.hasData || footerSnapshot.data!.isEmpty) {
return const SizedBox.shrink();
} else {
return widget
.controller.footerBuilder!(() async => footerSnapshot.data!);
}
},
);
final body = Expanded(
child: StreamBuilder<List<ItemType>>(
stream: bloc.states.bodyItems.cast<List<ItemType>>(),
builder: (context, bodySnapshot) {
if (bodySnapshot.connectionState == ConnectionState.waiting) {
return const EnhancedProgressIndicator();
} else if (bodySnapshot.hasError) {
return EnhancedErrorWidget(error: bodySnapshot.error);
} else if (!bodySnapshot.hasData || bodySnapshot.data!.isEmpty) {
return Center(
child: Text(defaultMessage),
);
} else {
return ListView.builder(
itemCount: bodySnapshot.data?.length ?? 0,
itemBuilder: (context, index) {
return widget.controller
.bodyBuilder(context, bodySnapshot.data![index], index);
},
);
}
},
),
);
return Column(
children: [
if (widget.controller.headerBuilder != null) header,
body,
if (widget.controller.footerBuilder != null) footer,
],
);
}
@override
void dispose() {
bloc.dispose();
super.dispose();
}
}
/// [Utils] ----------------------------------------------------
class EnhancedListTile<T extends Widget> extends StatelessWidget {
const EnhancedListTile(
{required this.leading, required this.title, super.key});
final T leading;
final T title;
@override
Widget build(BuildContext context) {
return Card(
child: ListTile(
leading: leading,
title: title,
),
);
}
}
class EnhancedErrorWidget extends StatelessWidget {
final Object? error;
const EnhancedErrorWidget({required this.error, super.key});
@override
Widget build(BuildContext context) {
log('error: $error');
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
error.toString(),
style: const TextStyle(color: Colors.red),
),
);
}
}
class EnhancedProgressIndicator extends StatelessWidget {
const EnhancedProgressIndicator({super.key});
@override
Widget build(BuildContext context) => const Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: CircularProgressIndicator(),
),
);
}
class NetworkError implements Exception {
final String message;
NetworkError(this.message);
}
class ParsingError implements Exception {
final String message;
ParsingError(this.message);
}
class AuthorizationError implements Exception {
final String message;
AuthorizationError(this.message);
}
/// [Repositories] ----------------------------------------------------
class EnhancedListViewRepository<BodyType, HeaderType, FooterType, QueryType> {
final BodyRetrievalUseCase<BodyType, QueryType?> fetchBody;
final HeaderRetrievalUseCase<HeaderType>? fetchHeader;
final FooterRetrievalUseCase<FooterType>? fetchFooter;
const EnhancedListViewRepository({
required this.fetchBody,
this.fetchHeader,
this.fetchFooter,
});
}
// class HeaderRepository<HeaderType, QueryType> {}
// class BodyRepository<BodyType, QueryType> {}
// class FooterRepository<FooterType, QueryType> {}
/// [Controllers] ----------------------------------------------------
class EnhancedListViewController<BodyType, HeaderType, FooterType, QueryType> {
final BodyTileBuilder<BodyType> bodyBuilder;
final HeaderTileBuilder<HeaderType>? headerBuilder;
final FooterTileBuilder<FooterType>? footerBuilder;
const EnhancedListViewController({
required this.bodyBuilder,
this.headerBuilder,
this.footerBuilder,
});
}
// class HeaderController<HeaderType, QueryType> {}
// class BodyController<BodyType, QueryType> {}
// class FooterController<FooterType, QueryType> {}
/// [Blocs] ----------------------------------------------------
Stream<bool> get loadingState => Stream<bool>.empty();
Stream<Exception> get errorState => Stream<Exception>.empty();
abstract class EnhancedListViewEvents<BodyType, HeaderType, FooterType,
QueryType> {
void loadBodyItems({bool reset = false, dynamic query = null});
void loadHeaderItems();
void loadFooterItems();
}
abstract class EnhancedListViewStates<BodyType, HeaderType, FooterType,
QueryType> {
Stream<List<BodyType>> get bodyItems;
Stream<List<HeaderType>> get headerItems;
Stream<List<FooterType>> get footerItems;
Stream<bool> get isLoading;
Stream<String> get errors;
}
class EnhancedListViewBloc<BodyType, HeaderType, FooterType, QueryType>
extends $EnhancedListViewBloc<BodyType, HeaderType, FooterType,
QueryType?> {
EnhancedListViewBloc({
required this.bodyItemsBuilder,
required this.headerItemsBuilder,
required this.footerItemsBuilder,
}) {
_$loadBodyItemsEvent
.startWith((query: null, reset: true))
.switchMap((item) => _fetchBodyItems(item.reset, item.query))
.bind(_bodyItems)
.addTo(_compositeSubscription);
_$loadHeaderItemsEvent
.switchMap((_) => _fetchHeaderItems())
.bind(_headerItems)
.addTo(_compositeSubscription);
_$loadFooterItemsEvent
.switchMap((_) => _fetchFooterItems())
.bind(_footerItems)
.addTo(_compositeSubscription);
}
final BodyRetrievalUseCase<BodyType, QueryType?> bodyItemsBuilder;
final HeaderRetrievalUseCase<HeaderType> headerItemsBuilder;
final FooterRetrievalUseCase<FooterType> footerItemsBuilder;
final _bodyItems = BehaviorSubject<List<BodyType>>.seeded([]);
final _headerItems = BehaviorSubject<List<HeaderType>>.seeded([]);
final _footerItems = BehaviorSubject<List<FooterType>>.seeded([]);
final _isLoading = BehaviorSubject<bool>.seeded(false);
final _errors = BehaviorSubject<String>();
Stream<List<BodyType>> _fetchBodyItems(bool reset, QueryType? query) async* {
try {
_isLoading.add(true);
final items = await bodyItemsBuilder(1, 10, query);
yield items.whereType<BodyType>().toList();
} catch (e) {
_errors.add(e.toString());
} finally {
_isLoading.add(false);
}
}
Stream<List<HeaderType>> _fetchHeaderItems() async* {
try {
_isLoading.add(true);
final items = await headerItemsBuilder();
yield items.whereType<HeaderType>().toList();
} catch (e) {
_errors.add(e.toString());
} finally {
_isLoading.add(false);
}
}
Stream<List<FooterType>> _fetchFooterItems() async* {
try {
_isLoading.add(true);
final items = await footerItemsBuilder();
yield items.whereType<FooterType>().toList();
} catch (e) {
_errors.add(e.toString());
} finally {
_isLoading.add(false);
}
}
void filterBodyItems(QueryType query) {
_$loadBodyItemsEvent.add((query: query, reset: true));
}
void filterHeaderItems(QueryType query) {
_$loadHeaderItemsEvent.add(null);
}
void filterFooterItems(QueryType query) {
_$loadFooterItemsEvent.add(null);
}
@override
void dispose() {
_bodyItems.close();
_headerItems.close();
_footerItems.close();
_isLoading.close();
_errors.close();
super.dispose();
}
@override
Stream<List<BodyType>> _mapToBodyItemsState() => _bodyItems.stream;
@override
Stream<String> _mapToErrorsState() => _errors.stream;
@override
Stream<List<FooterType>> _mapToFooterItemsState() => _footerItems.stream;
@override
Stream<List<HeaderType>> _mapToHeaderItemsState() => _headerItems.stream;
@override
Stream<bool> _mapToIsLoadingState() => _isLoading.stream;
}
abstract class EnhancedListViewBlocType extends RxBlocTypeBase {
EnhancedListViewEvents get events;
EnhancedListViewStates get states;
}
abstract class $EnhancedListViewBloc<BodyType, HeaderType, FooterType,
QueryType> extends RxBlocBase
implements
EnhancedListViewEvents,
EnhancedListViewStates,
EnhancedListViewBlocType {
final _compositeSubscription = CompositeSubscription();
/// Тhe [Subject] where events sink to by calling [loadBodyItems]
final _$loadBodyItemsEvent = PublishSubject<({bool reset, dynamic query})>();
/// Тhe [Subject] where events sink to by calling [loadHeaderItems]
final _$loadHeaderItemsEvent = PublishSubject<void>();
/// Тhe [Subject] where events sink to by calling [loadFooterItems]
final _$loadFooterItemsEvent = PublishSubject<void>();
/// The state of [bodyItems] implemented in [_mapToBodyItemsState]
late final Stream<List<BodyType>> _bodyItemsState = _mapToBodyItemsState();
/// The state of [headerItems] implemented in [_mapToHeaderItemsState]
late final Stream<List<HeaderType>> _headerItemsState =
_mapToHeaderItemsState();
/// The state of [footerItems] implemented in [_mapToFooterItemsState]
late final Stream<List<FooterType>> _footerItemsState =
_mapToFooterItemsState();
/// The state of [isLoading] implemented in [_mapToIsLoadingState]
late final Stream<bool> _isLoadingState = _mapToIsLoadingState();
/// The state of [errors] implemented in [_mapToErrorsState]
late final Stream<String> _errorsState = _mapToErrorsState();
@override
void loadBodyItems({
bool reset = false,
dynamic query = null,
}) =>
_$loadBodyItemsEvent.add((
reset: reset,
query: query,
));
@override
void loadHeaderItems() => _$loadHeaderItemsEvent.add(null);
@override
void loadFooterItems() => _$loadFooterItemsEvent.add(null);
@override
Stream<List<BodyType>> get bodyItems => _bodyItemsState;
@override
Stream<List<HeaderType>> get headerItems => _headerItemsState;
@override
Stream<List<FooterType>> get footerItems => _footerItemsState;
@override
Stream<bool> get isLoading => _isLoadingState;
@override
Stream<String> get errors => _errorsState;
Stream<List<BodyType>> _mapToBodyItemsState();
Stream<List<HeaderType>> _mapToHeaderItemsState();
Stream<List<FooterType>> _mapToFooterItemsState();
Stream<bool> _mapToIsLoadingState();
Stream<String> _mapToErrorsState();
@override
EnhancedListViewEvents get events => this;
@override
EnhancedListViewStates get states => this;
@override
void dispose() {
_$loadBodyItemsEvent.close();
_$loadHeaderItemsEvent.close();
_$loadFooterItemsEvent.close();
_compositeSubscription.dispose();
super.dispose();
}
}
// ignore: unused_element
typedef _LoadBodyItemsEventArgs = ({bool reset, dynamic query});

View File

@ -0,0 +1,81 @@
// class EnhancedSearchView<QueryType> extends StatelessWidget {
// const EnhancedSearchView({
// super.key,
// required this.filter,
// required this.cast,
// });
// final void Function(QueryType query) filter;
// final QueryType Function(String query) cast;
// @override
// Widget build(BuildContext context) {
// final theme = FlutterFlowTheme.of(context);
// final locale = FFLocalizations.of(context);
// TextEditingController controller = TextEditingController();
// return TextFormField(
// controller: controller,
// onChanged: (value) => EasyDebounce.debounce(
// '_model.keyTextFieldTextController',
// const Duration(milliseconds: 500),
// () => filter.call(cast.call(value)),
// ),
// cursorColor: theme.primaryText,
// showCursor: false,
// cursorWidth: 2.0,
// cursorRadius: Radius.circular(100),
// style: TextStyle(
// color: theme.primaryText,
// fontSize: 16.0,
// decorationColor: Colors.amber,
// ),
// keyboardType: TextInputType.text,
// textInputAction: TextInputAction.search,
// autocorrect: true,
// textCapitalization: TextCapitalization.sentences,
// decoration: InputDecoration(
// prefixIcon: Icon(Icons.search, color: theme.primary),
// labelText: locale.getVariableText(
// ptText: 'Pesquisar',
// enText: 'Search',
// ),
// labelStyle: TextStyle(
// color: theme.primaryText,
// fontSize: 16.0,
// ),
// hintText: locale.getVariableText(
// ptText: 'Digite sua pesquisa',
// enText: 'Enter your search',
// ),
// hintStyle: TextStyle(
// color: theme.accent2,
// fontSize: 14.0,
// ),
// filled: true,
// fillColor: Colors.transparent,
// helperStyle: TextStyle(
// color: theme.primaryText,
// decorationColor: theme.primaryText,
// ),
// focusColor: theme.primaryText,
// contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
// enabledBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// focusedBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// errorBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// focusedErrorBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText, width: 2.0),
// ),
// ),
// );
// }
// }

View File

@ -0,0 +1 @@
abstract class Entity<T> {}

View File

@ -0,0 +1,322 @@
// typedef SearchKey = GlobalKey<EnhancedRemoteListViewState>;
// typedef Query<X extends Archive> = X?;
// /// -----------------------------------------------
// /// [EnhancedListView]
// /// -----------------------------------------------
// abstract interface class EnhancedListView<T> extends StatefulWidget {
// const EnhancedListView({super.key});
// }
// abstract interface class EnhancedListViewState<T>
// extends State<EnhancedListView> {}
// /// -----------------------------------------------
// /// [EnhancedLocalListView]
// /// -----------------------------------------------
// class EnhancedLocalListView<T> extends EnhancedListView<T> {
// final List<T> list;
// final Widget Function(T) itemBuilder;
// final bool Function(T, String) filter;
// final Widget header;
// final List<T> Function(String)? onSearch;
// EnhancedLocalListView({
// Key? key,
// required this.list,
// required this.itemBuilder,
// required this.filter,
// List<T> Function(String)? onSearch,
// Widget? header,
// }) : header = header ?? const SizedBox.shrink(),
// onSearch = onSearch ??
// ((String query) =>
// list.where((documents) => filter(documents, query)).toList()),
// super(key: key);
// // return documents.where((documents) => filter(documents, query)).toList();
// @override
// EnhancedLocalListViewState<T> createState() =>
// EnhancedLocalListViewState<T>();
// }
// class EnhancedLocalListViewState<T> extends State<EnhancedLocalListView<T>> {
// TextEditingController editingController = TextEditingController();
// late List<T> filteredItems;
// @override
// void initState() {
// filteredItems = widget.list;
// super.initState();
// }
// @override
// Widget build(BuildContext context) {
// void filter(value) {
// safeSetState(() {
// filteredItems = widget.onSearch!(value);
// });
// }
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: <Widget>[
// Expanded(
// child: ListView.builder(
// shrinkWrap: true,
// itemCount: filteredItems.length + 1,
// itemBuilder: (context, index) {
// if (index == 0) return widget.header;
// return widget.itemBuilder(filteredItems[index - 1]);
// },
// ),
// ),
// Padding(
// padding: const EdgeInsets.all(30.0),
// child: TextFormField(
// controller: editingController,
// onChanged: filter,
// cursorColor: Colors.black,
// cursorWidth: 2.0,
// cursorRadius: Radius.circular(2.0),
// style: TextStyle(
// color: Colors.black,
// fontSize: 16.0,
// ),
// keyboardType: TextInputType.text,
// textInputAction: TextInputAction.search,
// autocorrect: true,
// textCapitalization: TextCapitalization.sentences,
// decoration: InputDecoration(
// prefixIcon: Icon(Icons.search, color: Colors.black),
// labelText: 'Pesquisar',
// labelStyle: TextStyle(
// color: Colors.black,
// fontSize: 16.0,
// ),
// hintText: 'Digite sua pesquisa',
// hintStyle: TextStyle(
// color: Colors.grey,
// fontSize: 14.0,
// ),
// filled: true,
// fillColor: Colors.white,
// contentPadding:
// EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
// enabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: Colors.black),
// ),
// focusedBorder: OutlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: Colors.blue),
// ),
// errorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: Colors.red),
// ),
// focusedErrorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: Colors.red, width: 2.0),
// ),
// ),
// )),
// ],
// );
// }
// }
// /// -----------------------------------------------
// /// [EnhancedRemoteListView]
// /// -----------------------------------------------
// // ignore: must_be_immutable
// class EnhancedRemoteListView<T, Y> extends EnhancedListView<T> {
// final Widget Function(BuildContext, T, int) bodyBuilder;
// final Future<List<Y?>> Function() headerItems;
// Widget Function<T>(Future<List<T?>> Function() gen) headerBuilder;
// final PagingController<int, T> pagingController;
// final Future<(bool, List<T?>?)> Function(int pageKey, Query query)
// dataProvider;
// final void Function(Object, StackTrace) onFetchError;
// EnhancedRemoteListView({
// Key? key,
// // required this.fetchItems,
// required this.bodyBuilder,
// required this.headerItems,
// required this.headerBuilder,
// required this.pagingController,
// required this.dataProvider,
// required this.onFetchError,
// }) : super(key: key);
// @override
// EnhancedRemoteListViewState<T, Y> createState() =>
// EnhancedRemoteListViewState<T, Y>();
// }
// class EnhancedRemoteListViewState<T, Y>
// extends State<EnhancedRemoteListView<T, Y>> with Pageable {
// TextEditingController editingController = TextEditingController();
// bool isLoading = false;
// Query query = Document.fromDesc('');
// @override
// void initState() {
// widget.pagingController.addPageRequestListener(
// (page) => fetchPage(
// dataProvider: () async => await widget.dataProvider(page, query),
// onDataUnavailable: () => showNoMoreDataSnackBar(context),
// onDataAvailable: (data) =>
// widget.pagingController.appendLastPage(data),
// onFetchError: (e, s) => widget.onFetchError),
// );
// widget.pagingController.addStatusListener(_showError);
// super.initState();
// }
// Future<void> _showError(PagingStatus status) async {
// if (status == PagingStatus.subsequentPageError) {
// final message = FFLocalizations.of(context).getVariableText(
// enText: 'Something went wrong while fetching a new page.',
// ptText: 'Algo deu errado ao buscar uma nova página.',
// );
// final retry = FFLocalizations.of(context).getVariableText(
// enText: 'Retry',
// ptText: 'Recarregar',
// );
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(message),
// action: SnackBarAction(
// label: retry,
// onPressed: () => widget.pagingController.retryLastFailedRequest(),
// ),
// ),
// );
// }
// }
// void filter(Query data) async {
// if (data is Category) {
// safeSetState(() => query = Category(
// id: data.id,
// color: data.color,
// title: data.title,
// ));
// widget.pagingController.refresh();
// } else if (data is Document) {
// safeSetState(() => query = data);
// widget.pagingController.refresh();
// } else {
// safeSetState(() {
// query = Document.fromDesc('');
// });
// widget.pagingController.refresh();
// }
// }
// @override
// Widget build(BuildContext context) {
// final noDataFound = FFLocalizations.of(context).getVariableText(
// ptText: "Nenhum item encontrado!",
// enText: "No item found",
// );
// final theme = FlutterFlowTheme.of(context);
// final locale = FFLocalizations.of(context);
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: <Widget>[
// buildPaginatedListView<int, T, Y>(
// noDataFound,
// widget.pagingController,
// widget.headerItems,
// widget.headerBuilder,
// widget.bodyBuilder,
// ),
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: TextFormField(
// controller: editingController,
// onChanged: (value) => EasyDebounce.debounce(
// '_model.keyTextFieldTextController',
// const Duration(milliseconds: 500),
// () => filter(Document.fromDesc(value)),
// ),
// cursorColor: theme.primaryText,
// showCursor: false,
// cursorWidth: 2.0,
// cursorRadius: Radius.circular(100),
// style: TextStyle(
// color: theme.primaryText,
// fontSize: 16.0,
// decorationColor: Colors.amber,
// ),
// keyboardType: TextInputType.text,
// textInputAction: TextInputAction.search,
// autocorrect: true,
// textCapitalization: TextCapitalization.sentences,
// decoration: InputDecoration(
// prefixIcon: Icon(Icons.search, color: theme.primary),
// labelText: locale.getVariableText(
// ptText: 'Pesquisar',
// enText: 'Search',
// ),
// labelStyle: TextStyle(
// color: theme.primaryText,
// fontSize: 16.0,
// ),
// hintText: locale.getVariableText(
// ptText: 'Digite sua pesquisa',
// enText: 'Enter your search',
// ),
// hintStyle: TextStyle(
// color: theme.accent2,
// fontSize: 14.0,
// ),
// filled: true,
// fillColor: Colors.transparent,
// helperStyle: TextStyle(
// color: theme.primaryText,
// decorationColor: theme.primaryText,
// ),
// focusColor: theme.primaryText,
// contentPadding:
// EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
// enabledBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// focusedBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// errorBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText),
// ),
// focusedErrorBorder: UnderlineInputBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// borderSide: BorderSide(color: theme.primaryText, width: 2.0),
// ),
// ),
// ),
// ),
// ],
// );
// }
// }

View File

@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
class ModelWidget extends Widget {
const ModelWidget({super.key});
@override
Element createElement() {
// TODO: implement createElement
throw UnimplementedError();
}
}

View File

@ -0,0 +1,26 @@
import 'package:flutter/widgets.dart';
import 'package:hub/shared/mixins/template_mixin.dart';
import 'package:hub/shared/widgets.dart';
/// [PageWidget]
abstract class PageWidget<T> extends Widget {
const PageWidget({super.key});
}
abstract class ModelPage<T> extends ModelWidget implements PageWidget<T> {
const ModelPage({super.key});
}
abstract class StatelessPage<T> extends StatelessWidget
with Template
implements PageWidget<T> {
const StatelessPage({super.key});
}
abstract class StatefulPage<T> extends StatefulWidget implements PageWidget<T> {
const StatefulPage({super.key});
}
abstract class PageState<T extends StatefulPage> extends State<T>
with Template {}

View File

@ -0,0 +1,183 @@
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
// Removed unnecessary import
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/widgets.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdfx/pdfx.dart';
import 'package:share_plus/share_plus.dart';
import 'package:http/http.dart' as http;
typedef ReadViewController = PdfController;
typedef DocumentType = PdfDocument;
abstract interface class Viewer extends StatelessComponent {
final String src;
const Viewer({
super.key,
required this.src,
});
@override
Widget build(BuildContext context) {
return buildViewer(context);
}
Widget buildViewer(BuildContext context);
}
class ReadView extends StatefulWidget {
final String url;
final String title;
final VoidCallback onError;
const ReadView({
super.key,
required this.onError,
required this.url,
required this.title,
});
@override
State<ReadView> createState() => ReadViewState();
}
class ReadViewState extends State<ReadView> {
Future<ReadViewController> _initializePdf() async {
try {
final file = await downloadPdf(widget.url);
final Future<DocumentType> document = DocumentType.openFile(file.path);
return ReadViewController(document: document);
} catch (e) {
final message = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao baixar o PDF',
enText: 'Error downloading PDF',
);
return Future.error(message);
}
}
Future<File> downloadPdf(String url) async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final bytes = response.bodyBytes;
final dir = await getTemporaryDirectory();
final file = File('${dir.path}/downloaded.pdf');
await file.writeAsBytes(bytes);
return file;
} else {
throw Exception('Falha ao baixar o PDF');
}
} catch (e) {
final message = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao baixar o PDF',
enText: 'Error downloading PDF',
);
await throwError(message, e);
rethrow;
}
}
Future<void> throwError(String message, dynamic error) async {
log('$message: $error');
await DialogUtil.error(context, message)
.whenComplete(() => widget.onError());
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
_buildPDFViewer(context),
buildShareButton(context),
],
);
}
Positioned buildShareButton(BuildContext context) {
final theme = FlutterFlowTheme.of(context);
return Positioned(
bottom: 10,
right: 10,
child: IconButton(
icon: Icon(
Icons.share,
color: theme.primaryText,
),
color: theme.primaryText,
onPressed: onShare,
),
);
}
Future<void> onShare() async {
try {
final Uri uri = Uri.parse(widget.url);
final response = await http.get(uri);
if (response.statusCode == 200) {
final XFile xfile = XFile.fromData(response.bodyBytes,
name: '${widget.title}.pdf', mimeType: 'application/pdf');
await Share.shareXFiles([xfile],
text: 'Confira este PDF!',
fileNameOverrides: ['${widget.title}.pdf']);
} else {
throw Exception(
'Erro ao compartilhar o arquivo: ${response.statusCode}');
}
} catch (e) {
final message = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao compartilhar o arquivo',
enText: 'Error sharing file',
);
await throwError(message, e);
}
}
Widget buildLoadingIndicator(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 15),
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
);
}
Widget _buildPDFViewer(BuildContext context) => Padding(
padding: EdgeInsets.all(10),
child: FutureBuilder<ReadViewController>(
future: _initializePdf(),
builder: (context, snapshot) {
if (!snapshot.hasData) return buildLoadingIndicator(context);
if (snapshot.error != null) {
return buildLoadingIndicator(context);
}
if (snapshot.connectionState == ConnectionState.waiting) {
return buildLoadingIndicator(context);
}
return PdfView(
controller: snapshot.data!,
renderer: (PdfPage page) => page.render(
width: page.width * 2,
height: page.height * 2,
cropRect: Rect.fromLTWH(
10.0, 10.0, page.width * 2, page.height * 2),
forPrint: false,
quality: 100,
format: PdfPageImageFormat.jpeg,
backgroundColor: '#ffffff',
),
scrollDirection: Axis.vertical,
);
}),
);
}

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:hub/shared/mixins/template_mixin.dart';
import 'package:hub/shared/widgets.dart';
abstract class ScreenWidget<T> extends Widget {
const ScreenWidget({super.key});
}
abstract class ModelScreen<T> extends ModelWidget implements ScreenWidget<T> {
const ModelScreen({super.key});
}
abstract class StatelessScreen<T> extends StatelessWidget
with Template
implements ScreenWidget<T> {
const StatelessScreen({super.key});
}
abstract class StatefulScreen<T> extends StatefulWidget
implements ScreenWidget<T> {
const StatefulScreen({super.key});
}
abstract class ScreenState<T extends StatefulScreen> extends State<T>
with Template {}

Some files were not shown because too many files have changed in this diff Show More