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'; class VehicleModel extends FlutterFlowModel { @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(); } @override void dispose() { tabBarController.dispose(); textFieldFocusLicensePlate!.dispose(); textFieldControllerLicensePlate!.dispose(); textFieldFocusColor!.dispose(); textFieldControllerColor!.dispose(); textFieldFocusModel!.dispose(); textFieldControllerModel!.dispose(); } static VehicleModel? _instance = VehicleModel._internal(); VehicleModel._internal(); factory VehicleModel() => _instance ?? VehicleModel._internal(); static void resetInstance() => _instance = null; dynamic item; String? vehicleId; late final TabController tabBarController; VoidCallback? onUpdateVehicle; VoidCallback? onRegisterVehicle; VoidCallback? safeSetState; final GlobalKey registerFormKey = GlobalKey(); final GlobalKey updateFormKey = GlobalKey(); ApiCallResponse? vehicleResponse; bool isEditing = false; BuildContext context = navigatorKey.currentContext!; 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; } Future initAsync() async {} Map? generateStatusColorMap(dynamic uItem) { 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? 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, ), ); return [ if (item['status'].contains('AGU')) FFButtonWidget( text: FFLocalizations.of(context).getVariableText( ptText: 'Editar', enText: 'Edit', ), icon: Icon( Icons.close, color: iconButtonColor, ), onPressed: () async { context.pop(); isEditing = true; item = item; switchTab(1); setEditForm(); }, options: buttonOptions, ), if (item['status'].contains('APR') || item['status'].contains('AGU')) FFButtonWidget( text: FFLocalizations.of(context).getVariableText( ptText: 'Cancelar', enText: 'Cancel', ), icon: Icon(Icons.close, color: iconButtonColor), onPressed: () 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 { int id = item['vehicleId']; await PhpGroup.deleteVehicle.call(vehicleId: id).then((value) { 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, ); } }).catchError((err, stack) { context.pop(); showSnackbar( context, FFLocalizations.of(context).getVariableText( enText: 'Error canceling request', ptText: 'Erro ao cancelar solicitação', ), true, ); }); }); }, options: buttonOptions, ), if (item['status'].contains('ATI')) FFButtonWidget( text: FFLocalizations.of(context).getVariableText( ptText: 'Excluir', enText: 'Delete', ), icon: Icon( Icons.close, color: iconButtonColor, ), onPressed: () 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 { int id = item['vehicleId']; await PhpGroup.deleteVehicle.call(vehicleId: id).then((value) { context.pop(value); context.pop(value); if (value == false) { showSnackbar( context, FFLocalizations.of(context).getVariableText( ptText: 'Erro ao excluir veículo', enText: 'Error deleting vehicle', ), true, ); } 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, ); }); }); }, options: buttonOptions, ), ]; } Map 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], ); } void setEditForm() { if (item != null) { vehicleId = item['vehicleId']; textFieldControllerLicensePlate!.text = item['licensePlate']; textFieldControllerColor!.text = item['color']; textFieldControllerModel!.text = item['model']; } } bool isFormValid(BuildContext context) { if (registerFormKey.currentState == null) return false; return registerFormKey.currentState!.validate(); } Future 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); } } Future 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); } } void switchTab(int index) { tabBarController.animateTo(index); if (index == 0) handleEditingChanged(false); safeSetState?.call(); } void clearFields() async { textFieldControllerLicensePlate!.clear(); textFieldControllerColor!.clear(); textFieldControllerModel!.clear(); } void handleEditingChanged(bool editing) { isEditing = editing; clearFields(); } }