Skip to content

Commit 5f3b14e

Browse files
committed
feat(dashboard): enhances the dashboard UI to display a list of the most recently created headlines.
- Localization: Added new strings for the "Recent Headlines" section title, a "View All" button, and a message for when no headlines are available. - UI Update: The DashboardPage now includes a new _RecentHeadlinesCard widget. - Recent Headlines Card: This card displays a title, a "View All" button that navigates to the content management page, and a list of recent headlines. Each headline in the list shows its title and relative creation time (e.g., "5m ago") and is tappable, navigating the user directly to that headline's edit page.
1 parent bbaab62 commit 5f3b14e

File tree

6 files changed

+135
-2
lines changed

6 files changed

+135
-2
lines changed

lib/dashboard/view/dashboard_page.dart

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
3-
import 'package:ht_dashboard/dashboard/bloc/dashboard_bloc.dart';
3+
import 'package:go_router/go_router.dart';
4+
import 'package:ht_dashboard/dashboard/bloc/dashboard.dart'; // Barrel file
45
import 'package:ht_dashboard/l10n/l10n.dart';
6+
import 'package:ht_dashboard/router/routes.dart';
57
import 'package:ht_dashboard/shared/shared.dart';
8+
import 'package:ht_shared/ht_shared.dart';
69

710
/// {@template dashboard_page}
811
/// The main dashboard page, displaying key statistics and quick actions.
@@ -47,6 +50,7 @@ class _DashboardPageState extends State<DashboardPage> {
4750
}
4851
if (state.status == DashboardStatus.success && state.summary != null) {
4952
final summary = state.summary!;
53+
final recentHeadlines = state.recentHeadlines;
5054
return ListView(
5155
padding: const EdgeInsets.all(AppSpacing.lg),
5256
children: [
@@ -77,7 +81,10 @@ class _DashboardPageState extends State<DashboardPage> {
7781
),
7882
],
7983
),
80-
// Other dashboard components will go here in future phases
84+
const SizedBox(height: AppSpacing.lg),
85+
_RecentHeadlinesCard(
86+
headlines: recentHeadlines,
87+
),
8188
],
8289
);
8390
}
@@ -88,6 +95,72 @@ class _DashboardPageState extends State<DashboardPage> {
8895
}
8996
}
9097

