feat : image profile

This commit is contained in:
2025-07-21 16:05:49 +03:30
parent 99503a2d72
commit a0c1d452c6
3 changed files with 196 additions and 77 deletions

View File

@@ -28,6 +28,20 @@ class ProfileLogic extends GetxController {
Rxn<IranProvinceCityModel> selectedCity = Rxn(); Rxn<IranProvinceCityModel> selectedCity = Rxn();
GlobalKey<FormState> formKey = GlobalKey(); GlobalKey<FormState> formKey = GlobalKey();
ImagePicker imagePicker = ImagePicker();
Rxn<XFile> selectedImage = Rxn<XFile>();
RxnString _base64Image = RxnString();
RxBool isOnLoading = false.obs;
@override
void onInit() {
super.onInit();
ever(selectedImage, (data) async {
if (data?.path != null) {
_base64Image.value = await convertImageToBase64(data!.path);
}
});
}
@override @override
void onReady() { void onReady() {
@@ -92,14 +106,22 @@ class ProfileLogic extends GetxController {
nationalCode: nationalCodeController.text, nationalCode: nationalCodeController.text,
nationalId: nationalIdController.text, nationalId: nationalIdController.text,
birthday: birthDate.value?.toGregorian().toString(), birthday: birthDate.value?.toGregorian().toString(),
image: _base64Image.value,
personType: 'self', personType: 'self',
type: 'self_profile', type: 'self_profile',
); );
isOnLoading.value = true;
await safeCall( await safeCall(
call: () async => await rootLogic.chickenRepository.updateUserProfile( call: () async => await rootLogic.chickenRepository.updateUserProfile(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
userProfile: userProfile, userProfile: userProfile,
), ),
onSuccess: (result) {
isOnLoading.value = false;
},
onError: (error, stackTrace) {
isOnLoading.value = false;
},
); );
} }

View File

