Skip to content

Commit a099827

Browse files
committed
feat(dashboard): completes the dashboard UI by adding two new components:
- Localization: New strings have been added for the "System Status" and "Quick Actions" cards, including labels for different app statuses and action buttons. - System Status Card: A new _SystemStatusCard widget displays the application's current operational status (Active, Maintenance, Disabled), fetched from the AppConfig. It uses distinct icons and colors for immediate visual feedback. - Quick Actions Card: A new _QuickActionsCard provides direct navigation to key administrative areas: "Create Headline," "Manage Content," and "App Configuration," improving workflow efficiency. - Layout Update: The DashboardPage layout has been updated to a two-column format to accommodate the new cards alongside the "Recent Headlines" list. This concludes all planned phases for the dashboard feature. The dashboard now serves as a comprehensive and functional hub for administrators.
1 parent 562a6c1 commit a099827

File tree

6 files changed

+303
-4
lines changed

6 files changed

+303
-4
lines changed

lib/dashboard/view/dashboard_page.dart

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:go_router/go_router.dart';
4-
import 'package:ht_dashboard/dashboard/bloc/dashboard.dart'; // Barrel file
4+
import 'package:ht_dashboard/dashboard/bloc/dashboard_bloc.dart';
5+
import 'package:ht_dashboard/l10n/app_localizations.dart';
56
import 'package:ht_dashboard/l10n/l10n.dart';
67
import 'package:ht_dashboard/router/routes.dart';
78
import 'package:ht_dashboard/shared/shared.dart';
@@ -48,8 +49,11 @@ class _DashboardPageState extends State<DashboardPage> {
4849
},
4950
);
5051
}
51-
if (state.status == DashboardStatus.success && state.summary != null) {
52+
if (state.status == DashboardStatus.success &&
53+
state.summary != null &&
54+
state.appConfig != null) {
5255
final summary = state.summary!;
56+
final appConfig = state.appConfig!;
5357
final recentHeadlines = state.recentHeadlines;
5458
return ListView(
5559
padding: const EdgeInsets.all(AppSpacing.lg),
@@ -82,8 +86,27 @@ class _DashboardPageState extends State<DashboardPage> {
8286
],
8387
),
8488
const SizedBox(height: AppSpacing.lg),
85-
_RecentHeadlinesCard(
86-
headlines: recentHeadlines,
89+
Row(
90+
crossAxisAlignment: CrossAxisAlignment.start,
91+
children: [
92+
Expanded(
93+
flex: 2,
94+
child: _RecentHeadlinesCard(
95+
headlines: recentHeadlines,
96+
),
97+
),
98+
const SizedBox(width: AppSpacing.lg),
99+
Expanded(
100+
flex: 1,
101+
child: Column(
102+
children: [
103+
_SystemStatusCard(status: appConfig.appOperationalStatus),
104+
const SizedBox(height: AppSpacing.lg),
105+
const _QuickActionsCard(),
106+
],
107+
),
108+
),
109+
],
87110
),
88111
],
89112
);
@@ -95,6 +118,122 @@ class _DashboardPageState extends State<DashboardPage> {
95118
}
96119
}
97120

