Files
rasadyar_application/packages/chicken/lib/features/common/profile/logic.dart

258 lines
8.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_chicken/features/common/data/model/request/change_password/change_password_request_model.dart';
import 'package:rasadyar_chicken/features/common/data/model/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/features/common/data/model/response/user_profile/user_profile.dart';
import 'package:rasadyar_chicken/features/common/data/repositories/common/common_repository.dart';
import 'package:rasadyar_core/core.dart';
class ProfileLogic extends GetxController {
CommonRepository commonRepository = diChicken.get<CommonRepository>();
GService gService = Get.find<GService>();
TokenStorageService tokenService = Get.find<TokenStorageService>();
RxInt selectedInformationType = 0.obs;
Rxn<Jalali> birthDate = Rxn<Jalali>();
Rx<Resource<UserProfile>> userProfile = Rx<Resource<UserProfile>>(
Resource.loading(),
);
Rx<Resource<UserLocalModel>> userLocal = Rx<Resource<UserLocalModel>>(
Resource.loading(),
);
TextEditingController nameController = TextEditingController();
TextEditingController lastNameController = TextEditingController();
TextEditingController nationalCodeController = TextEditingController();
TextEditingController nationalIdController = TextEditingController();
TextEditingController birthdayController = TextEditingController();
TextEditingController oldPasswordController = TextEditingController();
TextEditingController newPasswordController = TextEditingController();
TextEditingController retryNewPasswordController = TextEditingController();
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
Rxn<IranProvinceCityModel> selectedCity = Rxn();
GlobalKey<FormState> formKey = GlobalKey();
ImagePicker imagePicker = ImagePicker();
Rxn<XFile> selectedImage = Rxn<XFile>();
final RxnString _base64Image = RxnString();
RxBool isOnLoading = false.obs;
RxBool isUserInformationOpen = true.obs;
RxBool isUnitInformationOpen = false.obs;
ScrollController scrollController = ScrollController();
@override
void onInit() {
super.onInit();
ever(selectedImage, (data) async {
if (data?.path != null) {
_base64Image.value = await convertImageToBase64(data!.path);
}
});
}
@override
void onReady() {
super.onReady();
getUserProfile();
getUserRole();
selectedProvince.listen((p0) => getCites());
userProfile.listen((data) {
nameController.text = data.data?.firstName ?? '';
lastNameController.text = data.data?.lastName ?? '';
nationalCodeController.text = data.data?.nationalCode ?? '';
nationalIdController.text = data.data?.nationalId ?? '';
birthdayController.text =
data.data?.birthday?.toJalali.formatCompactDate() ?? '';
birthDate.value = data.data?.birthday?.toJalali;
selectedProvince.value = IranProvinceCityModel(
name: data.data?.province ?? '',
id: data.data?.provinceNumber ?? 0,
);
selectedCity.value = IranProvinceCityModel(
name: data.data?.city ?? '',
id: data.data?.cityNumber ?? 0,
);
});
}
Future<void> getUserProfile() async {
userProfile.value = Resource.loading();
await safeCall<UserProfile?>(
call: () async => await commonRepository.getUserProfile(
token: tokenService.accessToken.value!,
),
onSuccess: (result) {
if (result != null) {
userProfile.value = Resource.success(result);
}
},
onError: (error, stackTrace) {},
);
}
Future<void> getCites() async {
await safeCall(
call: () => commonRepository.getCity(
provinceName: selectedProvince.value?.name ?? '',
),
onSuccess: (result) {
if (result != null && result.isNotEmpty) {
cites.value = result;
}
},
);
}
Future<void> updateUserProfile() async {
UserProfile userProfile = UserProfile(
firstName: nameController.text,
lastName: lastNameController.text,
nationalCode: nationalCodeController.text,
nationalId: nationalIdController.text,
birthday: birthDate.value
?.toDateTime()
.formattedDashedGregorian
.toString(),
image: _base64Image.value,
personType: 'self',
type: 'self_profile',
);
isOnLoading.value = true;
await safeCall(
call: () async => await commonRepository.updateUserProfile(
token: tokenService.accessToken.value!,
userProfile: userProfile,
),
onSuccess: (result) {
isOnLoading.value = false;
},
onError: (error, stackTrace) {
isOnLoading.value = false;
},
);
}
Future<void> updatePassword() async {
if (formKey.currentState?.validate() ?? false) {
ChangePasswordRequestModel model = ChangePasswordRequestModel(
username: userProfile.value.data?.mobile,
password: newPasswordController.text,
);
await safeCall(
call: () async => await commonRepository.updatePassword(
token: tokenService.accessToken.value!,
model: model,
),
);
}
}
Future<void> getUserRole() async {
userLocal.value = Resource.loading();
await safeCall<UserLocalModel?>(
call: () async => tokenService.getUserLocal(Module.chicken),
onSuccess: (result) {
if (result != null) {
userLocal.value = Resource.success(result);
}
},
onError: (error, stackTrace) {},
);
}
void clearPasswordForm() {
oldPasswordController.clear();
newPasswordController.clear();
retryNewPasswordController.clear();
}
Future<void> changeUserRole(String newRole) async {
dLog(newRole);
await gService.saveRoute(Module.chicken, newRole);
Get.offAllNamed(newRole);
}
void scrollToSelectedItem(
int index, {
double chipWidth = 100,
double spacing = 8,
GlobalKey? itemKey,
}) {
if (!scrollController.hasClients) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_performScroll(index, chipWidth, spacing, itemKey);
});
} else {
_performScroll(index, chipWidth, spacing, itemKey);
}
}
void _performScroll(
int index,
double chipWidth,
double spacing,
GlobalKey? itemKey,
) {
if (!scrollController.hasClients) return;
double targetOffset;
// If we have a GlobalKey, use it for precise positioning
if (itemKey?.currentContext != null) {
final RenderBox? renderBox =
itemKey!.currentContext?.findRenderObject() as RenderBox?;
if (renderBox != null) {
final position = renderBox.localToGlobal(Offset.zero);
final scrollPosition = scrollController.position;
final viewportWidth = scrollPosition.viewportDimension;
final chipWidth = renderBox.size.width;
// Get the scroll position of the item
final itemScrollPosition = position.dx - scrollPosition.pixels;
// Center the item
targetOffset =
scrollPosition.pixels +
itemScrollPosition -
(viewportWidth / 2) +
(chipWidth / 2);
} else {
// Fallback to estimated position
targetOffset = _calculateEstimatedPosition(index, chipWidth, spacing);
}
} else {
// Use estimated position
targetOffset = _calculateEstimatedPosition(index, chipWidth, spacing);
}
scrollController.animateTo(
targetOffset.clamp(0.0, scrollController.position.maxScrollExtent),
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
double _calculateEstimatedPosition(
int index,
double chipWidth,
double spacing,
) {
final double itemPosition = (chipWidth + spacing) * index;
final double viewportWidth = scrollController.position.viewportDimension;
return itemPosition - (viewportWidth / 2) + (chipWidth / 2);
}
@override
void onClose() {
scrollController.dispose();
super.onClose();
}
}