98+
/// A card to display a list of recently created headlines.
99+
class _RecentHeadlinesCard extends StatelessWidget {
100+
const _RecentHeadlinesCard({required this.headlines});
101+
102+
final List<Headline> headlines;
103+
104+
@override
105+
Widget build(BuildContext context) {
106+
final l10n = context.l10n;
107+
final theme = Theme.of(context);
108+
109+
return Card(
110+
child: Padding(
111+
padding: const EdgeInsets.all(AppSpacing.lg),
112+
child: Column(
113+
crossAxisAlignment: CrossAxisAlignment.start,
114+
children: [
115+
Row(
116+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
117+
children: [
118+
Text(l10n.recentHeadlines, style: theme.textTheme.titleLarge),
119+
TextButton(
120+
onPressed: () =>
121+
context.goNamed(Routes.contentManagementName),
122+
child: Text(l10n.viewAll),
123+
),
124+
],
125+
),
126+
const SizedBox(height: AppSpacing.md),
127+
if (headlines.isEmpty)
128+
Padding(
129+
padding: const EdgeInsets.symmetric(vertical: AppSpacing.lg),
130+
child: Center(
131+
child: Text(
132+
l10n.noRecentHeadlines,
133+
style: theme.textTheme.bodyMedium
134+
?.copyWith(color: theme.colorScheme.onSurfaceVariant),
135+
),
136+
),
137+
)
138+
else
139+
...headlines.map(
140+
(headline) => ListTile(
141+
leading: const Icon(Icons.article_outlined),
142+
title: Text(headline.title, maxLines: 1),
143+
subtitle: Text(
144+
DateFormatter.formatRelativeTime(
145+
context,
146+
headline.createdAt,
147+
),
148+
),
149+
onTap: () => context.goNamed(
150+
Routes.editHeadlineName,
151+
pathParameters: {'id': headline.id},
152+
),
153+
contentPadding: EdgeInsets.zero,
154+
dense: true,
155+
),
156+
),
157+
],
158+
),
159+
),
160+
);
161+
}
162+
}
163+
91164
/// A private widget to display a single summary statistic on the dashboard.
92165
class _SummaryCard extends StatelessWidget {
93166
const _SummaryCard({

lib/l10n/app_localizations.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,24 @@ abstract class AppLocalizations {
13511351
/// In en, this message translates to:
13521352
/// **'Failed to load dashboard data.'**
13531353
String get dashboardLoadFailure;
1354+
1355+
/// Title for the recent headlines card on the dashboard
1356+
///
1357+
/// In en, this message translates to:
1358+
/// **'Recent Headlines'**
1359+
String get recentHeadlines;
1360+
1361+
/// Button text to view all items in a list
1362+
///
1363+
/// In en, this message translates to:
1364+
/// **'View All'**
1365+
String get viewAll;
1366+
1367+
/// Message shown when there are no recent headlines
1368+
///
1369+
/// In en, this message translates to:
1370+
/// **'No recent headlines to display.'**
1371+
String get noRecentHeadlines;
13541372
}
13551373

13561374
class _AppLocalizationsDelegate

lib/l10n/app_localizations_ar.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,4 +704,13 @@ class AppLocalizationsAr extends AppLocalizations {
704704

705705
@override
706706
String get dashboardLoadFailure => 'فشل تحميل بيانات لوحة القيادة.';
707+
708+
@override
709+
String get recentHeadlines => 'أحدث العناوين';
710+
711+
@override
712+
String get viewAll => 'عرض الكل';
713+
714+
@override
715+
String get noRecentHeadlines => 'لا توجد عناوين حديثة لعرضها.';
707716
}

lib/l10n/app_localizations_en.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,4 +702,13 @@ class AppLocalizationsEn extends AppLocalizations {
702702

703703
@override
704704
String get dashboardLoadFailure => 'Failed to load dashboard data.';
705+
706+
@override
707+
String get recentHeadlines => 'Recent Headlines';
708+
709+
@override
710+
String get viewAll => 'View All';
711+
712+
@override
713+
String get noRecentHeadlines => 'No recent headlines to display.';
705714
}

lib/l10n/arb/app_ar.arb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,5 +849,17 @@
849849
"dashboardLoadFailure": "فشل تحميل بيانات لوحة القيادة.",
850850
"@dashboardLoadFailure": {
851851
"description": "رسالة خطأ عند فشل تحميل بيانات لوحة القيادة"
852+
},
853+
"recentHeadlines": "أحدث العناوين",
854+
"@recentHeadlines": {
855+
"description": "عنوان بطاقة أحدث العناوين في لوحة القيادة"
856+
},
857+
"viewAll": "عرض الكل",
858+
"@viewAll": {
859+
"description": "نص زر عرض كل العناصر في قائمة"
860+
},
861+
"noRecentHeadlines": "لا توجد عناوين حديثة لعرضها.",
862+
"@noRecentHeadlines": {
863+
"description": "رسالة تظهر عند عدم وجود عناوين حديثة"
852864
}
853865
}

lib/l10n/arb/app_en.arb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,5 +849,17 @@
849849
"dashboardLoadFailure": "Failed to load dashboard data.",
850850
"@dashboardLoadFailure": {
851851
"description": "Error message when dashboard data fails to load"
852+
},
853+
"recentHeadlines": "Recent Headlines",
854+
"@recentHeadlines": {
855+
"description": "Title for the recent headlines card on the dashboard"
856+
},
857+
"viewAll": "View All",
858+
"@viewAll": {
859+
"description": "Button text to view all items in a list"
860+
},
861+
"noRecentHeadlines": "No recent headlines to display.",
862+
"@noRecentHeadlines": {
863+
"description": "Message shown when there are no recent headlines"
852864
}
853865
}

0 commit comments

Comments
 (0)