feat(blackList): Issue-523

This commit is contained in:
mso7nueh
2025-06-30 14:27:10 +03:00
parent 693260afb6
commit d4a05f47d1
24 changed files with 313 additions and 6 deletions

View File

@@ -0,0 +1,29 @@
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_state.dart';
import 'package:eatvio_app/features/menu/presentation/repositories/blocked_users_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BlockedUsersCubit extends Cubit<BlockedUsersState> {
final BlockedUsersRepository blockedUsersRepository;
BlockedUsersCubit({
required this.blockedUsersRepository,
}) : super(const BlockedUsersState());
getBlockedUsers() async {
try {
emit(BlockedUsersState.loaded(profilesList: await blockedUsersRepository.getBlockedUsers()));
} catch (e, st) {
emit(BlockedUsersState.error(errorMessage: '$e $st'));
}
}
blockUser(String slug) async {
await blockedUsersRepository.blockUserBySlug(slug);
await getBlockedUsers();
}
unblockUser(String slug) async {
await blockedUsersRepository.unblockUserBySlug(slug);
await getBlockedUsers();
}
}

View File

@@ -0,0 +1,15 @@
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'blocked_users_state.freezed.dart';
@freezed
abstract class BlockedUsersState with _$BlockedUsersState {
const factory BlockedUsersState() = _BlockedUsersState;
const factory BlockedUsersState.loading() = BlockedUsersStateLoading;
const factory BlockedUsersState.loaded({required List<ProfileModel> profilesList}) = BlockedUsersStateLoaded;
const factory BlockedUsersState.error({
required String errorMessage,
}) = BlockedUsersStateError;
}

View File

@@ -0,0 +1,43 @@
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_state.dart';
import 'package:eatvio_app/features/menu/presentation/widgets/blocked_user_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BlockedUsersScreen extends StatefulWidget {
const BlockedUsersScreen({super.key});
@override
State<BlockedUsersScreen> createState() => _BlockedUsersScreenState();
}
class _BlockedUsersScreenState extends State<BlockedUsersScreen> {
@override
Widget build(BuildContext context) {
return BlocProvider<BlockedUsersCubit>(
create: (BuildContext context) => sl<BlockedUsersCubit>()..getBlockedUsers(),
child: BlocBuilder<BlockedUsersCubit, BlockedUsersState>(
builder: (BuildContext context, BlockedUsersState state) {
if (state is BlockedUsersStateLoaded) {
return Scaffold(
appBar: AppBar(
title: const Text('Чёрный список'),
),
body: ListView.builder(
itemBuilder: (context, index) => BlockedUserWidget(profile: state.profilesList[index]),
itemCount: state.profilesList.length,
),
);
} else {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
),
);
}
}

View File

@@ -53,6 +53,8 @@ class MenuScreen extends StatelessWidget {
_tile(leading: ImageConstant.icnGlossary, title: 'Глоссарий', onTap: () => GoRouter.of(context).push('/glossary-screen')),
_divider(context),
_tile(leading: ImageConstant.icnSupport, title: 'Поддержка', onTap: () => GoRouter.of(context).push('/support-screen')),
_divider(context),
_tile(leading: 'assets/icons/blocked_users.svg', title: 'Чёрный список', onTap: () => GoRouter.of(context).pushNamed('blockedUsersScreen')),
// _divider(context),
// _tile(
// leading: ImageConstant.icnDevTools,

View File

@@ -0,0 +1,47 @@
import 'dart:developer';
import 'package:eatvio_app/features/menu/services/blocked_users_service.dart';
import 'package:eatvio_app/features/profile/models/profile_model.dart';
class BlockedUsersRepository {
final BlockedUserService blockedUserService;
BlockedUsersRepository({
required this.blockedUserService,
});
Future<List<ProfileModel>> getBlockedUsers() async {
try {
return (await blockedUserService.getBlockedUsers()).profilesList;
} catch (e, st) {
log(e.toString(), stackTrace: st);
rethrow;
}
}
blockUserBySlug(String slug) async {
try {
return await blockedUserService.blockUser(
data: {
'slug': slug,
},
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
rethrow;
}
}
unblockUserBySlug(String slug) async {
try {
return await blockedUserService.unblockUser(
data: {
'slug': slug,
},
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
rethrow;
}
}
}

View File

@@ -0,0 +1,83 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
class BlockedUserWidget extends StatefulWidget {
final ProfileModel profile;
const BlockedUserWidget({super.key, required this.profile});
@override
State<BlockedUserWidget> createState() => _BlockedUserWidgetState();
}
class _BlockedUserWidgetState extends State<BlockedUserWidget> {
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => GoRouter.of(context).pushNamed(
'profileScreen',
extra: Author(
authorSlug: widget.profile.slug,
authorName: widget.profile.name,
authorProfileIcon: widget.profile.profilePhotoUrl,
authorIsMe: false,
isEntitySubscribedByMe: false,
),
),
child: Ink(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Row(
children: [
CircleAvatar(
foregroundImage: NetworkImage(baseUrl + widget.profile.profilePhotoUrl),
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
radius: 28,
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget.profile.name,
style: const TextStyle(
color: Color(0xFF323F4B),
fontSize: 16,
fontWeight: FontWeight.w600,
height: 1,
),
),
],
),
const Spacer(),
InkWell(
onTap: () {
context.read<BlockedUsersCubit>().unblockUser(widget.profile.slug);
},
borderRadius: BorderRadius.circular(4),
child: Ink(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: const Color(0xFFF1F2F6),
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'Убрать',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF6D6F71),
),
),
),
),
],
),
),
);
}
}