import 'dart:convert'; import 'dart:developer'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:onufitness/constants/api_endpoints.dart'; import 'package:onufitness/models/master_dropdowns/coach_types_dropdown_response_model.dart'; import 'package:onufitness/services/api_services/base_api_services.dart'; import 'package:onufitness/services/local_storage_services/shared_services.dart'; import 'package:onufitness/utils/custom_sneakbar.dart'; class BecomeACoachController extends GetxController { @override void onInit() async { super.onInit(); fetchCoachTypes(); certificateTypeController = TextEditingController(); socialMediaController = TextEditingController(); selectedExperienceCount = TextEditingController(); } //............................................................................................................... var certificateFile = Rx(null); Future pickCertificate() async { final result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['jpg', 'jpeg', 'png', 'pdf'], ); if (result != null && result.files.single.path != null) { final file = result.files.single; final filePath = file.path!; final fileSize = file.size; // in bytes final fileExtension = file.extension?.toLowerCase(); const maxFileSize = 5 * 1024 * 1024; // 5MB if (!['jpg', 'jpeg', 'png', 'pdf'].contains(fileExtension)) { customSnackbar( title: "Invalid File", message: "Only PDF, PNG, JPG, JPEG files are allowed.", ); return; } if (fileSize > maxFileSize) { customSnackbar( title: "File Too Large", message: "File size too large. PDF, PNG, JPG, and JPEG files must be 5MB or smaller.", ); return; } certificateFile.value = XFile(filePath); } } //............................................................................................................ Rx selectedDate = Rx(null); void pickDate(BuildContext context) async { DateTime? pickedDate = await showDatePicker( context: context, initialDate: selectedDate.value ?? DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime.now(), ); if (pickedDate != null) { selectedDate.value = pickedDate; } } //............................................................................................................ var isCoachTypesLoading = false.obs; var apiCoachTypeList = [].obs; var selectedCoachTypes = "".obs; RxList localCoachTypesNameList = [].obs; RxInt selectedCoachTypesId = 0.obs; Future fetchCoachTypes() async { isCoachTypesLoading(true); try { var response = await ApiBase.getRequest( extendedURL: ApiUrl.fetchCoachTypes, sendHeaders: false, ); if (response.statusCode == 200 || response.statusCode == 201) { var responseData = coachTypesResponseModelFromJson(response.body); if (responseData.isSuccess == true) { apiCoachTypeList.assignAll(responseData.data ?? []); localCoachTypesNameList.clear(); for (var coach in responseData.data!) { localCoachTypesNameList.add(coach.typeName.toString()); } } else { var responseData = coachTypesResponseModelFromJson(response.body); customSnackbar( title: "Error", message: responseData.message ?? "Failed to get Coach Types", ); } } else { var responseData = coachTypesResponseModelFromJson(response.body); customSnackbar( title: "Error", message: responseData.message ?? "Failed to get Coach Types", ); } } catch (e) { log("Exception: $e"); customSnackbar(title: "Error", message: "Failed to get Coach Types"); } finally { isCoachTypesLoading(false); } } //............................................................................................................ TextEditingController certificateTypeController = TextEditingController(); TextEditingController socialMediaController = TextEditingController(); TextEditingController selectedExperienceCount = TextEditingController(); RxBool isBecomeCoachLoading = false.obs; Future becomeCoach() async { isBecomeCoachLoading(true); bool ret = false; try { if (certificateFile.value == null) { customSnackbar( title: "Error", message: "Please select a certificate file.", ); isBecomeCoachLoading(false); return false; } var response = await ApiBase.postMultipleFiles( extendedURL: ApiUrl.becomeACoach, body: { "UserID": SharedServices.getLoginDetails()?.data?.userId.toString(), "YearOfExperience": selectedExperienceCount.text, "CertificateType": certificateTypeController.text, "SocialMediaLinks": "", "CoachTypeID": selectedCoachTypesId.value, }, files: [certificateFile.value!], fileNameKey: 'Certificates', ); log(certificateFile.value!.path.toString()); if (response.statusCode == 200 || response.statusCode == 201) { Future.delayed(Duration(milliseconds: 300), () { customSnackbar( title: "Success", message: "Coach registration successful.", ); }); certificateTypeController.clear(); socialMediaController.clear(); selectedCoachTypesId.value = 0; selectedExperienceCount.text = ""; certificateFile.value = null; ret = true; } else { log("Error: ${response.body}"); Map responseData = json.decode(response.body); String message = responseData['message'] ?? 'Unknown error occurred'; Future.delayed(Duration(milliseconds: 300), () { customSnackbar(title: "Failed", message: message); }); } } catch (e) { log("Exception: $e"); customSnackbar( title: "Failure", message: "Unexpected error occurred. Please try again later.", ); } isBecomeCoachLoading(false); return ret; } // Upload Profile Picture................................................................................. var profileImage = Rx(null); final ImagePicker _picker = ImagePicker(); Future pickImage() async { final XFile? result = await _picker.pickImage(source: ImageSource.gallery); if (result != null) { final fileBytes = await result.readAsBytes(); final fileSize = fileBytes.length; const maxFileSize = 5 * 1024 * 1024; // 5MB if (fileSize > maxFileSize) { customSnackbar( title: "File Too Large", message: "Profile image must be 5MB or smaller. Please select a smaller file.", ); return; } profileImage.value = result; update(); await uploadProfilePicture(); } } //......................................................................................................... var isUploadingImage = false.obs; Future uploadProfilePicture() async { if (profileImage.value == null) { log("No image selected"); customSnackbar(title: "Error", message: "No image selected"); return; } isUploadingImage(true); try { var userId = SharedServices.getUserDetails()?.data?.userId.toString(); var response = await ApiBase.postSingleFileRequest( extendedURL: "${ApiUrl.uploadProfileImage}/$userId", sendHeaders: false, file: profileImage.value!, fileNameKey: 'file', ); log(response.statusCode.toString()); log(response.body.toString()); if (response.statusCode == 200 || response.statusCode == 201) { log("Image uploaded successfully"); customSnackbar( title: "Success", message: "Image uploaded successfully", duration: 1, ); } else { customSnackbar( title: "Error", message: jsonDecode(response.body)["message"], ); } } catch (e) { log("Error uploading image: \$e"); customSnackbar(title: "Error", message: "Failed to upload image"); } finally { isUploadingImage(false); } } }