flutter-freaccess-hub/lib/pages/vehicles_on_the_property/vehicle_model.dart

525 lines
17 KiB
Dart

import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/components/templates_components/details_component/details_component_widget.dart';
import 'package:hub/features/backend/index.dart';
import 'package:hub/flutter_flow/index.dart';
import 'package:hub/pages/vehicles_on_the_property/vehicles_on_the_property.dart';
import 'package:hub/shared/utils/index.dart';
/// [VehicleModel] is a class that contains the business logic of the vehicle page.
class VehicleModel extends FlutterFlowModel<VehiclePage>
with
_BaseVehiclePage,
_VehicleHistoryScreenModel,
_VehicleRegisterScreenModel,
_VehicleUpdateScreenModel {
/// [VehicleModel] is a singleton class that contains the business logic of the vehicle page.
static VehicleModel? _instance = VehicleModel._internal();
VehicleModel._internal();
factory VehicleModel() => _instance ?? VehicleModel._internal();
static void resetInstance() => _instance = null;
@override
void initState(BuildContext context) {
resetInstance();
initAsync();
tabBarController = TabController(
vsync: Navigator.of(context),
length: 2,
);
textFieldFocusLicensePlate = FocusNode();
textFieldControllerLicensePlate = TextEditingController();
textFieldFocusColor = FocusNode();
textFieldControllerColor = TextEditingController();
textFieldFocusModel = FocusNode();
textFieldControllerModel = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) async {
vehicleAmountRegister = 0;
});
}
@override
void dispose() {
tabBarController.dispose();
textFieldFocusLicensePlate!.dispose();
textFieldControllerLicensePlate!.dispose();
textFieldFocusColor!.dispose();
textFieldControllerColor!.dispose();
textFieldFocusModel!.dispose();
textFieldControllerModel!.dispose();
}
final GlobalKey<FormState> registerFormKey = GlobalKey<FormState>();
final GlobalKey<FormState> updateFormKey = GlobalKey<FormState>();
Future<void> initAsync() async {}
bool isFormValid(BuildContext context) {
if (registerFormKey.currentState == null) return false;
return registerFormKey.currentState!.validate();
}
}
/// [_BaseVehiclePage] is a mixin that contains the base logic of the vehicle page.
mixin class _BaseVehiclePage {
int count = 0;
late final VehicleModel model;
late final TabController tabBarController;
// dynamic item;
BuildContext context = navigatorKey.currentContext!;
bool isEditing = false;
String? vehicleId;
ApiCallResponse? vehicleResponse;
late final vehicleAmountRegister;
VoidCallback? onUpdateVehicle;
VoidCallback? onRegisterVehicle;
VoidCallback? safeSetState;
FocusNode? textFieldFocusLicensePlate;
TextEditingController? textFieldControllerLicensePlate;
String? textControllerLicensePlateValidator(
BuildContext context, String? value) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Placa é obrigatória',
enText: 'License Plate is required',
);
}
// (ABC-1234)
final brazilianPlateRegex = RegExp(r'^[A-Z]{3}-\d{4}$');
// (ABC1D23)
final mercosurPlateRegex = RegExp(r'^[A-Z]{3}\d[A-Z]\d{2}$');
if (!brazilianPlateRegex.hasMatch(value) &&
!mercosurPlateRegex.hasMatch(value)) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Placa inválida',
enText: 'Invalid license plate',
);
}
return null;
}
FocusNode? textFieldFocusColor;
TextEditingController? textFieldControllerColor;
String? textControllerColorValidator(BuildContext contexnt, String? value) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Cor é obrigatória',
enText: 'Color is required',
);
}
return null;
}
FocusNode? textFieldFocusModel;
TextEditingController? textFieldControllerModel;
String? textControllerModelValidator(BuildContext contexnt, String? value) {
if (value == null || value.isEmpty) {
return FFLocalizations.of(context).getVariableText(
ptText: 'Modelo é obrigatório',
enText: 'Model is required',
);
}
return null;
}
void switchTab(int index) {
tabBarController.animateTo(index);
if (index == 0) handleEditingChanged(false);
safeSetState?.call();
}
void clearFields() async {
textFieldControllerLicensePlate = TextEditingController(text: '');
textFieldControllerColor = TextEditingController(text: '');
textFieldControllerModel = TextEditingController(text: '');
}
void handleEditingChanged(bool editing) {
isEditing = editing;
clearFields();
}
void setEditForm(dynamic item) {
if (item != null) {
vehicleId = item['vehicleId'];
log("setEditForm ");
log("setEditForm -> ${item.toString()}");
textFieldControllerLicensePlate = TextEditingController(
text: item != null ? item['licensePlate'] ?? '' : '');
textFieldControllerColor =
TextEditingController(text: item != null ? item['color'] ?? '' : '');
textFieldControllerModel =
TextEditingController(text: item != null ? item['model'] ?? '' : '');
}
}
}
/// [_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: id).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 {
final int id = item['vehicleId'];
return await PhpGroup.deleteVehicle.call(vehicleId: id);
}
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
final int id = item['vehicleId'];
return await PhpGroup.deleteVehicle.call(vehicleId: id);
}
Future<ApiCallResponse> processCancelCreateRequest(dynamic item) async {
final int id = item['vehicleId'];
return await PhpGroup.deleteVehicle.call(vehicleId: id);
}
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 {
Future<void> registerVehicle() async {
final response = await PhpGroup.registerVehicle.call(
licensePlate: textFieldControllerLicensePlate!.text,
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
);
if (response.jsonBody['error'] == false) {
await DialogUtil.success(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo cadastrado com sucesso',
enText: 'Vehicle registered successfully',
)).then((_) async {
switchTab(0);
});
} else {
String errorMessage;
try {
errorMessage = response.jsonBody['message'];
} catch (e) {
errorMessage = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao cadastrar veículo',
enText: 'Error registering vehicle',
);
}
await DialogUtil.error(context, errorMessage);
}
}
}
/// [_VehicleUpdateScreenModel] is a mixin that contains the business logic of the vehicle update page.
mixin _VehicleUpdateScreenModel on _BaseVehiclePage {
Future<void> updateVehicle() async {
final response = await PhpGroup.updateVehicle.call(
licensePlate: textFieldControllerLicensePlate!.text,
color: textFieldControllerColor!.text,
model: textFieldControllerModel!.text,
vehicleId: vehicleId!,
);
if (response.jsonBody['error'] == false) {
await DialogUtil.success(
context,
FFLocalizations.of(context).getVariableText(
ptText: 'Veículo atualizado com sucesso',
enText: 'Vehicle updated successfully',
)).then((_) async {
switchTab(0);
});
} else {
String errorMessage;
try {
errorMessage = response.jsonBody['message'];
} catch (e) {
errorMessage = FFLocalizations.of(context).getVariableText(
ptText: 'Erro ao atualizar veículo',
enText: 'Error updating vehicle',
);
}
await DialogUtil.error(context, errorMessage);
}
}
}