Files
c_trans_mobile/lib/features/profile/presentation/pages/profile_page.dart
jahongireshonqulov 1bf3e41abe Initial commit
2025-10-18 09:40:06 +05:00

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();
}
}