fix profile

This commit is contained in:
2026-08-18 15:09:53 +03:00
parent 80a95ece5b
commit 6513a004d9
16 changed files with 268 additions and 26 deletions

View File

@@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
class DeleteAccountDialog extends StatelessWidget {
const DeleteAccountDialog({super.key});
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
insetPadding: const EdgeInsets.symmetric(horizontal: 40),
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: const Color(0xFF2E3253).withOpacity(0.95),
borderRadius: BorderRadius.circular(28),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"Удалить\nучётную запись?",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.w600,
height: 1.2,
),
),
const SizedBox(height: 16),
const Text(
"Это действие необратимо. Все ваши\nданные будут удалены безвозвратно",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white70,
fontSize: 14,
height: 1.4,
),
),
const SizedBox(height: 24),
Container(
width: double.infinity,
height: 52,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(26),
gradient: const LinearGradient(
colors: [Color(0xFFFF8E8E), Color(0xFFFE5F86)],
),
),
child: ElevatedButton(
onPressed: () => Navigator.pop(context, true),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(26),
),
),
child: const Text(
"Удалить",
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
height: 52,
child: ElevatedButton(
onPressed: () => Navigator.pop(context, false),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0D1024),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(26),
),
),
child: const Text(
"Отмена",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
),
],
),
),
);
}
}

View File

@@ -3,6 +3,8 @@ import 'package:be_happy/domain/entities/tariff.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../content_parser.dart';
class TariffInfoSheet extends StatefulWidget {
final Tariff tariff;
final bool isInsurance;
@@ -42,7 +44,6 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
),
child: Column(
children: [
// Полоска сверху (Handle)
const SizedBox(height: 12),
Container(
width: 40,
@@ -81,9 +82,9 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
const SizedBox(height: 30),
// Таблица цен
_buildPriceRow('Старт поездки', '${widget.tariff.startPrice} BYN'),
_buildPriceRow('Последующая минута', '${widget.tariff.drivePrice} BYN'),
_buildPriceRow('Пауза', '${widget.tariff.pausePrice} BYN/мин'),
_buildPriceRow('Старт поездки', '${widget.tariff.startPrice} руб.'),
_buildPriceRow('Последующая минута', '${widget.tariff.drivePrice} руб.'),
_buildPriceRow('Пауза', '${widget.tariff.pausePrice} руб./мин'),
_buildPriceRow('КЕШБЭК', '${widget.tariff.cashback * 100}%', isAccent: true),
const Divider(color: Colors.white24, height: 40),
@@ -98,7 +99,7 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
Image.asset('assets/icons/info_icon.png', width: 18, height: 18),
const Spacer(),
Text(
'${widget.tariff.insurance} BYN',
'${widget.tariff.insurance} руб.',
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(width: 12),
@@ -118,10 +119,14 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
const Divider(color: Colors.white24, height: 40),
_buildInfoBullet('Оплата страховки осуществляется только по банковской карте отдельным платежом'),
_buildInfoBullet('В режиме паузы время тарифа приостанавливается'),
_buildInfoBullet('При старте заказа будет заблокирована сумма в размере 7 рублей для проверки платежеспособности. Сумма разблокируется по факту списания средств за поездку.'),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: ContentParser.parseContent(
textJson: widget.tariff.description,
text: widget.tariff.descriptionJson,
),
),
const SizedBox(height: 30),
],
),

View File

@@ -281,7 +281,7 @@ class _TariffSheetState extends State<TariffSheet> {
subtitle: 'Старт поездки',
details: [
'Далее ${tariff.drivePrice.toStringAsFixed(2)} ${tariff.currency}/мин.',
'Минута на паузе ${tariff.pausePrice.toStringAsFixed(0)} ${tariff.currency}',
'Минута на паузе ${tariff.pausePrice.toStringAsFixed(2)} ${tariff.currency}',
],
isSelected: _selectedTariffIndex == index,
isInsurance: state.isInsurance,

View File

@@ -8,6 +8,8 @@ class ProfileStarted extends ProfileEvent {}
class ProfileUpdated extends ProfileEvent {}
class DeleteProfilePressed extends ProfileEvent {}
class ProfilePhotoUpdated extends ProfileEvent{
final File imageFile;

View File

@@ -77,6 +77,7 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
initialDate: _selectedBirthDate ?? DateTime.now(),
firstDate: DateTime(DateTime.now().year - 100),
lastDate: DateTime.now(),
locale: const Locale('ru', 'RU'),
);
if (picked != null && picked != _selectedBirthDate) {

View File

@@ -6,6 +6,7 @@ import '../../core/app_colors.dart';
import '../../domain/entities/user_profile.dart';
import '../components/custom_app_bar.dart';
import '../components/gradient_button.dart';
import '../components/dialog/delete_account_dialog.dart';
import '../viewmodel/profile_bloc.dart';
import 'edit_profile_screen.dart';
@@ -43,7 +44,19 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
Future<void> _openEditProfile(UserProfile profile) async {
context.go("/home/profile/edit");
context.go("/home/profile/edit");
}
Future<void> _confirmDeleteAccount(BuildContext context) async {
final confirmed = await showDialog<bool>(
context: context,
barrierColor: Colors.black.withOpacity(0.6),
builder: (dialogContext) => const DeleteAccountDialog(),
);
if (confirmed == true && context.mounted) {
context.read<ProfileBloc>().add(DeleteProfilePressed());
}
}
@override
@@ -136,12 +149,17 @@ class _ProfileScreenState extends State<ProfileScreen> {
onEditTap: () => context.go("/home/profile/edit"),
),
// const SizedBox(height: 24),
// _SettingsBlock(
// notificationsEnabled: notificationsEnabled,
// onNotificationsChanged: (v) =>
// setState(() => notificationsEnabled = v),
// ),
Padding(
padding: const EdgeInsets.all(20),
child: GradientButton(
text: 'Удалить учётную запись',
onTap: () => _confirmDeleteAccount(context),
showArrows: true,
height: 56,
width: double.infinity,
fontSize: 16,
),
),
],
),
),
@@ -370,4 +388,4 @@ class _SettingsBlock extends StatelessWidget {
),
);
}
}
}

