From a0c1d452c6ffe16c9885577bba3336070e91d778 Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Mon, 21 Jul 2025 16:05:49 +0330 Subject: [PATCH] feat : image profile --- .../lib/presentation/pages/profile/logic.dart | 22 ++ .../lib/presentation/pages/profile/view.dart | 249 ++++++++++++------ .../pages/sales_out_of_province/logic.dart | 2 - 3 files changed, 196 insertions(+), 77 deletions(-) diff --git a/packages/chicken/lib/presentation/pages/profile/logic.dart b/packages/chicken/lib/presentation/pages/profile/logic.dart index 629cd6c..b055406 100644 --- a/packages/chicken/lib/presentation/pages/profile/logic.dart +++ b/packages/chicken/lib/presentation/pages/profile/logic.dart @@ -28,6 +28,20 @@ class ProfileLogic extends GetxController { Rxn selectedCity = Rxn(); GlobalKey formKey = GlobalKey(); + ImagePicker imagePicker = ImagePicker(); + Rxn selectedImage = Rxn(); + 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 void onReady() { @@ -92,14 +106,22 @@ class ProfileLogic extends GetxController { nationalCode: nationalCodeController.text, nationalId: nationalIdController.text, birthday: birthDate.value?.toGregorian().toString(), + image: _base64Image.value, personType: 'self', type: 'self_profile', ); + isOnLoading.value = true; await safeCall( call: () async => await rootLogic.chickenRepository.updateUserProfile( token: rootLogic.tokenService.accessToken.value!, userProfile: userProfile, ), + onSuccess: (result) { + isOnLoading.value = false; + }, + onError: (error, stackTrace) { + isOnLoading.value = false; + }, ); } diff --git a/packages/chicken/lib/presentation/pages/profile/view.dart b/packages/chicken/lib/presentation/pages/profile/view.dart index 59335f8..78baaa6 100644 --- a/packages/chicken/lib/presentation/pages/profile/view.dart +++ b/packages/chicken/lib/presentation/pages/profile/view.dart @@ -1,3 +1,6 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:rasadyar_auth/data/models/local/user_local/user_local_model.dart'; import 'package:rasadyar_auth/presentation/routes/pages.dart'; @@ -25,21 +28,49 @@ class ProfilePage extends GetView { crossAxisAlignment: CrossAxisAlignment.center, children: [ Row(), - Container( - width: 128.w, - height: 128.h, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.blueLightActive, - ), - child: Center( - child: Assets.vec.userSvg.svg( - width: 64.w, - height: 64.h, - colorFilter: ColorFilter.mode(AppColor.whiteLight, BlendMode.srcIn), - ), - ), - ), + 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, + height: 128.h, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.blueLightActive, + ), + child: Center( + child: CircleAvatar( + radius: 64.w, + backgroundImage: + NetworkImage(data.value.data!.image!) + + + ), + ), + ); + }, + controller.userProfile, + ) ], ), ), @@ -96,16 +127,17 @@ class ProfilePage extends GetView { Container invoiceIssuanceInformation() => Container(); - Widget bankInformationWidget() => Column( - spacing: 16, - children: [ - itemList(title: 'نام بانک', content: 'سامان'), - itemList(title: 'نام صاحب حساب', content: 'رضا رضایی'), - itemList(title: 'شماره کارت ', content: '54154545415'), - itemList(title: 'شماره حساب', content: '62565263263652'), - itemList(title: 'شماره شبا', content: '62565263263652'), - ], - ); + Widget bankInformationWidget() => + Column( + spacing: 16, + children: [ + itemList(title: 'نام بانک', content: 'سامان'), + itemList(title: 'نام صاحب حساب', content: 'رضا رضایی'), + itemList(title: 'شماره کارت ', content: '54154545415'), + itemList(title: 'شماره حساب', content: '62565263263652'), + itemList(title: 'شماره شبا', content: '62565263263652'), + ], + ); Widget userProfileInformation() { return ObxValue((data) { @@ -120,7 +152,8 @@ class ProfilePage extends GetView { children: [ buildRowOnTapped( onTap: () { - Get.bottomSheet(userInformationBottomSheet(), isScrollControlled: true); + Get.bottomSheet( + userInformationBottomSheet(), isScrollControlled: true, ignoreSafeArea: false); }, titleWidget: Column( spacing: 3, @@ -184,33 +217,34 @@ class ProfilePage extends GetView { required String content, String? icon, bool hasColoredBox = false, - }) => Container( - padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), - decoration: BoxDecoration( - color: hasColoredBox ? AppColor.greenLight : Colors.transparent, - borderRadius: BorderRadius.circular(8), - border: hasColoredBox - ? Border.all(width: 0.25, color: AppColor.bgDark) - : Border.all(width: 0, color: Colors.transparent), - ), - child: Row( - spacing: 4, - children: [ - if (icon != null) - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: SvgGenImage.vec(icon).svg( - width: 20.w, - height: 20.h, - colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), - ), - ), - Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), - Spacer(), - Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), - ], - ), - ); + }) => + Container( + padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), + decoration: BoxDecoration( + color: hasColoredBox ? AppColor.greenLight : Colors.transparent, + borderRadius: BorderRadius.circular(8), + border: hasColoredBox + ? Border.all(width: 0.25, color: AppColor.bgDark) + : Border.all(width: 0, color: Colors.transparent), + ), + child: Row( + spacing: 4, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: SvgGenImage.vec(icon).svg( + width: 20.w, + height: 20.h, + colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), + ), + ), + Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), + Spacer(), + Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), + ], + ), + ); Widget cardActionWidget({ required String title, @@ -238,7 +272,7 @@ class ProfilePage extends GetView { width: 40, height: 40, colorFilter: - color ?? + color ?? ColorFilter.mode( selected ? AppColor.blueNormal : AppColor.whiteLight, BlendMode.srcIn, @@ -260,7 +294,7 @@ class ProfilePage extends GetView { Widget userInformationBottomSheet() { return BaseBottomSheet( - height: 500.h, + height: 750.h, child: SingleChildScrollView( child: Column( spacing: 8, @@ -270,16 +304,6 @@ class ProfilePage extends GetView { 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( padding: EdgeInsets.all(8), decoration: BoxDecoration( @@ -333,25 +357,75 @@ class ProfilePage extends GetView { 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( - spacing: 16, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ RElevated( + text: 'گالری', + width: 150.w, height: 40.h, - text: 'ویرایش', + textStyle: AppFonts.yekan20.copyWith(color: Colors.white), onPressed: () async { - await controller.updateUserProfile(); - controller.getUserProfile(); - Get.back(); + 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, - text: 'انصراف', - borderColor: AppColor.blueNormal, - onPressed: () { - Get.back(); + 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, + ); }, ), ], @@ -359,7 +433,32 @@ class ProfilePage extends GetView { ], ), ), - SizedBox(), + Row( + spacing: 16, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ObxValue((data) { + return RElevated( + height: 40.h, + text: 'ویرایش', + isLoading: data.value, + onPressed: () async { + await controller.updateUserProfile(); + controller.getUserProfile(); + Get.back(); + }, + ); + },controller.isOnLoading), + ROutlinedElevated( + height: 40.h, + text: 'انصراف', + borderColor: AppColor.blueNormal, + onPressed: () { + Get.back(); + }, + ), + ], + ), ], ), ), diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart index 3ebc74c..53c3f3a 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart @@ -35,8 +35,6 @@ class SalesOutOfProvinceLogic extends GetxController { RxBool isLoadingMoreAllocationsMade = false.obs; Rxn selectedCity = Rxn(); - //TODO add this to Di - ImagePicker imagePicker = ImagePicker(); GlobalKey formKey = GlobalKey(); TextEditingController quarantineCodeController = TextEditingController();