fix : ui bug

This commit is contained in:
2025-10-15 14:26:37 +03:30
parent 36ff3d5922
commit 464dacc39b
5 changed files with 449 additions and 227 deletions

26
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "rasadyar_app",
"request": "launch",
"type": "dart"
},
{
"name": "rasadyar_app (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "rasadyar_app (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

View File

@@ -1,5 +1,5 @@
sdk.dir=C:/Users/Housh11/AppData/Local/Android/Sdk sdk.dir=C:/Users/Housh11/AppData/Local/Android/Sdk
flutter.sdk=C:\\src\\flutter flutter.sdk=C:\\src\\flutter
flutter.buildMode=debug flutter.buildMode=release
flutter.versionName=1.3.25 flutter.versionName=1.3.26
flutter.versionCode=22 flutter.versionCode=23

View File

@@ -13,8 +13,12 @@ class ProfileLogic extends GetxController {
RxInt selectedInformationType = 0.obs; RxInt selectedInformationType = 0.obs;
Rxn<Jalali> birthDate = Rxn<Jalali>(); Rxn<Jalali> birthDate = Rxn<Jalali>();
Rx<Resource<UserProfile>> userProfile = Rx<Resource<UserProfile>>(Resource.loading()); Rx<Resource<UserProfile>> userProfile = Rx<Resource<UserProfile>>(
Rx<Resource<UserLocalModel>> userLocal = Rx<Resource<UserLocalModel>>(Resource.loading()); Resource.loading(),
);
Rx<Resource<UserLocalModel>> userLocal = Rx<Resource<UserLocalModel>>(
Resource.loading(),
);
TextEditingController nameController = TextEditingController(); TextEditingController nameController = TextEditingController();
TextEditingController lastNameController = TextEditingController(); TextEditingController lastNameController = TextEditingController();
@@ -36,6 +40,9 @@ class ProfileLogic extends GetxController {
RxnString _base64Image = RxnString(); RxnString _base64Image = RxnString();
RxBool isOnLoading = false.obs; RxBool isOnLoading = false.obs;
RxBool isUserInformationOpen = true.obs;
RxBool isUnitInformationOpen = false.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@@ -57,7 +64,8 @@ class ProfileLogic extends GetxController {
lastNameController.text = data.data?.lastName ?? ''; lastNameController.text = data.data?.lastName ?? '';
nationalCodeController.text = data.data?.nationalCode ?? ''; nationalCodeController.text = data.data?.nationalCode ?? '';
nationalIdController.text = data.data?.nationalId ?? ''; nationalIdController.text = data.data?.nationalId ?? '';
birthdayController.text = data.data?.birthday?.toJalali.formatCompactDate() ?? ''; birthdayController.text =
data.data?.birthday?.toJalali.formatCompactDate() ?? '';
birthDate.value = data.data?.birthday?.toJalali; birthDate.value = data.data?.birthday?.toJalali;
selectedProvince.value = IranProvinceCityModel( selectedProvince.value = IranProvinceCityModel(
name: data.data?.province ?? '', name: data.data?.province ?? '',
@@ -79,8 +87,9 @@ class ProfileLogic extends GetxController {
Future<void> getUserProfile() async { Future<void> getUserProfile() async {
userProfile.value = Resource.loading(); userProfile.value = Resource.loading();
await safeCall<UserProfile?>( await safeCall<UserProfile?>(
call: () async => call: () async => await chickenRepository.getUserProfile(
await chickenRepository.getUserProfile(token: tokenService.accessToken.value!), token: tokenService.accessToken.value!,
),
onSuccess: (result) { onSuccess: (result) {
if (result != null) { if (result != null) {
userProfile.value = Resource.success(result); userProfile.value = Resource.success(result);
@@ -92,7 +101,9 @@ class ProfileLogic extends GetxController {
Future<void> getCites() async { Future<void> getCites() async {
await safeCall( await safeCall(
call: () => chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''), call: () => chickenRepository.getCity(
provinceName: selectedProvince.value?.name ?? '',
),
onSuccess: (result) { onSuccess: (result) {
if (result != null && result.isNotEmpty) { if (result != null && result.isNotEmpty) {
cites.value = result; cites.value = result;
@@ -107,7 +118,10 @@ class ProfileLogic extends GetxController {
lastName: lastNameController.text, lastName: lastNameController.text,
nationalCode: nationalCodeController.text, nationalCode: nationalCodeController.text,
nationalId: nationalIdController.text, nationalId: nationalIdController.text,
birthday: birthDate.value?.toDateTime().formattedDashedGregorian.toString(), birthday: birthDate.value
?.toDateTime()
.formattedDashedGregorian
.toString(),
image: _base64Image.value, image: _base64Image.value,
personType: 'self', personType: 'self',
type: 'self_profile', type: 'self_profile',

View File

@@ -18,7 +18,6 @@ class ProfilePage extends GetView<ProfileLogic> {
spacing: 30, spacing: 30,
children: [ children: [
Expanded( Expanded(
child: Container( child: Container(
color: AppColor.blueNormal, color: AppColor.blueNormal,
child: Column( child: Column(
@@ -69,83 +68,127 @@ class ProfilePage extends GetView<ProfileLogic> {
flex: 3, flex: 3,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [ children: [
rolesWidget(), rolesWidget(),
SizedBox(height: 320.h, child: userProfileInformation()), SizedBox(height: 12.h,),
SizedBox( ObxValue((data) {
height: 130.h, if (data.value.status == ResourceStatus.loading) {
child: Container( return LoadingWidget();
margin: const EdgeInsets.symmetric(horizontal: 8), } else if (data.value.status == ResourceStatus.error) {
decoration: BoxDecoration( return ErrorWidget('خطا در دریافت اطلاعات کاربر');
color: Colors.white, } else if (data.value.status == ResourceStatus.success) {
borderRadius: BorderRadius.circular(8), return Column(
border: Border.all(width: 0.5, color: AppColor.darkGreyLight), spacing: 6,
children: [
ObxValue((isOpen) {
return GestureDetector(
onTap: () => isOpen.toggle(),
child: AnimatedContainer(
height: isOpen.value ? 320.h : 47.h,
duration: Duration(milliseconds: 500),
curve: Curves.linear,
child: userProfileInformation(data.value),
), ),
child: Stack( );
clipBehavior: Clip.none, }, controller.isUserInformationOpen),
children: [
Positioned.fill( Visibility(
child: Row( visible:
children: [ data.value.data?.unitName != null ||
Padding( data.value.data?.unitAddress != null ||
padding: EdgeInsets.fromLTRB(24, 28, 24, 13), data.value.data?.unitPostalCode != null ||
child: Wrap( data.value.data?.unitRegistrationNumber != null ||
spacing: 50, data.value.data?.unitEconomicalNumber != null ||
runSpacing: 20, data.value.data?.unitCity != null ||
children: [ data.value.data?.unitProvince != null ||
cardActionWidget( data.value.data?.unitNationalId != null,
title: 'تغییر رمز عبور',
selected: true, child: ObxValue((isOpen) {
cardColor: AppColor.blueLightActive, return GestureDetector(
cardIconColor: AppColor.blueNormal, onTap: () => isOpen.toggle(),
onPressed: () { child: AnimatedContainer(
height: isOpen.value ? 320.h : 47.h,
duration: Duration(milliseconds: 500),
curve: Curves.linear,
child: unitInformation(data.value),
),
);
}, controller.isUnitInformationOpen),
),
],
);
} else {
return SizedBox.shrink();
}
}, controller.userProfile),
GestureDetector(
onTap: () {
Get.bottomSheet( Get.bottomSheet(
changePasswordBottomSheet(), changePasswordBottomSheet(),
isScrollControlled: true, isScrollControlled: true,
); );
}, },
icon: Assets.vec.lockSvg.path,
),
cardActionWidget(
title: 'خروج',
selected: true,
cardColor: Color(0xFFF6BDBD),
cardIconColor: Color(0xFFEB5757),
textColor: AppColor.redDarkerText,
onPressed: () {
Get.bottomSheet(exitBottomSheet(), isScrollControlled: true);
},
icon: Assets.vec.logoutSvg.path,
),
],
),
),
],
),
),
Positioned(
right: 10,
top: -15,
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), height: 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 8.h),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)), border: Border.all(width: 1, color: const Color(0xFFD6D6D6)),
),
child: Text(
'اطلاعات هویتی',
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
), ),
child: Row(
spacing: 6,
children: [
Assets.vec.lockSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
), ),
Text(
'تغییر رمز عبور',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
), ),
], ],
),
)),
GestureDetector(
onTap: () {
Get.bottomSheet(
changePasswordBottomSheet(),
isScrollControlled: true,
);
},
child: Container(
height: 47.h,
margin: EdgeInsets.symmetric(horizontal: 8),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: const Color(0xFFD6D6D6)),
),
child: Row(
spacing: 6,
children: [
Assets.vec.logoutSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.redNormal, BlendMode.srcIn),
),
Text(
'خروج',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.redNormal),
),
],
),
)),
),
),
),
SizedBox(height: 100), SizedBox(height: 100),
], ],
@@ -157,7 +200,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: 'سامان'),
@@ -168,27 +212,25 @@ class ProfilePage extends GetView<ProfileLogic> {
], ],
); );
Widget userProfileInformation() { Widget userProfileInformation(Resource<UserProfile> value) {
return ObxValue((data) { UserProfile item = value.data!;
if (data.value.status == ResourceStatus.loading) {
return LoadingWidget();
} else if (data.value.status == ResourceStatus.error) {
return ErrorWidget('خطا در دریافت اطلاعات کاربر');
} else if (data.value.status == ResourceStatus.success) {
UserProfile item = data.value.data!;
return Stack( return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
Positioned.fill( Positioned.fill(
child: Container( child: ObxValue(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), (val) =>
Container(
height: val.value ? 320.h : 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 8 : 0),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h), padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: AppColor.darkGreyLight), border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
), ),
child: Column( child: val.value
? Column(
spacing: 6, spacing: 6,
children: [ children: [
Row( Row(
@@ -221,16 +263,17 @@ class ProfilePage extends GetView<ProfileLogic> {
icon: Assets.vec.userSvg.path, icon: Assets.vec.userSvg.path,
hasColoredBox: true, hasColoredBox: true,
), ),
itemList(
title: 'موبایل',
content: item.mobile ?? 'نامشخص',
icon: Assets.vec.callSvg.path,
),
itemList( itemList(
title: 'کدملی', title: 'کدملی',
content: item.nationalId ?? 'نامشخص', content: item.nationalId ?? 'نامشخص',
icon: Assets.vec.tagUserSvg.path, icon: Assets.vec.tagUserSvg.path,
), ),
itemList(
title: 'موبایل',
content: item.mobile ?? 'نامشخص',
icon: Assets.vec.callSvg.path,
),
itemList( itemList(
title: 'شماره شناسنامه', title: 'شماره شناسنامه',
content: item.nationalCode ?? 'نامشخص', content: item.nationalCode ?? 'نامشخص',
@@ -241,6 +284,7 @@ class ProfilePage extends GetView<ProfileLogic> {
content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص', content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص',
icon: Assets.vec.calendarSvg.path, icon: Assets.vec.calendarSvg.path,
), ),
//todo
itemList( itemList(
title: 'استان', title: 'استان',
content: item.province ?? 'نامشخص', content: item.province ?? 'نامشخص',
@@ -255,32 +299,165 @@ class ProfilePage extends GetView<ProfileLogic> {
), ),
), ),
], ],
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
), ),
), ),
controller.isUserInformationOpen,
), ),
),
Positioned( ObxValue(
(isOpen) =>
AnimatedPositioned(
right: 16, right: 16,
top: -7, top: isOpen.value ? -7 : 11,
duration: Duration(milliseconds: 500),
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration( decoration: isOpen.value
? BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)), border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
), )
: null,
child: Text( child: Text(
'اطلاعات هویتی', 'اطلاعات هویتی',
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor), style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
), ),
), ),
), ),
controller.isUserInformationOpen,
),
], ],
); );
} else {
return SizedBox.shrink();
} }
}, controller.userProfile);
Widget unitInformation(Resource<UserProfile> value) {
UserProfile item = value.data!;
return Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: ObxValue(
(val) =>
Container(
height: val.value ? 320.h : 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: val.value ? 12 : 0),
padding: EdgeInsets.symmetric(horizontal: 11.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
),
child: val.value
? Column(
children: [
SizedBox(height: 5.h),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
Get.bottomSheet(
userInformationBottomSheet(),
isScrollControlled: true,
ignoreSafeArea: false,
);
},
child: Assets.vec.editSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
child: Column(
spacing: 2,
children: [
itemList(
title: 'نام صنفی',
content: item.unitName ?? 'نامشخص',
hasColoredBox: true,
visible: item.unitName != null,
),
itemList(
title: 'شناسنامه ملی',
content: item.unitNationalId ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(
title: 'شماره ثبت',
content: item.unitRegistrationNumber ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(
title: 'کد اقتصادی',
content: item.unitEconomicalNumber ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(
title: 'کد پستی',
content: item.unitPostalCode ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(
title: 'استان',
content: item.province ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(
title: 'شهر',
content: item.city ?? 'نامشخص',
visible: item.unitName != null,
),
itemList(title: 'آدرس', content: item.unitAddress ?? 'نامشخص'),
],
),
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
),
),
controller.isUnitInformationOpen,
),
),
ObxValue(
(isOpen) =>
AnimatedPositioned(
right: 16,
top: isOpen.value ? -2 : 11,
duration: Duration(milliseconds: 500),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: isOpen.value
? BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
)
: null,
child: Text(
'اطلاعات صنفی',
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
),
),
),
controller.isUnitInformationOpen,
),
],
);
} }
Widget itemList({ Widget itemList({
@@ -288,7 +465,11 @@ class ProfilePage extends GetView<ProfileLogic> {
required String content, required String content,
String? icon, String? icon,
bool hasColoredBox = false, bool hasColoredBox = false,
}) => Container( bool? visible,
}) =>
Visibility(
visible: visible ?? true,
child: 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,
@@ -306,14 +487,15 @@ class ProfilePage extends GetView<ProfileLogic> {
child: SvgGenImage.vec(icon).svg( child: SvgGenImage.vec(icon).svg(
width: 20.w, width: 20.w,
height: 20.h, height: 20.h,
colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), colorFilter: ColorFilter.mode(AppColor.textColor, BlendMode.srcIn),
), ),
), ),
Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), Text(title, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
Spacer(), Spacer(),
Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), Text(content, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
], ],
), ),
),
); );
Widget cardActionWidget({ Widget cardActionWidget({

View File

@@ -1,7 +1,7 @@
name: rasadyar_app name: rasadyar_app
description: "A new Flutter project." description: "A new Flutter project."
publish_to: 'none' publish_to: 'none'
version: 1.3.25+22 version: 1.3.26+23
environment: environment:
sdk: ^3.9.2 sdk: ^3.9.2