Skip to content

Commit 1cc41ae

Browse files
committed
feat: followed categories list page
- Displays followed categories - Allows unfollowing categories - Navigates to add categories
1 parent db82d71 commit 1cc41ae

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_bloc/flutter_bloc.dart';
3+
import 'package:go_router/go_router.dart';
4+
import 'package:ht_main/account/bloc/account_bloc.dart';
5+
import 'package:ht_main/l10n/l10n.dart';
6+
import 'package:ht_main/router/routes.dart'; // Assuming new routes will be added
7+
import 'package:ht_main/shared/constants/app_spacing.dart';
8+
import 'package:ht_main/shared/widgets/widgets.dart'; // For FailureStateWidget
9+
import 'package:ht_shared/ht_shared.dart';
10+
11+
/// {@template followed_categories_list_page}
12+
/// Displays a list of categories the user is currently following.
13+
/// Allows unfollowing and navigating to add more categories.
14+
/// {@endtemplate}
15+
class FollowedCategoriesListPage extends StatelessWidget {
16+
/// {@macro followed_categories_list_page}
17+
const FollowedCategoriesListPage({super.key});
18+
19+
@override
20+
Widget build(BuildContext context) {
21+
final l10n = context.l10n;
22+
23+
return Scaffold(
24+
appBar: AppBar(
25+
title: Text(l10n.followedCategoriesPageTitle), // New l10n key needed
26+
actions: [
27+
IconButton(
28+
icon: const Icon(Icons.add_circle_outline),
29+
tooltip: l10n.addCategoriesTooltip, // New l10n key needed
30+
onPressed: () {
31+
context.goNamed(Routes.addCategoryToFollowName);
32+
},
33+
),
34+
],
35+
),
36+
body: BlocBuilder<AccountBloc, AccountState>(
37+
builder: (context, state) {
38+
if (state.status == AccountStatus.initial ||
39+
(state.status == AccountStatus.loading &&
40+
state.preferences == null)) {
41+
return const Center(child: CircularProgressIndicator());
42+
}
43+
44+
if (state.status == AccountStatus.failure &&
45+
state.preferences == null) {
46+
return FailureStateWidget(
47+
message: state.errorMessage ?? l10n.unknownError,
48+
onRetry: () {
49+
if (state.user?.id != null) {
50+
context.read<AccountBloc>().add(
51+
AccountLoadContentPreferencesRequested(
52+
userId: state.user!.id,
53+
),
54+
);
55+
}
56+
},
57+
);
58+
}
59+
60+
final followedCategories = state.preferences?.followedCategories;
61+
62+
if (followedCategories == null || followedCategories.isEmpty) {
63+
return Center(
64+
child: Padding(
65+
padding: const EdgeInsets.all(AppSpacing.lg),
66+
child: Column(
67+
mainAxisAlignment: MainAxisAlignment.center,
68+
children: [
69+
const Icon(Icons.category_outlined, size: 48),
70+
const SizedBox(height: AppSpacing.md),
71+
Text(
72+
l10n.noFollowedCategoriesMessage, // New l10n key
73+
style: Theme.of(context).textTheme.titleMedium,
74+
textAlign: TextAlign.center,
75+
),
76+
const SizedBox(height: AppSpacing.lg),
77+
ElevatedButton.icon(
78+
icon: const Icon(Icons.add_circle_outline),
79+
label: Text(l10n.addCategoriesButtonLabel), // New l10n
80+
onPressed: () {
81+
context.goNamed(Routes.addCategoryToFollowName);
82+
},
83+
),
84+
],
85+
),
86+
),
87+
);
88+
}
89+
90+
return ListView.builder(
91+
padding: const EdgeInsets.all(AppSpacing.md),
92+
itemCount: followedCategories.length,
93+
itemBuilder: (context, index) {
94+
final category = followedCategories[index];
95+
return Card(
96+
margin: const EdgeInsets.only(bottom: AppSpacing.sm),
97+
child: ListTile(
98+
leading: category.iconUrl != null &&
99+
Uri.tryParse(category.iconUrl!)?.isAbsolute == true
100+
? SizedBox(
101+
width: 36,
102+
height: 36,
103+
child: Image.network(
104+
category.iconUrl!,
105+
fit: BoxFit.contain,
106+
errorBuilder: (context, error, stackTrace) =>
107+
const Icon(Icons.category_outlined),
108+
),
109+
)
110+
: const Icon(Icons.category_outlined),
111+
title: Text(category.name),
112+
trailing: IconButton(
113+
icon: Icon(
114+
Icons.remove_circle_outline,
115+
color: Theme.of(context).colorScheme.error,
116+
),
117+
tooltip: l10n.unfollowCategoryTooltip(category.name), // New
118+
onPressed: () {
119+
context.read<AccountBloc>().add(
120+
AccountFollowCategoryToggled(category: category),
121+
);
122+
},
123+
),
124+
),
125+
);
126+
},
127+
);
128+
},
129+
),
130+
);
131+
}
132+
}

0 commit comments

Comments
 (0)