487 lines
21 KiB
Dart
487 lines
21 KiB
Dart
import 'dart:io';
|
|
import 'package:cargocalculaterapp/core/app_bloc/app_bloc.dart';
|
|
import 'package:cargocalculaterapp/core/extension/build_context_extension.dart';
|
|
import 'package:cargocalculaterapp/core/theme/app_text_styles.dart';
|
|
import 'package:cargocalculaterapp/core/theme/colors/app_colors.dart';
|
|
import 'package:cargocalculaterapp/core/theme/theme_data.dart';
|
|
import 'package:cargocalculaterapp/core/utils/app_utils.dart';
|
|
import 'package:cargocalculaterapp/core/widgets/text_filds/custom_text_field_name.dart';
|
|
import 'package:cargocalculaterapp/features/profile/presentation/pages/widgets/user_info_widget.dart';
|
|
import 'package:cargocalculaterapp/generated/l10n.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import '../../../../constants/constants.dart';
|
|
import '../../../../core/local_source/local_source.dart';
|
|
import '../../../../core/widgets/loading/progress_hud.dart';
|
|
import '../../../../injector_container.dart';
|
|
import '../../../../router/name_routes.dart';
|
|
import '../bloc/profile_bloc.dart';
|
|
import '../mixins/profile_mixin.dart';
|
|
import 'dialog/delete_profile_dialog.dart';
|
|
import 'dialog/language_dialog.dart';
|
|
|
|
class ProfilePage extends StatefulWidget {
|
|
const ProfilePage({super.key});
|
|
|
|
@override
|
|
State<ProfilePage> createState() => _ProfilePageState();
|
|
}
|
|
|
|
class _ProfilePageState extends State<ProfilePage> with ProfileMixin {
|
|
@override
|
|
void initState() {
|
|
initControllers();
|
|
context.read<ProfileBloc>().add(const GetProfileDataEvent());
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocConsumer<ProfileBloc, ProfileState>(
|
|
listenWhen: (previous, current) =>
|
|
previous.profileData != current.profileData,
|
|
listener: (context, state) {
|
|
fullNameController.text = state.profileData?.fullname ?? "";
|
|
emailController.text = state.profileData?.email ?? "";
|
|
phoneController.text = state.profileData?.phoneNumber ?? "";
|
|
},
|
|
builder: (context, state) {
|
|
return ModalProgressHUD(
|
|
inAsyncCall: state.isLoading,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
elevation: 0.5,
|
|
automaticallyImplyLeading: false,
|
|
title: Text(AppLocalization.current.profile),
|
|
),
|
|
body: ListView(
|
|
padding: AppUtils.kPaddingAll16,
|
|
children: [
|
|
state.readOnly
|
|
? Container(
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
top: 16,
|
|
),
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
color: context.color.statusBackground,
|
|
border: Border.all(color: context.color.lightBorder),
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
AppLocalization.current.personal_info,
|
|
style: context.text.orderTitle,
|
|
),
|
|
),
|
|
if (state.readOnly)
|
|
GestureDetector(
|
|
onTap: () {
|
|
context.read<ProfileBloc>().add(
|
|
const EditProfileEvent(),
|
|
);
|
|
},
|
|
child: SvgPicture.asset(
|
|
"assets/svg/ic_edit.svg",
|
|
),
|
|
),
|
|
],
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
UserInfoWidget(
|
|
title: AppLocalization.current.full_name,
|
|
name: state.profileData?.fullname ?? "-",
|
|
),
|
|
UserInfoWidget(
|
|
title: AppLocalization.current.phone_number,
|
|
name: state.profileData?.phoneNumber ?? "-",
|
|
),
|
|
UserInfoWidget(
|
|
title: AppLocalization.current.email,
|
|
name: state.profileData?.email ?? "-",
|
|
),
|
|
],
|
|
),
|
|
)
|
|
: Container(
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
top: 16,
|
|
),
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
color: context.color.statusBackground,
|
|
border: Border.all(color: context.color.lightBorder),
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
AppLocalization.current.personal_info,
|
|
style: context.text.orderTitle,
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
CustomTextFieldName(
|
|
hint: AppLocalization.current.full_name_hint,
|
|
name: AppLocalization.current.full_name,
|
|
controller: fullNameController,
|
|
inputType: TextInputType.name,
|
|
errorText:
|
|
AppLocalization.current.error_full_name,
|
|
isError:
|
|
(state.hasError ?? false) &&
|
|
(fullNameController.text.isNotEmpty),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
CustomTextFieldName(
|
|
hint: AppLocalization.current.phone_number_text,
|
|
name: AppLocalization.current.phone_number,
|
|
controller: phoneController,
|
|
inputType: TextInputType.phone,
|
|
errorText: AppLocalization.current.error_in_phone,
|
|
isError:
|
|
(state.hasError ?? false) &&
|
|
!RegExConst.phoneRegex.hasMatch(
|
|
phoneController.text,
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
CustomTextFieldName(
|
|
hint: AppLocalization.current.email_address,
|
|
name: AppLocalization.current.email,
|
|
controller: emailController,
|
|
inputType: TextInputType.emailAddress,
|
|
errorText: AppLocalization.current.error_email,
|
|
isError:
|
|
(state.hasError ?? false) &&
|
|
!RegExConst.emailRegex.hasMatch(
|
|
emailController.text,
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
context.read<ProfileBloc>().add(
|
|
UpdateProfileEvent(
|
|
fullName: fullNameController.text,
|
|
email: emailController.text,
|
|
phone: phoneController.text,
|
|
),
|
|
);
|
|
},
|
|
child: Text(AppLocalization.current.save),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
],
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
Material(
|
|
color: Colors.transparent,
|
|
child: InkWell(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
onTap: () {
|
|
Clipboard.setData(
|
|
ClipboardData(text: sl<LocalSource>().getUCode()),
|
|
);
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(AppLocalization.current.text_copied),
|
|
),
|
|
);
|
|
},
|
|
child: Ink(
|
|
padding: AppUtils.kPaddingHor16,
|
|
height: 56,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
color: context.color.scaffoldBackgroundColor,
|
|
border: Border.all(color: context.color.borderColor),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.numbers_outlined,
|
|
size: 24,
|
|
color: context.color.textColor,
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Text(
|
|
AppLocalization.current.user_id,
|
|
style: context.text.profileCategory,
|
|
),
|
|
const Spacer(),
|
|
Text(
|
|
sl<LocalSource>().getUCode(),
|
|
style: context.text.statusNumber,
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Icon(
|
|
Icons.copy_outlined,
|
|
color: context.color.textColor,
|
|
size: 16,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
Material(
|
|
color: Colors.transparent,
|
|
child: InkWell(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
onTap: () {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
isDismissible: true,
|
|
builder: (context) => const LanguageDialog(),
|
|
);
|
|
},
|
|
child: Ink(
|
|
padding: AppUtils.kPaddingHor16,
|
|
height: 56,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
color: context.color.scaffoldBackgroundColor,
|
|
border: Border.all(color: context.color.borderColor),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
"assets/svg/ic_world.svg",
|
|
width: 24,
|
|
height: 24,
|
|
colorFilter: ColorFilter.mode(
|
|
context.color.textColor,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Text(
|
|
AppLocalization.current.change_language,
|
|
style: context.text.profileCategory,
|
|
),
|
|
const Spacer(),
|
|
Text(
|
|
sl<LocalSource>().getLocale() == "uz"
|
|
? "O'zbek"
|
|
: sl<LocalSource>().getLocale() == "ru"
|
|
? "Русский"
|
|
: "Chinese",
|
|
style: context.text.statusNumber,
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Icon(
|
|
Icons.arrow_forward_ios_rounded,
|
|
color: context.color.textColor,
|
|
size: 16,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
Material(
|
|
color: Colors.transparent,
|
|
child: InkWell(
|
|
onTap: () {
|
|
if (sl<LocalSource>().getThemeMode() ==
|
|
ThemeMode.light.name) {
|
|
context.read<AppBloc>().add(
|
|
AppThemeSwitchDark(darkTheme: darkTheme),
|
|
);
|
|
} else {
|
|
context.read<AppBloc>().add(
|
|
AppThemeSwitchLight(lightTheme: lightTheme),
|
|
);
|
|
}
|
|
},
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
child: Ink(
|
|
padding: AppUtils.kPaddingHor16,
|
|
height: 56,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius16,
|
|
color: context.color.scaffoldBackgroundColor,
|
|
border: Border.all(color: context.color.borderColor),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
"assets/svg/ic_sun.svg",
|
|
width: 24,
|
|
height: 24,
|
|
colorFilter: ColorFilter.mode(
|
|
context.color.textColor,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Text(
|
|
AppLocalization.current.theme_mode,
|
|
style: context.text.profileCategory,
|
|
),
|
|
const Spacer(),
|
|
Text(
|
|
sl<LocalSource>().getThemeMode() ==
|
|
ThemeMode.light.name
|
|
? AppLocalization.current.light
|
|
: AppLocalization.current.dark,
|
|
style: context.text.statusNumber,
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
width: 24,
|
|
height: 16,
|
|
padding: const EdgeInsets.all(2),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: Colors.black, width: 2),
|
|
),
|
|
alignment:
|
|
sl<LocalSource>().getThemeMode() ==
|
|
ThemeMode.light.name
|
|
? Alignment.centerRight
|
|
: Alignment.centerLeft,
|
|
child: Container(
|
|
width: 8,
|
|
height: 8,
|
|
decoration: const BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight16,
|
|
Material(
|
|
color: Colors.transparent,
|
|
child: Padding(
|
|
padding: AppUtils.kPaddingHor24,
|
|
child: InkWell(
|
|
borderRadius: AppUtils.kBorderRadius24,
|
|
onTap: () async {
|
|
final language = sl<LocalSource>().getLocale();
|
|
await sl<LocalSource>().clear().then((value) {
|
|
sl<LocalSource>().setLocale(language);
|
|
sl<LocalSource>().setIsFirstEnter(false);
|
|
if (context.mounted) {
|
|
Navigator.pushNamedAndRemoveUntil(
|
|
context,
|
|
Routes.auth,
|
|
(route) => false,
|
|
);
|
|
}
|
|
});
|
|
},
|
|
child: Ink(
|
|
padding: AppUtils.kPaddingHor16,
|
|
height: 56,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
borderRadius: AppUtils.kBorderRadius24,
|
|
color: context.color.scaffoldBackgroundColor,
|
|
border: Border.all(color: context.color.borderColor),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
SvgPicture.asset(
|
|
"assets/svg/ic_log_out.svg",
|
|
width: 24,
|
|
height: 24,
|
|
colorFilter: const ColorFilter.mode(
|
|
ThemeColors.timerRed,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
AppUtils.kBoxWidth8,
|
|
Text(
|
|
AppLocalization.current.logout,
|
|
style: AppTextStyles.saleRed,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
AppUtils.kBoxHeight24,
|
|
//if (Platform.isIOS)
|
|
SizedBox(
|
|
height:
|
|
MediaQuery.of(context).size.height -
|
|
MediaQuery.of(context).padding.top -
|
|
MediaQuery.of(context).padding.bottom -
|
|
kBottomNavigationBarHeight-600
|
|
),
|
|
if (Platform.isIOS)
|
|
Center(
|
|
child: TextButton.icon(
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => const DeleteProfileDialog(),
|
|
).then((value) {
|
|
if (value is bool && context.mounted) {
|
|
context.read<ProfileBloc>().add(
|
|
const DeleteProfileEvent(),
|
|
);
|
|
}
|
|
});
|
|
},
|
|
label: Text(
|
|
AppLocalization.current.delete_account,
|
|
style: AppTextStyles.orderTitle,
|
|
),
|
|
icon: SvgPicture.asset(
|
|
"assets/svg/ic_trash.svg",
|
|
width: 18,
|
|
height: 18,
|
|
colorFilter: ColorFilter.mode(
|
|
context.color.textColor,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
disposeControllers();
|
|
super.dispose();
|
|
}
|
|
}
|