Skip to content

Commit f4cb2fd

Browse files
committed
feat(account): add followed countries list page
- Implement FollowedCountriesListPage widget to display and manage followed countries - Add functionality to load, display, and interact with followed countries - Include error handling and loading states - Enable navigation to add new countries and view country details
1 parent 4e359b3 commit f4cb2fd

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import 'package:core/core.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_bloc/flutter_bloc.dart';
4+
import 'package:flutter_news_app_mobile_client_full_source_code/account/bloc/account_bloc.dart';
5+
import 'package:flutter_news_app_mobile_client_full_source_code/entity_details/view/entity_details_page.dart';
6+
import 'package:flutter_news_app_mobile_client_full_source_code/l10n/l10n.dart';
7+
import 'package:flutter_news_app_mobile_client_full_source_code/router/routes.dart';
8+
import 'package:go_router/go_router.dart';
9+
import 'package:ui_kit/ui_kit.dart';
10+
11+
/// {@template followed_countries_list_page}
12+
/// Page to display and manage countries followed by the user.
13+
/// {@endtemplate}
14+
class FollowedCountriesListPage extends StatelessWidget {
15+
/// {@macro followed_countries_list_page}
16+
const FollowedCountriesListPage({super.key});
17+
18+
@override
19+
Widget build(BuildContext context) {
20+
final l10n = AppLocalizationsX(context).l10n;
21+
final followedCountries =
22+
context.watch<AccountBloc>().state.preferences?.followedCountries ?? [];
23+
24+
return Scaffold(
25+
appBar: AppBar(
26+
title: Text(l10n.followedCountriesPageTitle),
27+
actions: [
28+
IconButton(
29+
icon: const Icon(Icons.add_circle_outline),
30+
tooltip: l10n.addCountriesTooltip,
31+
onPressed: () {
32+
context.goNamed(Routes.addCountryToFollowName);
33+
},
34+
),
35+
],
36+
),
37+
body: BlocBuilder<AccountBloc, AccountState>(
38+
builder: (context, state) {
39+
if (state.status == AccountStatus.loading &&
40+
state.preferences == null) {
41+
return LoadingStateWidget(
42+
icon: Icons.flag_outlined,
43+
headline: l10n.followedCountriesLoadingHeadline,
44+
subheadline: l10n.pleaseWait,
45+
);
46+
}
47+
48+
if (state.status == AccountStatus.failure &&
49+
state.preferences == null) {
50+
return FailureStateWidget(
51+
exception:
52+
state.error ??
53+
OperationFailedException(l10n.followedCountriesErrorHeadline),
54+
onRetry: () {
55+
if (state.user?.id != null) {
56+
context.read<AccountBloc>().add(
57+
AccountLoadUserPreferences(userId: state.user!.id),
58+
);
59+
}
60+
},
61+
);
62+
}
63+
64+
if (followedCountries.isEmpty) {
65+
return InitialStateWidget(
66+
icon: Icons.public_off_outlined,
67+
headline: l10n.followedCountriesEmptyHeadline,
68+
subheadline: l10n.followedCountriesEmptySubheadline,
69+
);
70+
}
71+
72+
return ListView.builder(
73+
itemCount: followedCountries.length,
74+
itemBuilder: (context, index) {
75+
final country = followedCountries[index];
76+
return ListTile(
77+
leading: SizedBox(
78+
width: 40,
79+
height: 40,
80+
child: Image.network(
81+
country.flagUrl,
82+
errorBuilder: (context, error, stackTrace) =>
83+
const Icon(Icons.flag_outlined),
84+
),
85+
),
86+
title: Text(country.name),
87+
trailing: IconButton(
88+
icon: const Icon(
89+
Icons.remove_circle_outline,
90+
color: Colors.red,
91+
),
92+
tooltip: l10n.unfollowCountryTooltip(country.name),
93+
onPressed: () {
94+
context.read<AccountBloc>().add(
95+
AccountFollowCountryToggled(country: country),
96+
);
97+
},
98+
),
99+
onTap: () {
100+
context.push(
101+
Routes.countryDetails,
102+
extra: EntityDetailsPageArguments(entity: country),
103+
);
104+
},
105+
);
106+
},
107+
);
108+
},
109+
),
110+
);
111+
}
112+
}

0 commit comments

Comments
 (0)