Skip to content

Commit b39180e

Browse files
authored
Merge pull request #24 from headlines-toolkit/feature_saved_headlines
Feature saved headlines
2 parents a7070ab + b45bf9c commit b39180e

File tree

4 files changed

+101
-2
lines changed

4 files changed

+101
-2
lines changed
Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
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/headlines-feed/widgets/headline_item_widget.dart';
26
import 'package:ht_main/l10n/l10n.dart';
7+
import 'package:ht_main/router/routes.dart';
8+
import 'package:ht_main/shared/widgets/widgets.dart';
9+
import 'package:ht_shared/ht_shared.dart' show Headline;
310

411
/// {@template saved_headlines_page}
5-
/// A placeholder page for displaying user's saved headlines.
12+
/// Displays the list of headlines saved by the user.
13+
///
14+
/// Allows users to view details of a saved headline or remove it
15+
/// from their saved list.
616
/// {@endtemplate}
717
class SavedHeadlinesPage extends StatelessWidget {
818
/// {@macro saved_headlines_page}
@@ -11,9 +21,69 @@ class SavedHeadlinesPage extends StatelessWidget {
1121
@override
1222
Widget build(BuildContext context) {
1323
final l10n = context.l10n;
24+
1425
return Scaffold(
1526
appBar: AppBar(title: Text(l10n.accountSavedHeadlinesTile)),
16-
body: const Center(child: Text('SAVED HEADLINES PAGE (Placeholder)')),
27+
body: BlocBuilder<AccountBloc, AccountState>(
28+
builder: (context, state) {
29+
if (state.status == AccountStatus.loading &&
30+
state.preferences == null) {
31+
return LoadingStateWidget(
32+
icon: Icons.bookmarks_outlined,
33+
headline: 'Loading Saved Headlines...', // Placeholder
34+
subheadline: 'Please wait while we fetch your saved articles.', // Placeholder
35+
);
36+
}
37+
38+
if (state.status == AccountStatus.failure &&
39+
state.preferences == null) {
40+
return FailureStateWidget(
41+
message:
42+
state.errorMessage ?? 'Could not load saved headlines.', // Placeholder
43+
onRetry: () {
44+
if (state.user?.id != null) {
45+
context.read<AccountBloc>().add(
46+
AccountLoadContentPreferencesRequested(
47+
userId: state.user!.id,
48+
),
49+
);
50+
}
51+
},
52+
);
53+
}
54+
55+
final savedHeadlines = state.preferences?.savedHeadlines ?? [];
56+
57+
if (savedHeadlines.isEmpty) {
58+
return InitialStateWidget(
59+
icon: Icons.bookmark_add_outlined,
60+
headline: 'No Saved Headlines', // Placeholder
61+
subheadline: 'You haven\'t saved any articles yet. Start exploring!', // Placeholder
62+
);
63+
}
64+
65+
return ListView.separated(
66+
itemCount: savedHeadlines.length,
67+
separatorBuilder: (context, index) => const Divider(height: 1),
68+
itemBuilder: (context, index) {
69+
final headline = savedHeadlines[index];
70+
return HeadlineItemWidget(
71+
headline: headline,
72+
targetRouteName: Routes.accountArticleDetailsName,
73+
trailing: IconButton( // Changed from trailingWidget
74+
icon: const Icon(Icons.delete_outline),
75+
tooltip: 'Remove from saved', // Placeholder
76+
onPressed: () {
77+
context.read<AccountBloc>().add(
78+
AccountSaveHeadlineToggled(headline: headline),
79+
);
80+
},
81+
),
82+
);
83+
},
84+
);
85+
},
86+
),
1787
);
1888
}
1989
}

lib/headlines-feed/widgets/headline_item_widget.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class HeadlineItemWidget extends StatelessWidget {
1010
const HeadlineItemWidget({
1111
required this.headline,
1212
required this.targetRouteName, // Add targetRouteName
13+
this.trailing, // Add optional trailing widget
1314
super.key,
1415
});
1516

@@ -19,6 +20,9 @@ class HeadlineItemWidget extends StatelessWidget {
1920
/// The named route to navigate to when the item is tapped.
2021
final String targetRouteName; // Add targetRouteName
2122

23+
/// An optional widget to display at the end of the row.
24+
final Widget? trailing;
25+
2226
// Helper for date formatting
2327
static final _dateFormatter = DateFormat.yMd().add_jm();
2428

@@ -159,6 +163,11 @@ class HeadlineItemWidget extends StatelessWidget {
159163
],
160164
),
161165
),
166+
// Add the trailing widget if provided
167+
if (trailing != null) ...[
168+
const SizedBox(width: AppSpacing.md),
169+
trailing!,
170+
],
162171
],
163172
),
164173
),

lib/router/router.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,22 @@ GoRouter createRouter({
606606
child: Center(child: Text('SAVED HEADLINES PAGE')),
607607
);
608608
},
609+
routes: [
610+
GoRoute(
611+
path: Routes.accountArticleDetails, // 'article/:id'
612+
name: Routes.accountArticleDetailsName,
613+
builder: (context, state) {
614+
final id = state.pathParameters['id']!;
615+
return BlocProvider(
616+
create: (context) => HeadlineDetailsBloc(
617+
headlinesRepository:
618+
context.read<HtDataRepository<Headline>>(),
619+
)..add(HeadlineDetailsRequested(headlineId: id)),
620+
child: HeadlineDetailsPage(headlineId: id),
621+
);
622+
},
623+
),
624+
],
609625
),
610626
],
611627
),

lib/router/routes.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ abstract final class Routes {
7070
static const manageFollowedItemsName = 'manageFollowedItems'; // Renamed
7171
static const accountSavedHeadlines = 'saved-headlines';
7272
static const accountSavedHeadlinesName = 'accountSavedHeadlines';
73+
// New route for article details from saved headlines
74+
static const String accountArticleDetails =
75+
'article/:id'; // Relative to accountSavedHeadlines
76+
static const String accountArticleDetailsName = 'accountArticleDetails';
7377

7478
// --- Manage Followed Items Sub-Routes (relative to /account/manage-followed-items) ---
7579
static const followedCategoriesList = 'categories';

0 commit comments

Comments
 (0)