765 lines
45 KiB
Dart
765 lines
45 KiB
Dart
// ignore_for_file: deprecated_member_use_from_same_package, use_build_context_synchronously
|
|
|
|
import 'package:cross_file/cross_file.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:easy_debounce/easy_debounce.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:hoshan/core/gen/assets.gen.dart';
|
|
import 'package:hoshan/core/services/api/dio_service.dart';
|
|
import 'package:hoshan/data/model/ai/credit_model.dart';
|
|
import 'package:hoshan/data/repository/auth_repository.dart';
|
|
import 'package:hoshan/ui/screens/setting/cubit/check_username_cubit.dart';
|
|
import 'package:hoshan/ui/screens/splash/cubit/user_info_cubit.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/responsive.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/animations/animated_visibility.dart';
|
|
import 'package:hoshan/ui/widgets/components/button/circle_icon_btn.dart';
|
|
import 'package:hoshan/ui/widgets/components/button/loading_button.dart';
|
|
import 'package:hoshan/ui/widgets/components/dialog/bottom_sheets.dart';
|
|
import 'package:hoshan/ui/widgets/components/dialog/dialog_handler.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/custome_image.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/network_image.dart';
|
|
import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart';
|
|
import 'package:hoshan/ui/widgets/components/text/auth_text_field.dart';
|
|
import 'package:hoshan/ui/widgets/components/text/card_number_input.dart';
|
|
import 'package:hoshan/ui/widgets/sections/header/reversible_appbar.dart';
|
|
|
|
class EditProfilePage extends StatefulWidget {
|
|
const EditProfilePage({super.key});
|
|
|
|
@override
|
|
State<EditProfilePage> createState() => _EditProfilePageState();
|
|
}
|
|
|
|
class _EditProfilePageState extends State<EditProfilePage> {
|
|
TextEditingController username = TextEditingController();
|
|
TextEditingController mobile = TextEditingController();
|
|
TextEditingController email = TextEditingController();
|
|
TextEditingController pasword = TextEditingController();
|
|
TextEditingController rePassword = TextEditingController();
|
|
String? imageUrl;
|
|
String cardNumber = '';
|
|
final ValueNotifier<XFile?> image = ValueNotifier(null);
|
|
final ValueNotifier<bool> loading = ValueNotifier(false);
|
|
final ValueNotifier<bool> showCard = ValueNotifier(false);
|
|
|
|
@override
|
|
void initState() {
|
|
imageUrl = UserInfoCubit.userInfoModel.image;
|
|
|
|
if (UserInfoCubit.userInfoModel.cardNumber != null) {
|
|
cardNumber = UserInfoCubit.userInfoModel.cardNumber!;
|
|
showCard.value = true;
|
|
}
|
|
if (UserInfoCubit.userInfoModel.username != null) {
|
|
username.text = UserInfoCubit.userInfoModel.username!;
|
|
}
|
|
if (UserInfoCubit.userInfoModel.mobileNumber != null) {
|
|
mobile.text = UserInfoCubit.userInfoModel.mobileNumber!;
|
|
}
|
|
if (UserInfoCubit.userInfoModel.email != null) {
|
|
email.text = UserInfoCubit.userInfoModel.email!;
|
|
}
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: ReversibleAppbar(
|
|
context,
|
|
titleText: 'ویرایش پروفایل',
|
|
),
|
|
body: Responsive(context).maxWidthInDesktop(
|
|
child: (contxet, maxWidth) => Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
physics: const BouncingScrollPhysics(),
|
|
child: BlocConsumer<UserInfoCubit, UserInfoState>(
|
|
listener: (context, state) {},
|
|
builder: (context, state) {
|
|
return Column(
|
|
children: [
|
|
Center(
|
|
child: Stack(
|
|
children: [
|
|
ValueListenableBuilder(
|
|
valueListenable: image,
|
|
builder: (context, date, _) {
|
|
return Container(
|
|
width: 140,
|
|
height: 140,
|
|
margin: const EdgeInsets.only(
|
|
top: 24, bottom: 40),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.gray[300],
|
|
shape: BoxShape.circle,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
blurRadius: 6,
|
|
color: const Color(0xff4d4d4d)
|
|
.withValues(alpha: 0.4))
|
|
]),
|
|
child: ClipOval(
|
|
child: date != null
|
|
? GestureDetector(
|
|
onTap: () => DialogHandler(
|
|
context: context)
|
|
.showImageHero(
|
|
image: date.path),
|
|
child: CustomeImage(
|
|
src: date.path,
|
|
fit: BoxFit.cover,
|
|
),
|
|
)
|
|
: imageUrl != null &&
|
|
imageUrl!.isNotEmpty
|
|
? ImageNetwork(
|
|
url: DioService.baseURL +
|
|
imageUrl!,
|
|
showHero: true,
|
|
)
|
|
: Padding(
|
|
padding:
|
|
const EdgeInsets.all(
|
|
32),
|
|
child: Assets
|
|
.icon.bold.profile
|
|
.svg(),
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
Positioned(
|
|
bottom: 0 + 40,
|
|
left: 0,
|
|
child: CircleIconBtn(
|
|
icon: Assets.icon.outline.galleryAdd,
|
|
color: AppColors.secondryColor.defaultShade,
|
|
iconColor: Colors.white,
|
|
size: 48,
|
|
iconPadding: const EdgeInsets.all(10),
|
|
onTap: () =>
|
|
BottomSheetHandler(context).showPickImage(
|
|
withAvatar: true,
|
|
profile: true,
|
|
onSelect: (file) {
|
|
image.value = file;
|
|
},
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Column(
|
|
children: [
|
|
BlocBuilder<CheckUsernameCubit,
|
|
CheckUsernameState>(
|
|
builder: (context, state) {
|
|
return Column(
|
|
children: [
|
|
AuthTextField(
|
|
justEnglish: true,
|
|
success: state is CheckUsernameSuccess
|
|
? Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(
|
|
Icons.check_circle,
|
|
color: AppColors
|
|
.green.defaultShade,
|
|
size: 16,
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
'نام کاربری در دسترس است',
|
|
style: AppTextStyles
|
|
.body5
|
|
.copyWith(
|
|
color: AppColors
|
|
.green
|
|
.defaultShade),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
: null,
|
|
error: state is CheckUsernameFail ||
|
|
state is CheckUsernameEmpty
|
|
? Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(
|
|
Icons
|
|
.warning_amber_rounded,
|
|
color: AppColors
|
|
.red.defaultShade,
|
|
size: 16,
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
state is CheckUsernameFail
|
|
? 'نام کاربری قبلا انتخاب شده است'
|
|
: 'نام کاربری کوتاه است',
|
|
style: AppTextStyles
|
|
.body5
|
|
.copyWith(
|
|
color: AppColors
|
|
.red
|
|
.defaultShade),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
: null,
|
|
label: 'نام کاربری',
|
|
suffix: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Assets
|
|
.icon.outline.profileTick
|
|
.svg(
|
|
color: state
|
|
is CheckUsernameFail
|
|
? AppColors
|
|
.red.defaultShade
|
|
: state
|
|
is CheckUsernameSuccess
|
|
? AppColors.green
|
|
.defaultShade
|
|
: Theme.of(context)
|
|
.colorScheme
|
|
.primary),
|
|
),
|
|
controller: username,
|
|
onChange: (usernameText) {
|
|
context
|
|
.read<CheckUsernameCubit>()
|
|
.loading();
|
|
EasyDebounce.debounce('my-username',
|
|
const Duration(seconds: 1), () {
|
|
context
|
|
.read<CheckUsernameCubit>()
|
|
.check(usernameText);
|
|
});
|
|
},
|
|
),
|
|
if (state is CheckUsernameLoading)
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 18, vertical: 4),
|
|
child: Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(
|
|
width: 16,
|
|
height: 16,
|
|
child:
|
|
CircularProgressIndicator(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
'درحال بررسی',
|
|
style: AppTextStyles.body5
|
|
.copyWith(
|
|
color: Theme.of(
|
|
context)
|
|
.colorScheme
|
|
.primary),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
);
|
|
},
|
|
),
|
|
|
|
if (mobile.text.isNotEmpty)
|
|
Column(
|
|
children: [
|
|
const SizedBox(
|
|
height: 24,
|
|
),
|
|
AuthTextField(
|
|
label: 'تلفن همراه',
|
|
enabled: false,
|
|
suffix: Padding(
|
|
padding: const EdgeInsets.all(10.0),
|
|
child: Assets.icon.outline.call.svg(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary),
|
|
),
|
|
controller: mobile,
|
|
),
|
|
],
|
|
),
|
|
if (email.text.isNotEmpty)
|
|
Column(
|
|
children: [
|
|
const SizedBox(
|
|
height: 24,
|
|
),
|
|
AuthTextField(
|
|
label: 'ایمیل',
|
|
enabled: false,
|
|
suffix: Padding(
|
|
padding: const EdgeInsets.all(10.0),
|
|
child: Icon(Icons.email_rounded,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary)),
|
|
controller: email,
|
|
),
|
|
],
|
|
),
|
|
// const SizedBox(
|
|
// height: 24,
|
|
// ),
|
|
// AuthTextField(
|
|
// label: 'آدرس ایمیل',
|
|
// suffix: Padding(
|
|
// padding: const EdgeInsets.all(10.0),
|
|
// child: Assets.icon.outline.smsTracking.svg(),
|
|
// ),
|
|
// controller: email,
|
|
// ),
|
|
const SizedBox(
|
|
height: 24,
|
|
),
|
|
ValueListenableBuilder(
|
|
valueListenable: rePassword,
|
|
builder: (context, rePass, child) {
|
|
return ValueListenableBuilder(
|
|
valueListenable: pasword,
|
|
builder: (context, pass, child) {
|
|
return Column(
|
|
children: [
|
|
// AuthTextField(
|
|
// label: 'رمز عبور',
|
|
// textInputAction:
|
|
// TextInputAction.next,
|
|
// suffix: Padding(
|
|
// padding: const EdgeInsets.all(
|
|
// 10.0),
|
|
// child: Assets
|
|
// .icon.outline.lock
|
|
// .svg(
|
|
// color: pass.text !=
|
|
// rePass.text
|
|
// ? AppColors.red
|
|
// .defaultShade
|
|
// : Theme.of(
|
|
// context)
|
|
// .colorScheme
|
|
// .primary),
|
|
// ),
|
|
// controller: pasword,
|
|
// error: pass.text.length < 8 &&
|
|
// pass.text.isNotEmpty
|
|
// ? Row(
|
|
// crossAxisAlignment:
|
|
// CrossAxisAlignment
|
|
// .start,
|
|
// children: [
|
|
// Icon(
|
|
// Icons
|
|
// .warning_amber_rounded,
|
|
// color: AppColors.red
|
|
// .defaultShade,
|
|
// size: 16,
|
|
// ),
|
|
// const SizedBox(
|
|
// width: 8,
|
|
// ),
|
|
// Expanded(
|
|
// child: Text(
|
|
// 'رمز عبور حداقل باید ۸ کارکتر باشد',
|
|
// style: AppTextStyles
|
|
// .body5
|
|
// .copyWith(
|
|
// color: AppColors
|
|
// .red
|
|
// .defaultShade),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// )
|
|
// : pass.text != rePass.text
|
|
// ? const SizedBox()
|
|
// : null,
|
|
// ),
|
|
// const SizedBox(
|
|
// height: 24,
|
|
// ),
|
|
// ValueListenableBuilder(
|
|
// valueListenable: rePassword,
|
|
// builder:
|
|
// (context, pass, child) {
|
|
// return AuthTextField(
|
|
// label: 'تکرار رمز عبور',
|
|
// suffix: Padding(
|
|
// padding:
|
|
// const EdgeInsets.all(
|
|
// 10.0),
|
|
// child: Assets
|
|
// .icon.outline.lock
|
|
// .svg(
|
|
// color: pasword
|
|
// .text !=
|
|
// pass.text
|
|
// ? AppColors
|
|
// .red
|
|
// .defaultShade
|
|
// : Theme.of(
|
|
// context)
|
|
// .colorScheme
|
|
// .primary),
|
|
// ),
|
|
// controller: rePassword,
|
|
// error:
|
|
// pasword.text !=
|
|
// pass.text
|
|
// ? Row(
|
|
// crossAxisAlignment:
|
|
// CrossAxisAlignment
|
|
// .start,
|
|
// children: [
|
|
// Icon(
|
|
// Icons
|
|
// .warning_amber_rounded,
|
|
// color: AppColors
|
|
// .red
|
|
// .defaultShade,
|
|
// size: 16,
|
|
// ),
|
|
// const SizedBox(
|
|
// width: 8,
|
|
// ),
|
|
// Expanded(
|
|
// child: Text(
|
|
// 'رمز عبور با تکرار آن مطابقت ندارد',
|
|
// style: AppTextStyles
|
|
// .body5
|
|
// .copyWith(
|
|
// color: AppColors.red.defaultShade),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// )
|
|
// : null,
|
|
// );
|
|
// },
|
|
// ),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}),
|
|
|
|
const SizedBox(
|
|
height: 24,
|
|
),
|
|
ValueListenableBuilder(
|
|
valueListenable: showCard,
|
|
builder: (context, show, child) {
|
|
return Column(
|
|
children: [
|
|
// GestureDetector(
|
|
// onTap: () => showCard.value = !show,
|
|
// child: Row(
|
|
// children: [
|
|
// Transform.scale(
|
|
// scale: 1.4,
|
|
// child: Checkbox(
|
|
// value: show,
|
|
// activeColor: AppColors
|
|
// .secondryColor
|
|
// .defaultShade,
|
|
// side: BorderSide(
|
|
// width: 1,
|
|
// color: Theme.of(context)
|
|
// .colorScheme
|
|
// .onSurface),
|
|
// onChanged: (value) {
|
|
// showCard.value =
|
|
// value ?? false;
|
|
// },
|
|
// materialTapTargetSize:
|
|
// MaterialTapTargetSize
|
|
// .shrinkWrap,
|
|
// shape:
|
|
// RoundedRectangleBorder(
|
|
// borderRadius:
|
|
// BorderRadius
|
|
// .circular(
|
|
// 6)),
|
|
// ),
|
|
// ),
|
|
// // Expanded(
|
|
// // child: Text(
|
|
// // 'تمایل به کسب درآمد از طریق ساخت دستیار دارم.',
|
|
// // style: AppTextStyles.body4
|
|
// // .copyWith(
|
|
// // color: Theme.of(
|
|
// // context)
|
|
// // .colorScheme
|
|
// // .onSurface),
|
|
// // ),
|
|
// // ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
AnimatedVisibility(
|
|
isVisible: show,
|
|
duration: const Duration(
|
|
milliseconds: 300),
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(
|
|
height: 24,
|
|
),
|
|
Text(
|
|
'وارد کردن شماره کارت برای دریافت درآمد:',
|
|
style: AppTextStyles.body4
|
|
.copyWith(
|
|
color: Theme.of(
|
|
context)
|
|
.colorScheme
|
|
.onSurface),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets
|
|
.symmetric(
|
|
vertical: 8.0),
|
|
child: CardNumberInput(
|
|
initialValue: cardNumber,
|
|
onChange: (value) {
|
|
cardNumber = value;
|
|
},
|
|
),
|
|
),
|
|
Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.start,
|
|
children: [
|
|
Icon(
|
|
Icons
|
|
.warning_amber_rounded,
|
|
color: AppColors
|
|
.red.defaultShade,
|
|
size: 32,
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
'شماره کارت شما برای انتقال درآمد ماهانه استفاده میشود. حریم خصوصی شما تضمین شده است و اطلاعات شما کاملا محرمانه خواهد بود.',
|
|
textAlign:
|
|
TextAlign.justify,
|
|
style: AppTextStyles
|
|
.body5
|
|
.copyWith(
|
|
color: AppColors
|
|
.black[
|
|
300]),
|
|
),
|
|
)
|
|
],
|
|
)
|
|
],
|
|
))
|
|
],
|
|
);
|
|
}),
|
|
const SizedBox(
|
|
height: 40,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
|
|
color: Theme.of(context).scaffoldBackgroundColor,
|
|
child: ValueListenableBuilder(
|
|
valueListenable: loading,
|
|
builder: (context, data, _) {
|
|
return LoadingButton(
|
|
width: MediaQuery.sizeOf(context).width,
|
|
height: 40,
|
|
color: AppColors.primaryColor.defaultShade,
|
|
loading: data,
|
|
radius: 24,
|
|
onPressed: data
|
|
? null
|
|
: () async {
|
|
try {
|
|
loading.value = true;
|
|
|
|
if (username.text !=
|
|
UserInfoCubit.userInfoModel.username &&
|
|
(context.read<CheckUsernameCubit>().state
|
|
is CheckUsernameSuccess)) {
|
|
try {
|
|
await AuthRepository.editUsername(
|
|
username.text);
|
|
} on DioException catch (e) {
|
|
SnackBarManager(context,
|
|
id: 'changeUsername')
|
|
.show(
|
|
status: SnackBarStatus.error,
|
|
message:
|
|
'خطا در تغییر نام کاربری دوباره سعی کنید');
|
|
Future.delayed(const Duration(seconds: 3));
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
}
|
|
if (pasword.text.isNotEmpty) {
|
|
if (pasword.text == rePassword.text) {
|
|
try {
|
|
await AuthRepository.editPasswordProfile(
|
|
pasword.text);
|
|
} on DioException catch (e) {
|
|
SnackBarManager(context,
|
|
id: 'changePassword')
|
|
.show(
|
|
status: SnackBarStatus.error,
|
|
message:
|
|
'خطا در تغییر رمز دوباره سعی کنید');
|
|
Future.delayed(
|
|
const Duration(seconds: 3));
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (image.value != null) {
|
|
try {
|
|
await AuthRepository.editImageProfile(
|
|
image.value!);
|
|
} on DioException catch (e) {
|
|
SnackBarManager(context, id: 'changeImage')
|
|
.show(
|
|
status: SnackBarStatus.error,
|
|
message:
|
|
'خطا در آپلود فایل دوباره سعی کنید');
|
|
Future.delayed(const Duration(seconds: 3));
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
// if (cardNumber !=
|
|
// UserInfoCubit.userInfoModel.cardNumber) {
|
|
// if (cardNumber.length == 16 ||
|
|
// cardNumber.isEmpty) {
|
|
try {
|
|
await AuthRepository.editCardNumber(
|
|
showCard.value ? cardNumber : '');
|
|
} on DioException catch (e) {
|
|
SnackBarManager(context, id: 'changeCard')
|
|
.show(
|
|
status: SnackBarStatus.error,
|
|
message:
|
|
'خطا در ثبت شماره کارت دوباره سعی کنید',
|
|
);
|
|
Future.delayed(const Duration(seconds: 3));
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
// }
|
|
// }
|
|
|
|
try {
|
|
await context
|
|
.read<UserInfoCubit>()
|
|
.getUserInfo()
|
|
.then(
|
|
(value) {
|
|
SnackBarManager(context).show(
|
|
status: SnackBarStatus.success,
|
|
message:
|
|
'اطلاعات با موفقیت بروزرسانی شد');
|
|
},
|
|
);
|
|
context.read<UserInfoCubit>().changeCredit(
|
|
CreditModel(
|
|
credit: UserInfoCubit
|
|
.userInfoModel.credit,
|
|
freeCredit: UserInfoCubit
|
|
.userInfoModel.freeCredit));
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
loading.value = false;
|
|
},
|
|
child: Text(
|
|
'تایید',
|
|
style:
|
|
AppTextStyles.body4.copyWith(color: Colors.white),
|
|
),
|
|
);
|
|
}),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|