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
flutter.sdk=C:\\src\\flutter
flutter.buildMode=debug
flutter.versionName=1.3.25
flutter.versionCode=22
flutter.buildMode=release
flutter.versionName=1.3.26
flutter.versionCode=23

View File

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

View File

@@ -18,7 +18,6 @@ class ProfilePage extends GetView<ProfileLogic> {
spacing: 30,
children: [
Expanded(
child: Container(
color: AppColor.blueNormal,
child: Column(
@@ -69,83 +68,127 @@ class ProfilePage extends GetView<ProfileLogic> {
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [
rolesWidget(),
SizedBox(height: 320.h, child: userProfileInformation()),
SizedBox(height: 12.h,),
SizedBox(
height: 130.h,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
),
child: Stack(
clipBehavior: Clip.none,
ObxValue((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) {
return Column(
spacing: 6,
children: [
Positioned.fill(
child: Row(
children: [
Padding(
padding: EdgeInsets.fromLTRB(24, 28, 24, 13),
child: Wrap(
spacing: 50,
runSpacing: 20,
children: [
cardActionWidget(
title: 'تغییر رمز عبور',
selected: true,
cardColor: AppColor.blueLightActive,
cardIconColor: AppColor.blueNormal,
onPressed: () {
Get.bottomSheet(
changePasswordBottomSheet(),
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,
),
],
),
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),
),
);
}, controller.isUserInformationOpen),
Visibility(
visible:
data.value.data?.unitName != null ||
data.value.data?.unitAddress != null ||
data.value.data?.unitPostalCode != null ||
data.value.data?.unitRegistrationNumber != null ||
data.value.data?.unitEconomicalNumber != null ||
data.value.data?.unitCity != null ||
data.value.data?.unitProvince != null ||
data.value.data?.unitNationalId != null,
child: ObxValue((isOpen) {
return GestureDetector(
onTap: () => isOpen.toggle(),
child: AnimatedContainer(
height: isOpen.value ? 320.h : 47.h,
duration: Duration(milliseconds: 500),
curve: Curves.linear,
child: unitInformation(data.value),
),
],
),
),
Positioned(
right: 10,
top: -15,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
),
child: Text(
'اطلاعات هویتی',
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
),
),
);
}, controller.isUnitInformationOpen),
),
],
);
} else {
return SizedBox.shrink();
}
}, controller.userProfile),
GestureDetector(
onTap: () {
Get.bottomSheet(
changePasswordBottomSheet(),
isScrollControlled: true,
);
},
child: Container(
height: 47.h,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 8.h),
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.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),
],
@@ -157,130 +200,264 @@ class ProfilePage extends GetView<ProfileLogic> {
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) {
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(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
),
child: Column(
spacing: 6,
children: [
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(
Widget userProfileInformation(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 ? 8 : 0),
padding: EdgeInsets.symmetric(horizontal: 11.h, vertical: 8.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: AppColor.darkGreyLight),
),
child: val.value
? Column(
spacing: 6,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
itemList(
title: 'نام و نام خانوادگی',
content: item.fullname ?? 'نامشخص',
icon: Assets.vec.userSvg.path,
hasColoredBox: true,
),
itemList(
title: 'موبایل',
content: item.mobile ?? 'نامشخص',
icon: Assets.vec.callSvg.path,
),
itemList(
title: 'کدملی',
content: item.nationalId ?? 'نامشخص',
icon: Assets.vec.tagUserSvg.path,
),
itemList(
title: 'شماره شناسنامه',
content: item.nationalCode ?? 'نامشخص',
icon: Assets.vec.userSquareSvg.path,
),
itemList(
title: 'تاریخ تولد',
content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص',
icon: Assets.vec.calendarSvg.path,
),
itemList(
title: 'استان',
content: item.province ?? 'نامشخص',
icon: Assets.vec.pictureFrameSvg.path,
),
itemList(
title: 'شهر',
content: item.city ?? 'نامشخص',
icon: Assets.vec.mapSvg.path,
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),
),
),
],
),
),
],
),
),
),
Positioned(
right: 16,
top: -7,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.5, color: Color(0xFFA9A9A9)),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
child: Column(
children: [
itemList(
title: 'نام و نام خانوادگی',
content: item.fullname ?? 'نامشخص',
icon: Assets.vec.userSvg.path,
hasColoredBox: true,
),
itemList(
title: 'کدملی',
content: item.nationalId ?? 'نامشخص',
icon: Assets.vec.tagUserSvg.path,
),
itemList(
title: 'موبایل',
content: item.mobile ?? 'نامشخص',
icon: Assets.vec.callSvg.path,
),
itemList(
title: 'شماره شناسنامه',
content: item.nationalCode ?? 'نامشخص',
icon: Assets.vec.userSquareSvg.path,
),
itemList(
title: 'تاریخ تولد',
content: item.birthday?.toJalali.formatCompactDate() ?? 'نامشخص',
icon: Assets.vec.calendarSvg.path,
),
//todo
itemList(
title: 'استان',
content: item.province ?? 'نامشخص',
icon: Assets.vec.pictureFrameSvg.path,
),
itemList(
title: 'شهر',
content: item.city ?? 'نامشخص',
icon: Assets.vec.mapSvg.path,
),
],
),
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Icon(CupertinoIcons.chevron_down, color: AppColor.iconColor)],
),
),
child: Text(
'اطلاعات هویتی',
style: AppFonts.yekan16.copyWith(color: AppColor.iconColor),
controller.isUserInformationOpen,
),
),
ObxValue(
(isOpen) =>
AnimatedPositioned(
right: 16,
top: isOpen.value ? -7 : 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),
),
),
),
),
],
);
} else {
return SizedBox.shrink();
}
}, controller.userProfile);
controller.isUserInformationOpen,
),
],
);
}
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({
@@ -288,33 +465,38 @@ class ProfilePage extends GetView<ProfileLogic> {
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),
),
bool? visible,
}) =>
Visibility(
visible: visible ?? true,
child: 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),
),
Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)),
Spacer(),
Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)),
],
),
);
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.textColor, BlendMode.srcIn),
),
),
Text(title, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
Spacer(),
Text(content, style: AppFonts.yekan14.copyWith(color: AppColor.textColor)),
],
),
),
);
Widget cardActionWidget({
required String title,
@@ -458,11 +640,11 @@ class ProfilePage extends GetView<ProfileLogic> {
child: Center(
child: data.value == null
? Padding(
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
child: Image.network(
controller.userProfile.value.data?.image ?? '',
),
)
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),
),
);

View File

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