View File

@@ -1,25 +1,38 @@
import 'dart:async';
import 'package:be_happy/domain/usecase/delete_profile_usecase.dart';
import 'package:be_happy/domain/usecase/upload_profile_photo_usecase.dart';
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/entities/user_profile.dart';
import '../../domain/usecase/get_profile_usecase.dart';
import '../../domain/usecase/logout_usecase.dart';
import '../../domain/usecase/update_profile_usecase.dart';
import '../event/profile_event.dart';
import '../event/spalsh_event.dart';
import '../state/profile_state.dart';
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final GetProfileUseCase getProfileUseCase;
final UploadProfilePhotoUsecase uploadProfilePhotoUsecase;
final UpdateProfileUseCase updateProfileUseCase;
final DeleteProfileUsecase deleteProfileUsecase;
final LogoutUseCase logoutUseCase;
final SplashBloc splashBloc;
ProfileBloc(this.getProfileUseCase,
this.uploadProfilePhotoUsecase,
this.updateProfileUseCase)
this.updateProfileUseCase,
this.deleteProfileUsecase,
this.logoutUseCase,
this.splashBloc)
: super(ProfileState.initial()) {
on<ProfileStarted>(_onStarted);
on<ProfileUpdated>(_onUpdated);
on<ProfilePhotoUpdated>(_onPhotoUploaded);
on<DeleteProfilePressed>(_onDeleteProfilePressed);
}
Future<void> _onStarted(
@@ -55,7 +68,6 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final avatarId = await uploadProfilePhotoUsecase(event.imageFile);
if (avatarId != null) {
// Отправляем PATCH запрос с новым avatarId
await updateProfileUseCase(UserProfile(
name: '',
birthDate: '',
@@ -72,4 +84,14 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
emit(state.copyWith(isLoading: false, error: "Ошибка загрузки: ${e.toString()}"));
}
}
FutureOr<void> _onDeleteProfilePressed(DeleteProfilePressed event, Emitter<ProfileState> emit) async {
try {
await deleteProfileUsecase();
splashBloc.add(AuthLogoutRequested());
} catch (e) {
emit(state.copyWith(isLoading: false, error: "Ошибка удаления профиля: ${e.toString()}"));
}
}
}