121+
/// A card to display the current operational status of the application.
122+
class _SystemStatusCard extends StatelessWidget {
123+
const _SystemStatusCard({required this.status});
124+
125+
final RemoteAppStatus status;
126+
127+
@override
128+
Widget build(BuildContext context) {
129+
final l10n = context.l10n;
130+
final theme = Theme.of(context);
131+
132+
final (icon, color, text) = _getStatusDetails(status, l10n, theme);
133+
134+
return Card(
135+
child: Padding(
136+
padding: const EdgeInsets.all(AppSpacing.lg),
137+
child: Column(
138+
crossAxisAlignment: CrossAxisAlignment.start,
139+
children: [
140+
Text(l10n.systemStatus, style: theme.textTheme.titleLarge),
141+
const SizedBox(height: AppSpacing.md),
142+
Row(
143+
children: [
144+
Icon(icon, color: color, size: 24),
145+
const SizedBox(width: AppSpacing.sm),
146+
Text(
147+
text,
148+
style: theme.textTheme.titleMedium?.copyWith(color: color),
149+
),
150+
],
151+
),
152+
],
153+
),
154+
),
155+
);
156+
}
157+
158+
/// Returns the appropriate icon, color, and text for a given status.
159+
(IconData, Color, String) _getStatusDetails(
160+
RemoteAppStatus status,
161+
AppLocalizations l10n,
162+
ThemeData theme,
163+
) {
164+
switch (status) {
165+
case RemoteAppStatus.active:
166+
return (
167+
Icons.check_circle_outline,
168+
theme.colorScheme.primary,
169+
l10n.appStatusActive,
170+
);
171+
case RemoteAppStatus.maintenance:
172+
return (
173+
Icons.warning_amber_outlined,
174+
theme.colorScheme.tertiary,
175+
l10n.appStatusMaintenance,
176+
);
177+
case RemoteAppStatus.disabled:
178+
return (
179+
Icons.cancel_outlined,
180+
theme.colorScheme.error,
181+
l10n.appStatusDisabled,
182+
);
183+
}
184+
}
185+
}
186+
187+
/// A card providing quick navigation to common administrative tasks.
188+
class _QuickActionsCard extends StatelessWidget {
189+
const _QuickActionsCard();
190+
191+
@override
192+
Widget build(BuildContext context) {
193+
final l10n = context.l10n;
194+
final theme = Theme.of(context);
195+
196+
return Card(
197+
child: Padding(
198+
padding: const EdgeInsets.all(AppSpacing.lg),
199+
child: Column(
200+
crossAxisAlignment: CrossAxisAlignment.start,
201+
children: [
202+
Text(l10n.quickActions, style: theme.textTheme.titleLarge),
203+
const SizedBox(height: AppSpacing.md),
204+
SizedBox(
205+
width: double.infinity,
206+
child: ElevatedButton.icon(
207+
icon: const Icon(Icons.add_circle_outline),
208+
label: Text(l10n.createHeadlineAction),
209+
onPressed: () => context.goNamed(Routes.createHeadlineName),
210+
),
211+
),
212+
const SizedBox(height: AppSpacing.sm),
213+
SizedBox(
214+
width: double.infinity,
215+
child: OutlinedButton.icon(
216+
icon: const Icon(Icons.folder_open_outlined),
217+
label: Text(l10n.manageContentAction),
218+
onPressed: () => context.goNamed(Routes.contentManagementName),
219+
),
220+
),
221+
const SizedBox(height: AppSpacing.sm),
222+
SizedBox(
223+
width: double.infinity,
224+
child: OutlinedButton.icon(
225+
icon: const Icon(Icons.settings_applications_outlined),
226+
label: Text(l10n.appConfigAction),
227+
onPressed: () => context.goNamed(Routes.appConfigurationName),
228+
),
229+
),
230+
],
231+
),
232+
),
233+
);
234+
}
235+
}
236+
98237
/// A card to display a list of recently created headlines.
99238
class _RecentHeadlinesCard extends StatelessWidget {
100239
const _RecentHeadlinesCard({required this.headlines});

lib/l10n/app_localizations.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,54 @@ abstract class AppLocalizations {
13691369
/// In en, this message translates to:
13701370
/// **'No recent headlines to display.'**
13711371
String get noRecentHeadlines;
1372+
1373+
/// Title for the system status card on the dashboard
1374+
///
1375+
/// In en, this message translates to:
1376+
/// **'System Status'**
1377+
String get systemStatus;
1378+
1379+
/// Title for the quick actions card on the dashboard
1380+
///
1381+
/// In en, this message translates to:
1382+
/// **'Quick Actions'**
1383+
String get quickActions;
1384+
1385+
/// Button text for the create headline quick action
1386+
///
1387+
/// In en, this message translates to:
1388+
/// **'Create Headline'**
1389+
String get createHeadlineAction;
1390+
1391+
/// Button text for the manage content quick action
1392+
///
1393+
/// In en, this message translates to:
1394+
/// **'Manage Content'**
1395+
String get manageContentAction;
1396+
1397+
/// Button text for the app configuration quick action
1398+
///
1399+
/// In en, this message translates to:
1400+
/// **'App Configuration'**
1401+
String get appConfigAction;
1402+
1403+
/// Text for the 'Active' app status
1404+
///
1405+
/// In en, this message translates to:
1406+
/// **'Active'**
1407+
String get appStatusActive;
1408+
1409+
/// Text for the 'Maintenance' app status
1410+
///
1411+
/// In en, this message translates to:
1412+
/// **'Maintenance'**
1413+
String get appStatusMaintenance;
1414+
1415+
/// Text for the 'Disabled' app status
1416+
///
1417+
/// In en, this message translates to:
1418+
/// **'Disabled'**
1419+
String get appStatusDisabled;
13721420
}
13731421

13741422
class _AppLocalizationsDelegate

lib/l10n/app_localizations_ar.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,4 +713,28 @@ class AppLocalizationsAr extends AppLocalizations {
713713

714714
@override
715715
String get noRecentHeadlines => 'لا توجد عناوين حديثة لعرضها.';
716+
717+
@override
718+
String get systemStatus => 'حالة النظام';
719+
720+
@override
721+
String get quickActions => 'إجراءات سريعة';
722+
723+
@override
724+
String get createHeadlineAction => 'إنشاء عنوان';
725+
726+
@override
727+
String get manageContentAction => 'إدارة المحتوى';
728+
729+
@override
730+
String get appConfigAction => 'إعدادات التطبيق';
731+
732+
@override
733+
String get appStatusActive => 'نشط';
734+
735+
@override
736+
String get appStatusMaintenance => 'صيانة';
737+
738+
@override
739+
String get appStatusDisabled => 'معطل';
716740
}

lib/l10n/app_localizations_en.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,4 +711,28 @@ class AppLocalizationsEn extends AppLocalizations {
711711

712712
@override
713713
String get noRecentHeadlines => 'No recent headlines to display.';
714+
715+
@override
716+
String get systemStatus => 'System Status';
717+
718+
@override
719+
String get quickActions => 'Quick Actions';
720+
721+
@override
722+
String get createHeadlineAction => 'Create Headline';
723+
724+
@override
725+
String get manageContentAction => 'Manage Content';
726+
727+
@override
728+
String get appConfigAction => 'App Configuration';
729+
730+
@override
731+
String get appStatusActive => 'Active';
732+
733+
@override
734+
String get appStatusMaintenance => 'Maintenance';
735+
736+
@override
737+
String get appStatusDisabled => 'Disabled';
714738
}

lib/l10n/arb/app_ar.arb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,5 +861,37 @@
861861
"noRecentHeadlines": "لا توجد عناوين حديثة لعرضها.",
862862
"@noRecentHeadlines": {
863863
"description": "رسالة تظهر عند عدم وجود عناوين حديثة"
864+
},
865+
"systemStatus": "حالة النظام",
866+
"@systemStatus": {
867+
"description": "عنوان بطاقة حالة النظام في لوحة القيادة"
868+
},
869+
"quickActions": "إجراءات سريعة",
870+
"@quickActions": {
871+
"description": "عنوان بطاقة الإجراءات السريعة في لوحة القيادة"
872+
},
873+
"createHeadlineAction": "إنشاء عنوان",
874+
"@createHeadlineAction": {
875+
"description": "نص زر الإجراء السريع لإنشاء عنوان"
876+
},
877+
"manageContentAction": "إدارة المحتوى",
878+
"@manageContentAction": {
879+
"description": "نص زر الإجراء السريع لإدارة المحتوى"
880+
},
881+
"appConfigAction": "إعدادات التطبيق",
882+
"@appConfigAction": {
883+
"description": "نص زر الإجراء السريع لإعدادات التطبيق"
884+
},
885+
"appStatusActive": "نشط",
886+
"@appStatusActive": {
887+
"description": "نص حالة التطبيق 'نشط'"
888+
},
889+
"appStatusMaintenance": "صيانة",
890+
"@appStatusMaintenance": {
891+
"description": "نص حالة التطبيق 'صيانة'"
892+
},
893+
"appStatusDisabled": "معطل",
894+
"@appStatusDisabled": {
895+
"description": "نص حالة التطبيق 'معطل'"
864896
}
865897
}