@@ -1,3 +1,6 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rasadyar_auth/data/models/local/user_local/user_local_model.dart'; import 'package:rasadyar_auth/data/models/local/user_local/user_local_model.dart';
import 'package:rasadyar_auth/presentation/routes/pages.dart'; import 'package:rasadyar_auth/presentation/routes/pages.dart';
@@ -25,7 +28,30 @@ class ProfilePage extends GetView<ProfileLogic> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Row(), Row(),
Container( ObxValue(
(data) {
final status = data.value.status;
if (status == ResourceStatus.loading) {
return Container(
width: 128.w,
height: 128.h,
child: Center(child: CupertinoActivityIndicator(color: AppColor
.greenNormal,)),
);
}
if (status == ResourceStatus.error) {
return Container(
width: 128.w,
height: 128.h,
child: Center(child: Text('خطا در دریافت اطلاعات')),
);
}
// Default UI
return Container(
width: 128.w, width: 128.w,
height: 128.h, height: 128.h,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -33,13 +59,18 @@ class ProfilePage extends GetView<ProfileLogic> {
color: AppColor.blueLightActive, color: AppColor.blueLightActive,
), ),
child: Center( child: Center(
child: Assets.vec.userSvg.svg( child: CircleAvatar(
width: 64.w, radius: 64.w,
height: 64.h, backgroundImage:
colorFilter: ColorFilter.mode(AppColor.whiteLight, BlendMode.srcIn), NetworkImage(data.value.data!.image!)
),
), ),
), ),
);
},
controller.userProfile,
)
], ],
), ),
), ),
@@ -96,7 +127,8 @@ class ProfilePage extends GetView<ProfileLogic> {
Container invoiceIssuanceInformation() => Container(); Container invoiceIssuanceInformation() => Container();
Widget bankInformationWidget() => Column( Widget bankInformationWidget() =>
Column(
spacing: 16, spacing: 16,
children: [ children: [
itemList(title: 'نام بانک', content: 'سامان'), itemList(title: 'نام بانک', content: 'سامان'),
@@ -120,7 +152,8 @@ class ProfilePage extends GetView<ProfileLogic> {
children: [ children: [
buildRowOnTapped( buildRowOnTapped(
onTap: () { onTap: () {
Get.bottomSheet(userInformationBottomSheet(), isScrollControlled: true); Get.bottomSheet(
userInformationBottomSheet(), isScrollControlled: true, ignoreSafeArea: false);
}, },
titleWidget: Column( titleWidget: Column(
spacing: 3, spacing: 3,
@@ -184,7 +217,8 @@ class ProfilePage extends GetView<ProfileLogic> {
required String content, required String content,
String? icon, String? icon,
bool hasColoredBox = false, bool hasColoredBox = false,
}) => Container( }) =>
Container(
padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: hasColoredBox ? AppColor.greenLight : Colors.transparent, color: hasColoredBox ? AppColor.greenLight : Colors.transparent,
@@ -260,7 +294,7 @@ class ProfilePage extends GetView<ProfileLogic> {
Widget userInformationBottomSheet() { Widget userInformationBottomSheet() {
return BaseBottomSheet( return BaseBottomSheet(
height: 500.h, height: 750.h,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
spacing: 8, spacing: 8,
@@ -270,16 +304,6 @@ class ProfilePage extends GetView<ProfileLogic> {
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
), ),
/*
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
),
child: Column(spacing: 12, children: [_provinceWidget(), _cityWidget()]),
),*/
Container( Container(
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -333,19 +357,98 @@ class ProfilePage extends GetView<ProfileLogic> {
SizedBox(), SizedBox(),
],
),
),
SizedBox(),
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
),
child: Column(
spacing: 8,
children: [
Text('عکس پروفایل',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
ObxValue((data) {
return Container(
width: Get.width,
height: 270,
decoration: BoxDecoration(
color: AppColor.lightGreyNormal,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: AppColor.blackLight),
),
child: Center(
child: data.value == null
? Padding(
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
child: Image.network(controller.userProfile.value.data?.image ?? '')
)
: Image.file(File(data.value!.path), fit: BoxFit.cover),
),
);
}, controller.selectedImage),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RElevated(
text: 'گالری',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
onPressed: () async {
controller.selectedImage.value = await controller.imagePicker.pickImage(
source: ImageSource.gallery,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
SizedBox(width: 16),
ROutlinedElevated(
text: 'دوربین',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal),
onPressed: () async {
controller.selectedImage.value = await controller.imagePicker.pickImage(
source: ImageSource.camera,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
],
),
],
),
),
Row( Row(
spacing: 16, spacing: 16,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
RElevated( ObxValue((data) {
return RElevated(
height: 40.h, height: 40.h,
text: 'ویرایش', text: 'ویرایش',
isLoading: data.value,
onPressed: () async { onPressed: () async {
await controller.updateUserProfile(); await controller.updateUserProfile();
controller.getUserProfile(); controller.getUserProfile();
Get.back(); Get.back();
}, },
), );
},controller.isOnLoading),
ROutlinedElevated( ROutlinedElevated(
height: 40.h, height: 40.h,
text: 'انصراف', text: 'انصراف',
@@ -359,10 +462,6 @@ class ProfilePage extends GetView<ProfileLogic> {
], ],
), ),
), ),
SizedBox(),
],
),
),
); );
} }

View File

@@ -35,8 +35,6 @@ class SalesOutOfProvinceLogic extends GetxController {
RxBool isLoadingMoreAllocationsMade = false.obs; RxBool isLoadingMoreAllocationsMade = false.obs;
Rxn<IranProvinceCityModel> selectedCity = Rxn(); Rxn<IranProvinceCityModel> selectedCity = Rxn();
//TODO add this to Di
ImagePicker imagePicker = ImagePicker();
GlobalKey<FormState> formKey = GlobalKey<FormState>(); GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController quarantineCodeController = TextEditingController(); TextEditingController quarantineCodeController = TextEditingController();