This commit is contained in:
jantunemesssias 2025-01-31 14:30:52 -03:00
parent bc16df866a
commit 268c4c897b
46 changed files with 713 additions and 462 deletions

29
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,29 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// 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"
]
},
{
"name": "flutter-freaccesss-hub (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "flutter-freaccesss-hub (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

View File

@ -7,13 +7,10 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart';
import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/components/templates_components/forgot_password_template_component/forgot_password_template_component_widget.dart';
import 'package:hub/features/backend/api_requests/index.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart';
@ -23,14 +20,10 @@ import 'package:hub/features/notification/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/index.dart' as ff;
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/initialization.dart';
import 'package:hub/main.dart';
import 'package:hub/pages/forgot_password_page/forgot_password_screen.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicle_model.dart';
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:patrol/patrol.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'app_test.dart';

View File

@ -34,7 +34,7 @@ class AuthenticationTest {
);
Map<String, String> concat(String username, String domain, String password) {
return {
'emailTextFormField': '${username}@${domain}.test',
'emailTextFormField': '$username@$domain.test',
'passwordTextFormField': password,
};
}
@ -138,7 +138,7 @@ class AuthenticationTest {
Map<String, String> concat(String name, String username, String domain, String password) {
return {
'nameTextFormField': name,
'emailTextFormField': '${username}@${domain}.test',
'emailTextFormField': '$username@$domain.test',
'passwordTextFormField': password,
};
}

View File

@ -150,6 +150,7 @@ class _CustomInputUtilState extends State<CustomInputUtil> {
maxLines: null,
maxLength: widget.haveMaxLength ? widget.maxLength : null,
keyboardType: widget.keyboardType,
inputFormatters: [
LengthLimitingTextInputFormatter(widget.maxLength),
],

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

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hub/shared/utils/limited_text_size.dart';
class ToastUtil {
static void showToast({

View File

@ -195,6 +195,7 @@ class _BottomArrowLinkedLocalsComponentWidgetState extends State<BottomArrowLink
return CardItemTemplateComponentWidget(
key: ValueKey<String>(local['CLI_NOME']),
imagePath: _imagePath(local),
icon: null,
labelsHashMap: _labelsHashMap(local),
statusHashMap: [_statusHashMap(local)],
onTapCardItemAction: () async {

View File

@ -12,18 +12,73 @@ import 'card_item_template_component_model.dart';
export 'card_item_template_component_model.dart';
class FreCardIcon extends StatelessWidget {
final double height;
final double width;
final Icon icon;
const FreCardIcon({
super.key,
required this.height,
required this.width,
required this.icon,
});
@override
Widget build(BuildContext context) {
return SizedBox(
height: height,
width: width,
child: icon,
);
}
}
class FreCardPin extends StatelessWidget {
final double height;
final double width;
final Color color;
const FreCardPin({
super.key,
required this.height,
required this.width,
required this.color,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: height,
width: width,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
),
);
}
}
class CardItemTemplateComponentWidget extends StatefulWidget {
const CardItemTemplateComponentWidget({
super.key,
required this.labelsHashMap,
required this.statusHashMap,
required this.imagePath,
this.imagePath,
this.icon,
this.pin,
required this.onTapCardItemAction,
});
final Map<String, String>? labelsHashMap;
final List<Map<String, Color>?> statusHashMap;
final String? imagePath;
final FreCardIcon? icon;
final FreCardPin? pin;
final Future Function()? onTapCardItemAction;
@override
@ -124,8 +179,25 @@ class _CardItemTemplateComponentWidgetState
);
}
Widget _generateIcon() {
return Column(
children: [
widget.icon!,
],
);
}
Widget _generatePin() {
return widget.pin!;
}
List<Widget> _generateStatus() {
double limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context);
int statusCount = statusLinkedHashMap.length;
double itemWidthFactor = statusCount == 1 ? 0.5 : 0.25;
return statusLinkedHashMap.expand((statusLinked) {
return statusLinked.entries.map((entry) {
final text = entry.key;
@ -135,7 +207,7 @@ class _CardItemTemplateComponentWidgetState
message: text,
child: Container(
padding: const EdgeInsets.all(5),
width: MediaQuery.of(context).size.width * 0.25,
width: MediaQuery.of(context).size.width * itemWidthFactor,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(5),
@ -161,38 +233,54 @@ class _CardItemTemplateComponentWidgetState
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 360) {
return Row(
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
..._generateLabels(),
SizedBox(height: 3),
Wrap(
spacing: 8,
runSpacing: 4,
children: _generateStatus(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [if(widget.pin != null) _generatePin()]),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
..._generateLabels(),
Wrap(
spacing: 8,
runSpacing: 4,
children: _generateStatus(),
),
]
.addToEnd(const SizedBox(height: 5))
.divide(const SizedBox(height: 3))
.addToStart(const SizedBox(height: 5)),
),
]
.addToEnd(const SizedBox(height: 5))
.divide(const SizedBox(height: 1))
.addToStart(const SizedBox(height: 5)),
),
),
if(widget.icon != null) _generateIcon(),
if (widget.imagePath != null) _generateImage()
]
.addToEnd(const SizedBox(width: 10))
.addToStart(const SizedBox(width: 10)),
),
if (widget.imagePath != null) _generateImage(),
]
.addToEnd(const SizedBox(width: 10))
.addToStart(const SizedBox(width: 10)),
.addToStart(SizedBox(height: 5))
.addToEnd(SizedBox(height: 5)),
);
} else {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.imagePath != null) _generateImage(),
if(widget.icon != null) _generateIcon(),
Container(
padding: const EdgeInsets.all(8),
child: Column(

View File

@ -3,6 +3,7 @@ import 'dart:collection';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/components/templates_components/details_component/details_component_model.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
@ -10,10 +11,11 @@ import 'package:hub/shared/utils/limited_text_size.dart';
class DetailsComponentWidget extends StatefulWidget {
const DetailsComponentWidget({
Key? key,
super.key,
required this.labelsHashMap,
required this.statusHashMap,
this.imagePath,
this.icon,
this.onTapCardItemAction,
required this.buttons,
});
@ -23,6 +25,7 @@ class DetailsComponentWidget extends StatefulWidget {
final String? imagePath;
final Future Function()? onTapCardItemAction;
final List<Widget>? buttons;
final FreCardIcon? icon;
@override
State<DetailsComponentWidget> createState() => _DetailsComponentWidgetState();
@ -95,6 +98,16 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
useOldImageOnUrlChange: true,
),
),
if (widget.icon != null && widget.icon != '')
Container(
width: MediaQuery.of(context).size.width * 0.3,
height: MediaQuery.of(context).size.width * 0.3,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
shape: BoxShape.circle,
),
child: widget.icon!,
),
SizedBox(height: MediaQuery.of(context).size.height * 0.03),
Row(
children: statusLinkedHashMap.expand((linkedHashMap) {
@ -109,6 +122,7 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
autofocus: false,
canRequestFocus: false,
readOnly: true,
initialValue: item.key,
obscureText: false,
decoration: InputDecoration(
isDense: true,
@ -120,7 +134,7 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
),
filled: true,
fillColor: item.value,
labelText: item.key,
// labelText: item.key,
labelStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
@ -156,16 +170,20 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
color: FlutterFlowTheme.of(context).info,
),
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,
color: FlutterFlowTheme.of(context).info,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily,
style: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.labelMediumFamily,
fontWeight: FontWeight.bold,
color: FlutterFlowTheme.of(context).info,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily,
),
fontSize: limitedBodyFontSize,
),
fontSize: limitedBodyFontSize,
),
textAlign: TextAlign.center,
maxLines: null,
keyboardType: TextInputType.name,
@ -188,7 +206,7 @@ class _DetailsComponentWidgetState extends State<DetailsComponentWidget> {
// return Text('key: $key, value: $value');
return TextFormField(
readOnly: true,
initialValue: '$value',
initialValue: value,
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,

View File

@ -32,7 +32,6 @@ class LiberationHistoryItemDetailsTemplateComponentModel
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
;
}
@override

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart';

View File

@ -140,7 +140,6 @@ class RegisiterVistorTemplateComponentModel
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
;
}
@override

View File

@ -35,7 +35,7 @@ class RegisiterVistorTemplateComponentWidget extends StatefulWidget {
class _RegisiterVistorTemplateComponentWidgetState
extends State<RegisiterVistorTemplateComponentWidget> {
late RegisiterVistorTemplateComponentModel _model;
bool _isLoading = false;
final bool _isLoading = false;
final scaffoldKey = GlobalKey<ScaffoldState>();
bool _isVisitorRegistered = false;

View File

@ -41,7 +41,6 @@ class ViewVisitDetailModel extends FlutterFlowModel<ViewVisitDetailWidget> {
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
;
}
@override

View File

@ -43,7 +43,6 @@ class VisitorSearchModalTemplateComponentModel
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
;
}
@override

View File

@ -1,4 +1,3 @@
import 'package:meta/meta.dart';
class DeadCode {
final String? desc;

View File

@ -66,6 +66,7 @@ class PhpGroup extends Api {
static GetResidentsByProperty getResidentsByProperty =
GetResidentsByProperty();
static GetOpenedVisits getOpenedVisits = GetOpenedVisits();
@override
GetLicense getLicense = GetLicense();
static GetProvSchedules getProvSchedules = GetProvSchedules();
static RegisterVehicle registerVehicle = RegisterVehicle();
@ -76,7 +77,7 @@ class PhpGroup extends Api {
class CancelVehicle {
Future<ApiCallResponse> call({
required final String vehicleId,
required final int vehicleId,
required final String licensePlate,
required final String model,
required final String color,
@ -118,7 +119,7 @@ class CancelVehicle {
class DeleteVehicle {
Future<ApiCallResponse> call({
required final String vehicleId,
required final int vehicleId,
required final String licensePlate,
required final String model,
required final String color,

View File

@ -3,7 +3,6 @@
import 'package:hub/features/backend/index.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'index.dart';
class DeviceStruct extends BaseStruct {
DeviceStruct({

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';

View File

@ -12,6 +12,8 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class AboutSystemPage extends StatefulWidget {
const AboutSystemPage({super.key});
@override
_AboutSystemPageState createState() => _AboutSystemPageState();
}

View File

@ -4,7 +4,6 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:hub/features/home/presentation/widgets/drawer_widget.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';

View File

@ -58,7 +58,7 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource {
},
conflictAlgorithm: ConflictAlgorithm.replace,
);
} catch (e, s) {}
} catch (e) {}
}
@override

View File

@ -255,7 +255,7 @@ class _LocalProfileComponentWidgetState
),
Tooltip(
message:
valueOrDefault<String>(' ' + state.ownerName, ''),
valueOrDefault<String>(' ${state.ownerName}', ''),
child: Text(
valueOrDefault<String>(
state.ownerName.length > 30

View File

@ -95,6 +95,8 @@ class LocalUtil {
try {
await StorageHelper().set(LocalsStorageKey.whatsapp.key, jsonBody['whatsapp'] ?? false);
await StorageHelper().set(LocalsStorageKey.provisional.key, jsonBody['provisional'] ?? false);
await StorageHelper().set(LocalsStorageKey.vehicleAutoApproval.key, jsonBody['vehicleAutoApproval'] ?? false);
await StorageHelper().set(
LocalsStorageKey.pets.key,
jsonBody['pet'] ?? false,
@ -118,6 +120,11 @@ class LocalUtil {
await StorageHelper().set(LocalsStorageKey.petAmount.key,
jsonBody['petAmountRegister']?.toString().isEmpty ?? true ? '0' : jsonBody['petAmountRegister'].toString());
await StorageHelper().set(LocalsStorageKey.vehicleAmountRegister.key,
jsonBody['vehicleAmountRegister']?.toString().isEmpty ?? true ? '0' : jsonBody['vehicleAmountRegister'].toString());
await StorageHelper().set(ProfileStorageKey.userName.key, jsonBody['visitado']['VDO_NOME'] ?? '');
await StorageHelper().set(ProfileStorageKey.userEmail.key, jsonBody['visitado']['VDO_EMAIL'] ?? '');
await StorageHelper().set(LocalsStorageKey.provisional.key, jsonBody['provisional'] ?? false);

View File

@ -7,9 +7,13 @@ import 'package:material_symbols_icons/symbols.dart';
enum MenuEntryType { Home, Drawer, Property }
class MenuEntry implements BaseModule {
@override
final String key;
@override
final IconData icon;
@override
final String name;
@override
final String route;
final List<MenuEntryType> types;

View File

@ -76,16 +76,15 @@ class _MenuButtonWidgetState extends State<ButtonMenuItem> {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.icon != null)
Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.only(left: 8.0),
child: Icon(
widget.icon,
size: 24.0,
color: FlutterFlowTheme.of(context).primaryText,
),
Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.only(left: 8.0),
child: Icon(
widget.icon,
size: 24.0,
color: FlutterFlowTheme.of(context).primaryText,
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 10.0),

View File

@ -94,7 +94,7 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
Future<bool> isNewVersion() async {
final String? reponse =
await StorageHelper().get(LocalsStorageKey.isNewVersion.key);
final bool isNewVersion = reponse.toBoolean();
final bool isNewVersion = reponse.toBoolean;
return isNewVersion;
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'module_model.dart';

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'module_model.freezed.dart';

View File

@ -1,6 +1,4 @@
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
abstract class BaseModule {
String get key;

View File

@ -61,7 +61,7 @@ class License {
}
static Future<String> _precessWpp() async {
final bool whatsapp = await StorageHelper().get(LocalsStorageKey.whatsapp.key).then((v) => v.toBoolean());
final bool whatsapp = await StorageHelper().get(LocalsStorageKey.whatsapp.key).then((v) => v.toBoolean);
if (whatsapp)
return ModuleStatus.active.key;
else
@ -69,7 +69,7 @@ class License {
}
static Future<String> _processProvisional() async {
final bool provisional = await StorageHelper().get(LocalsStorageKey.provisional.key).then((v) => v.toBoolean());
final bool provisional = await StorageHelper().get(LocalsStorageKey.provisional.key).then((v) => v.toBoolean);
if (provisional)
return ModuleStatus.active.key;
else
@ -77,7 +77,7 @@ class License {
}
static Future<String> _processPets() async {
final bool pets = await StorageHelper().get(LocalsStorageKey.pets.key).then((v) => v.toBoolean());
final bool pets = await StorageHelper().get(LocalsStorageKey.pets.key).then((v) => v.toBoolean);
if (pets)
return ModuleStatus.active.key;
else

View File

@ -1,5 +1,4 @@
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';

View File

@ -1,8 +1,6 @@
import 'dart:developer';
import 'package:hub/features/storage/constants/profile_constants.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/shared/constants/index.dart';
import 'package:sqflite/sqflite.dart';

View File

@ -34,7 +34,9 @@ enum LocalsStorageKey implements DatabaseStorageKey {
panic('fre_panic'),
person('fre_person'),
requestOSNotification('fre_requestOSnotification'),
isNewVersion('fre_isNewVersion');
isNewVersion('fre_isNewVersion'),
vehicleAutoApproval('fre_vehicleAutoApproval'),
vehicleAmountRegister('fre_vehicleAmountRegister');
final String key;

View File

@ -1,7 +1,6 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:hub/features/profile/data/data_sources/profile_local_data_source.dart';
import 'package:hub/features/storage/index.dart';
class StorageHelper implements StorageRepository {

View File

@ -1,6 +1,5 @@
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:flutter/material.dart';
import 'package:auto_size_text/auto_size_text.dart';
class FFButtonOptions {
const FFButtonOptions({

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_core/firebase_core.dart';

View File

@ -14,7 +14,6 @@ import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/test_util.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'initialization.dart';

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:flutter/material.dart';

View File

@ -29,7 +29,7 @@ class _ResidentsOnThePropertyState extends State<ResidentsOnTheProperty>
late final ResidentsOnThePropertyModel model;
late Future<void> _future;
List<dynamic> _wrap = [];
final List<dynamic> _wrap = [];
@override
void initState() {

View File

@ -18,6 +18,7 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
int _pageNumber = 1;
bool _hasData = false;
bool _loading = false;
int count = 0;
@override
@ -28,7 +29,8 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
_future = _fetchVisits();
_scrollController = ScrollController()
..addListener(() {
if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) {
if (_scrollController.position.atEdge &&
_scrollController.position.pixels != 0) {
_loadMore();
}
});
@ -53,59 +55,101 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
);
}
String getRandomStatus() {
var statuses = ['ATI', 'INA', 'APR_CREATE', 'APR_DELETE', 'APR_UPDATE', 'AGU_CHANGE'];
String mockRandomMapStatusColor() {
var statuses = [
'ATI',
'INA',
'APR_CREATE',
'APR_DELETE',
'APR_UPDATE',
'AGU_CHANGE'
];
statuses.shuffle();
return statuses.first;
}
Widget _item(BuildContext context, Map<String, dynamic> uItem) {
uItem['status'] = getRandomStatus();
return CardItemTemplateComponentWidget(
imagePath: null,
labelsHashMap: {
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
uItem['licensePlate'] ?? '',
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:': uItem['model'] ?? '',
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:': uItem['tag'] ?? '',
},
statusHashMap: [widget.model.generateStatusColorMap(uItem)],
onTapCardItemAction: () async {
await showDialog(
useSafeArea: true,
context: context,
builder: (context) {
return Dialog(
alignment: Alignment.center,
child: widget.model.buildVehicleDetails(
Future<Widget> _item(BuildContext context, Map<String, dynamic> uItem) async {
// uItem['status'] = mockRandomMapStatusColor();
final bool? isOwner = uItem['isOwnerVehicle'];
late final IconData? iconData;
late final FreCardIcon? cardIcon;
if(isOwner is bool) {
iconData = isOwner ? Symbols.no_crash :Symbols.directions_car;
cardIcon = FreCardIcon(height: 50, width: 100, icon: Icon(iconData, size: 80, opticalSize: 10));
}
final String? tag = uItem['tag'];
final bool containTag = tag.isNotNullAndEmpty;
final Map<String, String> labelsHashMap = {
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
uItem['licensePlate'] ?? '',
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
uItem['model'] ?? '',
'${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:':
uItem['personName'] ?? '',
if (containTag)
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:':
uItem['tag'] ?? '',
};
final List<Map<String, Color>?> statusHashMap = [
await widget.model.generateStatusColorMap(uItem, 2)
];
Future<Future Function()?> onTapCardItemAction() async {
await showDialog(
useSafeArea: true,
context: context,
builder: (context) {
return Dialog(
alignment: Alignment.center,
child: FutureBuilder<Widget>(
future: widget.model.buildVehicleDetails(
icon: isOwner is bool ? cardIcon : null,
item: uItem,
context: context,
model: widget.model,
));
},
).whenComplete(() {
safeSetState(() {
_pageNumber = 1;
_wrap = [];
_future = _fetchVisits().then((value) => value!.jsonBody['vehicles'] ?? []);
});
}).catchError((e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículos", e, s);
safeSetState(() {
_hasData = false;
_loading = false;
});
),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return snapshot.data ?? Container();
} else {
return Center(child: CircularProgressIndicator());
}
},
));
},
).whenComplete(() {
safeSetState(() {
_pageNumber = 1;
_wrap = [];
_future =
_fetchVisits().then((value) => value!.jsonBody['vehicles'] ?? []);
});
},
);
}).catchError((e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículos", e, s);
safeSetState(() {
_hasData = false;
_loading = false;
});
});
return null;
return null;
}
return CardItemTemplateComponentWidget(
icon: cardIcon,
labelsHashMap: labelsHashMap,
statusHashMap: statusHashMap,
onTapCardItemAction: onTapCardItemAction);
}
Future<ApiCallResponse?> _fetchVisits() async {
try {
setState(() => _loading = true);
var response = await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString());
var response =
await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString());
final List<dynamic> vehicles = response.jsonBody['vehicles'] ?? [];
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);
@ -130,7 +174,8 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
return null;
} catch (e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s);
LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículo", e, s);
setState(() {
_hasData = false;
_loading = false;
@ -149,7 +194,10 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
@override
Widget build(BuildContext context) {
late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context);
late final limitedHeaderTextSize =
LimitedFontSizeUtil.getHeaderFontSize(context);
late final double limitedBodyTextSize =
LimitedFontSizeUtil.getBodyFontSize(context);
return Column(
mainAxisSize: MainAxisSize.max,
@ -192,13 +240,30 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
return Padding(
padding: const EdgeInsets.only(right: 30, top: 10),
child: Text(
'',
(widget.model.amountRegister == '0' ||
widget.model.amountRegister == null)
? ''
: "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Pets: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/$count",
textAlign: TextAlign.right,
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedBodyTextSize,
),
),
);
} else {
Map<String, dynamic> item = _wrap[index - 1];
return _item(context, item);
return FutureBuilder<Widget>(
future: _item(context, item),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return snapshot.data ?? Container();
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
});
},

View File

@ -1,10 +1,13 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
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';
/// [VehicleModel] is a class that contains the business logic of the vehicle page.
@ -39,7 +42,7 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
textFieldControllerModel = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) async {
vehicleAmountRegister = 0;
amountRegister = '0';
});
}
@ -57,7 +60,10 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
final GlobalKey<FormState> registerFormKey = GlobalKey<FormState>();
final GlobalKey<FormState> updateFormKey = GlobalKey<FormState>();
Future<void> initAsync() async {}
Future<void> initAsync() async {
amountRegister = await StorageHelper().get(LocalsStorageKey.vehicleAmountRegister.key);
}
bool isFormValid(BuildContext context) {
if (registerFormKey.currentState == null) return false;
@ -75,7 +81,7 @@ mixin class _BaseVehiclePage {
bool isEditing = false;
String? vehicleId;
ApiCallResponse? vehicleResponse;
late final vehicleAmountRegister;
String? amountRegister = '0';
VoidCallback? onUpdateVehicle;
VoidCallback? onRegisterVehicle;
@ -93,9 +99,9 @@ mixin class _BaseVehiclePage {
}
// (ABC-1234)
final brazilianPlateRegex = RegExp(r'^[A-Z]{3}-\d{4}$');
final brazilianPlateRegex = RegExp(r'^[A-Z]{3}\d{4}$');
// (ABC1D23)
final mercosurPlateRegex = RegExp(r'^[A-Z]{3}\d[A-Z]\d{2}$');
final mercosurPlateRegex = RegExp(r'^[A-Z]{3}\d[A-Z0-9]\d{2}$');
if (!brazilianPlateRegex.hasMatch(value) &&
!mercosurPlateRegex.hasMatch(value)) {
@ -165,316 +171,6 @@ mixin class _BaseVehiclePage {
}
}
/// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page.
mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
Map<String, Color>? generateStatusColorMap(dynamic uItem) {
final autoApproval = uItem['autoApproval'];
if (autoApproval == true) return null;
final statusMap = {
"ATI": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Ativo',
enText: 'Active',
),
"color": FlutterFlowTheme.of(context).success,
},
"INA": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Inativo',
enText: 'Inactive',
),
"color": FlutterFlowTheme.of(context).accent2,
},
"APR_CREATE": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Criando',
enText: 'Creating',
),
"color": FlutterFlowTheme.of(context).success,
},
"APR_DELETE": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Deletando',
enText: 'Deleting',
),
"color": FlutterFlowTheme.of(context).error,
},
"APR_UPDATE": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Atualizando',
enText: 'Updating',
),
"color": FlutterFlowTheme.of(context).warning,
},
"AGU_CHANGE": {
"text": FFLocalizations.of(context).getVariableText(
ptText: 'Aguardando',
enText: 'Waiting',
),
"color": FlutterFlowTheme.of(context).accent2,
},
};
final status = uItem['status'];
if (statusMap.containsKey(status)) {
return {
statusMap[status]!['text'] as String:
statusMap[status]!['color'] as Color,
};
}
return {};
}
List<FFButtonWidget>? generateActionButtons(dynamic item) {
final Color iconButtonColor = FlutterFlowTheme.of(context).primaryText;
final FFButtonOptions buttonOptions = FFButtonOptions(
height: 40,
color: FlutterFlowTheme.of(context).primaryBackground,
elevation: 0,
textStyle: TextStyle(
color: FlutterFlowTheme.of(context).primaryText,
fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15),
),
splashColor: FlutterFlowTheme.of(context).success,
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).primaryBackground,
width: 1,
),
);
final updateText = FFLocalizations.of(context)
.getVariableText(ptText: 'Editar', enText: 'Edit');
final updateIcon = Icon(Icons.edit, color: iconButtonColor);
Future updateOnPressed() async {
context.pop();
isEditing = true;
switchTab(1);
setEditForm(item);
}
final cancelText = FFLocalizations.of(context)
.getVariableText(ptText: 'Cancelar', enText: 'Cancel');
final cancelIcon = Icon(Icons.close, color: iconButtonColor);
Future cancelOnPressed() async {
showAlertDialog(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Cancelar Solicitação',
enText: 'Cancel Request',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Você tem certeza que deseja cancelar essa solicitação?',
enText: 'Are you sure you want to delete this request?',
),
() async => await processCancelRequest(item['status'], item),
);
}
final deleteText = FFLocalizations.of(context)
.getVariableText(ptText: 'Excluir', enText: 'Delete');
final deleteIcon = Icon(Icons.delete, color: iconButtonColor);
Future deleteOnPressed() async {
showAlertDialog(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Excluir Veículo',
enText: 'Delete Vehicle',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Você tem certeza que deseja excluir esse veículo?',
enText: 'Are you sure you want to delete this vehicle?',
),
() async => await processDeleteRequest(item),
);
}
return [
if (item['status'].contains('AGU'))
FFButtonWidget(
text: updateText,
icon: updateIcon,
onPressed: updateOnPressed,
options: buttonOptions,
),
if (item['status'].contains('APR') || item['status'].contains('AGU'))
FFButtonWidget(
text: cancelText,
icon: cancelIcon,
onPressed: cancelOnPressed,
options: buttonOptions,
),
if (item['status'].contains('ATI'))
FFButtonWidget(
text: deleteText,
icon: deleteIcon,
onPressed: deleteOnPressed,
options: buttonOptions,
),
];
}
Future<void> processDeleteRequest(dynamic item) async {
int id = item['vehicleId'];
await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
).then((value) {
context.pop(value);
context.pop(value);
// ignore: unrelated_type_equality_checks
if (value == false) {
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao excluir veículo',
enText: 'Error deleting vehicle',
),
true,
);
// ignore: unrelated_type_equality_checks
} else if (value == true) {
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Success deleting vehicle',
ptText: 'Succeso ao excluir veículo',
),
false,
);
}
}).catchError((err, stack) {
context.pop();
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Error deleting vehicle',
ptText: 'Erro ao excluir veículo',
),
true,
);
});
}
Future<void> processCancelRequest(String status, dynamic item) async {
late final ApiCallResponse value;
try {
switch (status) {
case 'APR_CREATE':
value = await processCancelDeleteRequest(item);
break;
case 'AGU_CHANGE':
value = await processCancelUpdateRequest(item);
break;
case 'APR_DELETE':
value = await processCancelCreateRequest(item);
break;
default:
break;
}
context.pop(value);
context.pop(value);
if (value.jsonBody['error'] == false) {
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao cancelar solicitação',
enText: 'Error canceling request',
),
true,
);
} else if (value.jsonBody['error'] == true) {
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Success canceling request',
ptText: 'Succeso ao cancelar solicitação',
),
false,
);
}
} catch (err) {
context.pop();
showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Error canceling request',
ptText: 'Erro ao cancelar solicitação',
),
true,
);
}
}
Future<ApiCallResponse> processCancelDeleteRequest(dynamic item) async {
return await PhpGroup.cancelVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Future<ApiCallResponse> processCancelCreateRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Map<String, String> generateLabelsHashMap(dynamic item) {
return {
if (item['model'] != null && item['model'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
item['model'].toString().toUpperCase(),
if (item['licensePlate'] != null && item['licensePlate'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
item['licensePlate'].toString().toUpperCase(),
if (item['color'] != null && item['color'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Cor", enText: "Color")}:':
item['color'].toString().toUpperCase(),
if (item['personName'] != null && item['personName'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:':
item['personName'].toString().toUpperCase(),
if (item['tag'] != null && item['tag'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:':
item['tag'].toString().toUpperCase(),
};
}
Widget buildVehicleDetails({
required dynamic item,
required BuildContext context,
required VehicleModel model,
}) {
final status = generateStatusColorMap(item);
final buttons = generateActionButtons(item);
final labels = generateLabelsHashMap(item);
return DetailsComponentWidget(
buttons: buttons,
labelsHashMap: labels,
statusHashMap: [status],
);
}
}
/// [_VehicleRegisterScreenModel] is a mixin that contains the business logic of the vehicle register page.
mixin _VehicleRegisterScreenModel on _BaseVehiclePage {
@ -540,3 +236,372 @@ mixin _VehicleUpdateScreenModel on _BaseVehiclePage {
}
}
}
/// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page.
mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
Future<Map<String, Color>?> generateStatusColorMap(dynamic uItem, int count) async {
final autoApproval = await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key);
if(autoApproval.toBoolean == true) return null;
final theme = FlutterFlowTheme.of(context);
final localization = FFLocalizations.of(context);
byLanguage(en, pt) => localization.getVariableText(enText: en, ptText: pt);
final preFixStatusMap = {
"ATI": {
"text": '',
"color": theme.success,
},
"INA": {
"text": '',
"color": theme.accent2,
},
"APR_CREATE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.success,
},
"APR_DELETE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.error,
},
"APR_UPDATE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.warning,
},
"AGU_CHANGE": {
"text": byLanguage('Awaiting', 'Aguardando'),
"color": theme.accent2,
},
};
final vehicleStatusMap = {
"ATI": {
"text": byLanguage('Active', 'Ativo'),
"color": theme.success,
},
"INA": {
"text": byLanguage('Inactive', 'Inativo'),
"color": theme.accent2,
},
"APR_CREATE": {
"text": byLanguage('Creation', 'Criação'),
"color": theme.success,
},
"APR_DELETE": {
"text": byLanguage('Deletion', 'Exclusão'),
"color": theme.error,
},
"APR_UPDATE": {
"text": byLanguage('Update', 'Atualização'),
"color": theme.warning,
},
"AGU_CHANGE": {
"text": byLanguage('Correction', 'Correção'),
"color": theme.accent2,
},
};
final ownerStatusMap = {
true: {
"text": byLanguage('My Vehicle', 'Meu Veículo'),
"color": theme.primaryText,
},
false: {
"text": byLanguage('', ''),
"color": theme.accent2,
},
};
final status = uItem['status'];
final isOwner = uItem['isOwnerVehicle'];
if (vehicleStatusMap.containsKey(status)) {
if(count > 1) return {
preFixStatusMap[status]!['text'] as String: preFixStatusMap[status]!['color'] as Color,
vehicleStatusMap[status]!['text'] as String: vehicleStatusMap[status]!['color'] as Color,
// if (ownerStatusMap.containsKey(isOwner))
// ownerStatusMap[isOwner]!['text'] as String: ownerStatusMap[isOwner]!['color'] as Color
};
else return {
"${preFixStatusMap[status]!['text']} ${vehicleStatusMap[status]!['text']}": vehicleStatusMap[status]!['color'] as Color
};
}
return {};
}
Future<List<FFButtonWidget>?> generateActionButtons(dynamic item) async {
final Color iconButtonColor = FlutterFlowTheme.of(context).primaryText;
final FFButtonOptions buttonOptions = FFButtonOptions(
height: 40,
color: FlutterFlowTheme.of(context).primaryBackground,
elevation: 0,
textStyle: TextStyle(
color: FlutterFlowTheme.of(context).primaryText,
fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15),
),
splashColor: FlutterFlowTheme.of(context).success,
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).primaryBackground,
width: 1,
),
);
final updateText = FFLocalizations.of(context)
.getVariableText(ptText: 'Editar', enText: 'Edit');
final updateIcon = Icon(Icons.edit, color: iconButtonColor);
Future updateOnPressed() async {
context.pop();
isEditing = true;
switchTab(1);
setEditForm(item);
}
final cancelText = FFLocalizations.of(context)
.getVariableText(ptText: 'Cancelar', enText: 'Cancel');
final cancelIcon = Icon(Icons.close, color: iconButtonColor);
Future cancelOnPressed() async {
showAlertDialog(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Cancelar Solicitação',
enText: 'Cancel Request',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Você tem certeza que deseja cancelar essa solicitação?',
enText: 'Are you sure you want to delete this request?',
),
() async => await processCancelRequest(item['status'], item)
);
}
final deleteText = FFLocalizations.of(context)
.getVariableText(ptText: 'Excluir', enText: 'Delete');
final deleteIcon = Icon(Icons.delete, color: iconButtonColor);
Future deleteOnPressed() async {
showAlertDialog(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Excluir Veículo',
enText: 'Delete Vehicle',
),
FFLocalizations.of(context).getVariableText(
ptText: 'Você tem certeza que deseja excluir esse veículo?',
enText: 'Are you sure you want to delete this vehicle?',
),
() async => await processDeleteRequest(item),
);
}
final bool containStatus = item['status'] == null;
final bool isOwnerVehicle = item['isOwnerVehicle'];
final bool isAGU = item['status'].contains('AGU');
final bool isAPR = item['status'].contains('APR');
final bool isATI = item['status'].contains('ATI');
if(containStatus) return [
FFButtonWidget(
text: deleteText,
icon: deleteIcon,
onPressed: deleteOnPressed,
options: buttonOptions,
),
];
return [
if (isAGU && isOwnerVehicle)
FFButtonWidget(
text: updateText,
icon: updateIcon,
onPressed: updateOnPressed,
options: buttonOptions,
),
if ((isAPR || isAGU) && (isOwnerVehicle))
FFButtonWidget(
text: cancelText,
icon: cancelIcon,
onPressed: cancelOnPressed,
options: buttonOptions,
),
if (isATI && isOwnerVehicle)
FFButtonWidget(
text: deleteText,
icon: deleteIcon,
onPressed: deleteOnPressed,
options: buttonOptions,
),
];
}
Future<void> processDeleteRequest(dynamic item) async {
log('processDeleteRequest -> item[$item]');
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
)
.then((value) {
context.pop(value);
context.pop(value);
// ignore: unrelated_type_equality_checks
if (value.jsonBody['error'] == true) {
final String errorMsg = value.jsonBody['error_msg'];
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
ptText: errorMsg,
enText: 'Error deleting vehicle',
),
true,
);
// ignore: unrelated_type_equality_checks
}
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Success deleting vehicle',
ptText: 'Succeso ao excluir veículo',
),
false,
);
}).catchError((err, stack) {
context.pop();
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Error deleting vehicle',
ptText: 'Erro ao excluir veículo',
),
true,
);
});
}
Future<void> processCancelRequest(String status, dynamic item) async {
late final ApiCallResponse value;
try {
switch (status) {
case 'APR_CREATE':
value = await processCancelDeleteRequest(item);
break;
case 'AGU_CHANGE':
value = await processCancelUpdateRequest(item);
break;
case 'APR_DELETE':
value = await processCancelCreateRequest(item);
break;
default:
break;
}
context.pop(value);
context.pop(value);
if (value.jsonBody['error'] == true) {
final String errorMsg = value.jsonBody['error_msg'] ;
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
ptText: errorMsg,
enText: 'Error canceling request',
),
true,
);
}
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Success canceling request',
ptText: 'Succeso ao cancelar solicitação',
),
false,
);
} catch (err) {
context.pop();
return showSnackbar(
context,
FFLocalizations.of(context).getVariableText(
enText: 'Error canceling request',
ptText: 'Erro ao cancelar solicitação',
),
true,
);
}
}
Future<ApiCallResponse> processCancelDeleteRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Future<ApiCallResponse> processCancelCreateRequest(dynamic item) async {
return await PhpGroup.deleteVehicle.call(
vehicleId: item['vehicleId'],
licensePlate: item['licensePlate'],
model: item['model'],
color: item['color'],
);
}
Future<Map<String, String>> generateLabelsHashMap(dynamic item) async {
return {
if (item['model'] != null && item['model'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
item['model'].toString().toUpperCase(),
if (item['licensePlate'] != null && item['licensePlate'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
item['licensePlate'].toString().toUpperCase(),
if (item['color'] != null && item['color'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Cor", enText: "Color")}:':
item['color'].toString().toUpperCase(),
if (item['personName'] != null && item['personName'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:':
item['personName'].toString().toUpperCase(),
if (item['tag'] != null && item['tag'] != '')
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:':
item['tag'].toString().toUpperCase(),
};
}
Future<Widget> buildVehicleDetails({
required dynamic item,
required BuildContext context,
required VehicleModel model,
required FreCardIcon? icon,
}) async {
final status = await generateStatusColorMap(item, 1);
final buttons = await generateActionButtons(item);
final labels = await generateLabelsHashMap(item);
return DetailsComponentWidget(
icon: icon,
buttons: buttons,
labelsHashMap: labels,
statusHashMap: [status],
);
}
}

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@ -8,11 +7,9 @@ import 'package:hub/components/atomic_components/shared_components_atoms/tabview
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/features/module/index.dart';
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/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/utils/dialog_util.dart';
import 'package:hub/shared/utils/license_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart';

View File

@ -80,7 +80,7 @@ class VisitsModel extends FlutterFlowModel<VehiclePage> {
),
}),
imagePath:
'https://freaccess.com.br/freaccess/getImage.php?devUUID=${devUUID}&cliID=${cliUUID}&atividade=getFoto&Documento=${item['VDO_DOCUMENTO']}&tipo=E',
'https://freaccess.com.br/freaccess/getImage.php?devUUID=$devUUID&cliID=$cliUUID&atividade=getFoto&Documento=${item['VDO_DOCUMENTO']}&tipo=E',
statusHashMap: [
Map<String, Color>.from({
if (item['VTA_FIXA'] != null)

View File

@ -1,16 +1,16 @@
extension StringNullableExtensions on String? {
bool toBoolean() {
bool get toBoolean {
if (this == null) return false;
return this!.toLowerCase() == 'true';
}
bool isNullOrEmpty() {
bool get isNullOrEmpty {
if (this == null) return true;
if (this == '') return true;
return false;
}
bool isNotNullAndEmpty() {
bool get isNotNullAndEmpty {
if (this == null) return false;
if (this == '') return false;
return true;
@ -18,8 +18,9 @@ extension StringNullableExtensions on String? {
}
extension StringExtensions on String {
bool toBoolean() {
return this.toLowerCase() == 'true';
bool get toBoolean {
return toLowerCase() == 'true';
}
}

View File

@ -6,11 +6,11 @@ class TextUtil extends StatelessWidget {
final TextAlign? textAlign;
const TextUtil({
Key? key,
super.key,
required this.text,
this.style,
this.textAlign,
}) : super(key: key);
});
@override
Widget build(BuildContext context) {