lib/l10n/arb/app_en.arb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,5 +861,37 @@
861861
"noRecentHeadlines": "No recent headlines to display.",
862862
"@noRecentHeadlines": {
863863
"description": "Message shown when there are no recent headlines"
864+
},
865+
"systemStatus": "System Status",
866+
"@systemStatus": {
867+
"description": "Title for the system status card on the dashboard"
868+
},
869+
"quickActions": "Quick Actions",
870+
"@quickActions": {
871+
"description": "Title for the quick actions card on the dashboard"
872+
},
873+
"createHeadlineAction": "Create Headline",
874+
"@createHeadlineAction": {
875+
"description": "Button text for the create headline quick action"
876+
},
877+
"manageContentAction": "Manage Content",
878+
"@manageContentAction": {
879+
"description": "Button text for the manage content quick action"
880+
},
881+
"appConfigAction": "App Configuration",
882+
"@appConfigAction": {
883+
"description": "Button text for the app configuration quick action"
884+
},
885+
"appStatusActive": "Active",
886+
"@appStatusActive": {
887+
"description": "Text for the 'Active' app status"
888+
},
889+
"appStatusMaintenance": "Maintenance",
890+
"@appStatusMaintenance": {
891+
"description": "Text for the 'Maintenance' app status"
892+
},
893+
"appStatusDisabled": "Disabled",
894+
"@appStatusDisabled": {
895+
"description": "Text for the 'Disabled' app status"
864896
}
865897
}

0 commit comments

Comments
 (0)