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/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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/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/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/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/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/backend/api_requests/index.dart';
import 'package:hub/features/local/index.dart'; import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/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/features/storage/index.dart';
import 'package:hub/flutter_flow/index.dart' as ff; import 'package:hub/flutter_flow/index.dart' as ff;
import 'package:hub/flutter_flow/index.dart'; import 'package:hub/flutter_flow/index.dart';
import 'package:hub/initialization.dart';
import 'package:hub/main.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:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:patrol/patrol.dart';
import 'package:flutter_web_plugins/url_strategy.dart'; import 'package:flutter_web_plugins/url_strategy.dart';
import 'app_test.dart'; import 'app_test.dart';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.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)) ?? ''; (await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
cliUUID = cliUUID =
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? ''; (await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
;
} }
@override @override

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart'; 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'; import 'package:url_launcher/url_launcher.dart';
class AboutSystemPage extends StatefulWidget { class AboutSystemPage extends StatefulWidget {
const AboutSystemPage({super.key});
@override @override
_AboutSystemPageState createState() => _AboutSystemPageState(); _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/home/presentation/widgets/drawer_widget.dart';
import 'package:hub/features/local/index.dart'; import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/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_icon_button.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart';

View File

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

View File

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

View File

@ -95,6 +95,8 @@ class LocalUtil {
try { try {
await StorageHelper().set(LocalsStorageKey.whatsapp.key, jsonBody['whatsapp'] ?? false); await StorageHelper().set(LocalsStorageKey.whatsapp.key, jsonBody['whatsapp'] ?? false);
await StorageHelper().set(LocalsStorageKey.provisional.key, jsonBody['provisional'] ?? false); await StorageHelper().set(LocalsStorageKey.provisional.key, jsonBody['provisional'] ?? false);
await StorageHelper().set(LocalsStorageKey.vehicleAutoApproval.key, jsonBody['vehicleAutoApproval'] ?? false);
await StorageHelper().set( await StorageHelper().set(
LocalsStorageKey.pets.key, LocalsStorageKey.pets.key,
jsonBody['pet'] ?? false, jsonBody['pet'] ?? false,
@ -118,6 +120,11 @@ class LocalUtil {
await StorageHelper().set(LocalsStorageKey.petAmount.key, await StorageHelper().set(LocalsStorageKey.petAmount.key,
jsonBody['petAmountRegister']?.toString().isEmpty ?? true ? '0' : jsonBody['petAmountRegister'].toString()); 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.userName.key, jsonBody['visitado']['VDO_NOME'] ?? '');
await StorageHelper().set(ProfileStorageKey.userEmail.key, jsonBody['visitado']['VDO_EMAIL'] ?? ''); await StorageHelper().set(ProfileStorageKey.userEmail.key, jsonBody['visitado']['VDO_EMAIL'] ?? '');
await StorageHelper().set(LocalsStorageKey.provisional.key, jsonBody['provisional'] ?? false); 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 } enum MenuEntryType { Home, Drawer, Property }
class MenuEntry implements BaseModule { class MenuEntry implements BaseModule {
@override
final String key; final String key;
@override
final IconData icon; final IconData icon;
@override
final String name; final String name;
@override
final String route; final String route;
final List<MenuEntryType> types; final List<MenuEntryType> types;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -61,7 +61,7 @@ class License {
} }
static Future<String> _precessWpp() async { 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) if (whatsapp)
return ModuleStatus.active.key; return ModuleStatus.active.key;
else else
@ -69,7 +69,7 @@ class License {
} }
static Future<String> _processProvisional() async { 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) if (provisional)
return ModuleStatus.active.key; return ModuleStatus.active.key;
else else
@ -77,7 +77,7 @@ class License {
} }
static Future<String> _processPets() async { 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) if (pets)
return ModuleStatus.active.key; return ModuleStatus.active.key;
else else

View File

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer';
import 'package:app_links/app_links.dart'; import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hub/features/storage/index.dart'; import 'package:hub/features/storage/index.dart';

View File

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

View File

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

View File

@ -1,7 +1,6 @@
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/cupertino.dart'; 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'; import 'package:hub/features/storage/index.dart';
class StorageHelper implements StorageRepository { class StorageHelper implements StorageRepository {

View File

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

View File

@ -1,4 +1,3 @@
import 'dart:developer';
import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_core/firebase_core.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/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/internationalization.dart';
import 'package:hub/flutter_flow/nav/nav.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 'package:responsive_framework/responsive_framework.dart';
import 'initialization.dart'; import 'initialization.dart';

View File

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

View File

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

View File

@ -18,6 +18,7 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
int _pageNumber = 1; int _pageNumber = 1;
bool _hasData = false; bool _hasData = false;
bool _loading = false; bool _loading = false;
int count = 0; int count = 0;
@override @override
@ -28,7 +29,8 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
_future = _fetchVisits(); _future = _fetchVisits();
_scrollController = ScrollController() _scrollController = ScrollController()
..addListener(() { ..addListener(() {
if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) { if (_scrollController.position.atEdge &&
_scrollController.position.pixels != 0) {
_loadMore(); _loadMore();
} }
}); });
@ -53,59 +55,101 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
); );
} }
String getRandomStatus() { String mockRandomMapStatusColor() {
var statuses = ['ATI', 'INA', 'APR_CREATE', 'APR_DELETE', 'APR_UPDATE', 'AGU_CHANGE']; var statuses = [
'ATI',
'INA',
'APR_CREATE',
'APR_DELETE',
'APR_UPDATE',
'AGU_CHANGE'
];
statuses.shuffle(); statuses.shuffle();
return statuses.first; return statuses.first;
} }
Widget _item(BuildContext context, Map<String, dynamic> uItem) { Future<Widget> _item(BuildContext context, Map<String, dynamic> uItem) async {
uItem['status'] = getRandomStatus(); // uItem['status'] = mockRandomMapStatusColor();
return CardItemTemplateComponentWidget( final bool? isOwner = uItem['isOwnerVehicle'];
imagePath: null, late final IconData? iconData;
labelsHashMap: { late final FreCardIcon? cardIcon;
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
uItem['licensePlate'] ?? '', if(isOwner is bool) {
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:': uItem['model'] ?? '', iconData = isOwner ? Symbols.no_crash :Symbols.directions_car;
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:': uItem['tag'] ?? '', cardIcon = FreCardIcon(height: 50, width: 100, icon: Icon(iconData, size: 80, opticalSize: 10));
}, }
statusHashMap: [widget.model.generateStatusColorMap(uItem)], final String? tag = uItem['tag'];
onTapCardItemAction: () async { final bool containTag = tag.isNotNullAndEmpty;
await showDialog( final Map<String, String> labelsHashMap = {
useSafeArea: true, '${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
context: context, uItem['licensePlate'] ?? '',
builder: (context) { '${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
return Dialog( uItem['model'] ?? '',
alignment: Alignment.center, '${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:':
child: widget.model.buildVehicleDetails( 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, item: uItem,
context: context, context: context,
model: widget.model, model: widget.model,
)); ),
}, builder: (context, snapshot) {
).whenComplete(() { if (snapshot.connectionState == ConnectionState.done) {
safeSetState(() { return snapshot.data ?? Container();
_pageNumber = 1; } else {
_wrap = []; return Center(child: CircularProgressIndicator());
_future = _fetchVisits().then((value) => value!.jsonBody['vehicles'] ?? []); }
}); },
}).catchError((e, s) { ));
DialogUtil.errorDefault(context); },
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículos", e, s); ).whenComplete(() {
safeSetState(() { safeSetState(() {
_hasData = false; _pageNumber = 1;
_loading = false; _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 { Future<ApiCallResponse?> _fetchVisits() async {
try { try {
setState(() => _loading = true); 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'] ?? []; final List<dynamic> vehicles = response.jsonBody['vehicles'] ?? [];
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0); safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);
@ -130,7 +174,8 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
return null; return null;
} catch (e, s) { } catch (e, s) {
DialogUtil.errorDefault(context); DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s); LogUtil.requestAPIFailed(
"proccessRequest.php", "", "Consulta de Veículo", e, s);
setState(() { setState(() {
_hasData = false; _hasData = false;
_loading = false; _loading = false;
@ -149,7 +194,10 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
@override @override
Widget build(BuildContext context) { 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( return Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
@ -192,13 +240,30 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen> {
return Padding( return Padding(
padding: const EdgeInsets.only(right: 30, top: 10), padding: const EdgeInsets.only(right: 30, top: 10),
child: Text( 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, textAlign: TextAlign.right,
style: TextStyle(
fontFamily: 'Nunito',
fontSize: limitedBodyTextSize,
),
), ),
); );
} else { } else {
Map<String, dynamic> item = _wrap[index - 1]; 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 'dart:developer';
import 'package:flutter/material.dart'; 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/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/features/backend/index.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/flutter_flow/index.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.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/utils/index.dart';
/// [VehicleModel] is a class that contains the business logic of the vehicle page. /// [VehicleModel] is a class that contains the business logic of the vehicle page.
@ -39,7 +42,7 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
textFieldControllerModel = TextEditingController(); textFieldControllerModel = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) async { 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> registerFormKey = GlobalKey<FormState>();
final GlobalKey<FormState> updateFormKey = 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) { bool isFormValid(BuildContext context) {
if (registerFormKey.currentState == null) return false; if (registerFormKey.currentState == null) return false;
@ -75,7 +81,7 @@ mixin class _BaseVehiclePage {
bool isEditing = false; bool isEditing = false;
String? vehicleId; String? vehicleId;
ApiCallResponse? vehicleResponse; ApiCallResponse? vehicleResponse;
late final vehicleAmountRegister; String? amountRegister = '0';
VoidCallback? onUpdateVehicle; VoidCallback? onUpdateVehicle;
VoidCallback? onRegisterVehicle; VoidCallback? onRegisterVehicle;
@ -93,9 +99,9 @@ mixin class _BaseVehiclePage {
} }
// (ABC-1234) // (ABC-1234)
final brazilianPlateRegex = RegExp(r'^[A-Z]{3}-\d{4}$'); final brazilianPlateRegex = RegExp(r'^[A-Z]{3}\d{4}$');
// (ABC1D23) // (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) && if (!brazilianPlateRegex.hasMatch(value) &&
!mercosurPlateRegex.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. /// [_VehicleRegisterScreenModel] is a mixin that contains the business logic of the vehicle register page.
mixin _VehicleRegisterScreenModel on _BaseVehiclePage { 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:flutter/material.dart';
import 'package:google_fonts/google_fonts.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/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
import 'package:hub/features/backend/index.dart'; import 'package:hub/features/backend/index.dart';
import 'package:hub/features/module/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/flutter_flow/index.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicle_model.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/dialog_util.dart';
import 'package:hub/shared/utils/license_util.dart'; import 'package:hub/shared/utils/license_util.dart';
import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/limited_text_size.dart';

View File

@ -80,7 +80,7 @@ class VisitsModel extends FlutterFlowModel<VehiclePage> {
), ),
}), }),
imagePath: 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: [ statusHashMap: [
Map<String, Color>.from({ Map<String, Color>.from({
if (item['VTA_FIXA'] != null) if (item['VTA_FIXA'] != null)

View File

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

View File

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