From a13e9d2c92457ba453681b6d8939a3418a913f63 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 4 Jul 2025 18:22:02 +0100 Subject: [PATCH 1/3] feat(dashboard): make summary cards responsive Replaces the `Wrap` widget for the summary cards with a `LayoutBuilder`. This allows the layout to switch from a `Row` on wider screens to a `Column` on narrower screens, ensuring the cards utilize the available space effectively and stack vertically when needed. --- lib/dashboard/view/dashboard_page.dart | 66 ++++++++++++++++++-------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/lib/dashboard/view/dashboard_page.dart b/lib/dashboard/view/dashboard_page.dart index 007d2eb..bf8c9a7 100644 --- a/lib/dashboard/view/dashboard_page.dart +++ b/lib/dashboard/view/dashboard_page.dart @@ -58,26 +58,52 @@ class _DashboardPageState extends State { return ListView( padding: const EdgeInsets.all(AppSpacing.lg), children: [ - Wrap( - spacing: AppSpacing.lg, - runSpacing: AppSpacing.lg, - children: [ - _SummaryCard( - icon: Icons.article_outlined, - title: l10n.totalHeadlines, - value: summary.headlineCount.toString(), - ), - _SummaryCard( - icon: Icons.category_outlined, - title: l10n.totalCategories, - value: summary.categoryCount.toString(), - ), - _SummaryCard( - icon: Icons.source_outlined, - title: l10n.totalSources, - value: summary.sourceCount.toString(), - ), - ], + LayoutBuilder( + builder: (context, constraints) { + const tabletBreakpoint = 800; + final isNarrow = constraints.maxWidth < tabletBreakpoint; + + final summaryCards = [ + _SummaryCard( + icon: Icons.article_outlined, + title: l10n.totalHeadlines, + value: summary.headlineCount.toString(), + ), + _SummaryCard( + icon: Icons.category_outlined, + title: l10n.totalCategories, + value: summary.categoryCount.toString(), + ), + _SummaryCard( + icon: Icons.source_outlined, + title: l10n.totalSources, + value: summary.sourceCount.toString(), + ), + ]; + + if (isNarrow) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + summaryCards[0], + const SizedBox(height: AppSpacing.lg), + summaryCards[1], + const SizedBox(height: AppSpacing.lg), + summaryCards[2], + ], + ); + } + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: summaryCards[0]), + const SizedBox(width: AppSpacing.lg), + Expanded(child: summaryCards[1]), + const SizedBox(width: AppSpacing.lg), + Expanded(child: summaryCards[2]), + ], + ); + }, ), const SizedBox(height: AppSpacing.lg), Row( From cb4874c3afc994c051e8e5c2756d5a3ca6c3240b Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 4 Jul 2025 18:24:49 +0100 Subject: [PATCH 2/3] feat(dashboard): make main content area responsive Replaces the main content `Row` with a `LayoutBuilder`. This allows the layout to switch from a `Row` on wider screens to a `Column` on narrower screens, ensuring the recent headlines, system status, and quick actions cards stack vertically on smaller displays. --- lib/dashboard/view/dashboard_page.dart | 45 +++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/dashboard/view/dashboard_page.dart b/lib/dashboard/view/dashboard_page.dart index bf8c9a7..dcd5d42 100644 --- a/lib/dashboard/view/dashboard_page.dart +++ b/lib/dashboard/view/dashboard_page.dart @@ -106,19 +106,14 @@ class _DashboardPageState extends State { }, ), const SizedBox(height: AppSpacing.lg), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: _RecentHeadlinesCard( - headlines: recentHeadlines, - ), - ), - const SizedBox(width: AppSpacing.lg), - Expanded( - flex: 1, - child: Column( + LayoutBuilder( + builder: (context, constraints) { + const wideBreakpoint = 1200; + final isWide = constraints.maxWidth > wideBreakpoint; + + final mainContent = [ + _RecentHeadlinesCard(headlines: recentHeadlines), + Column( children: [ _SystemStatusCard( status: appConfig.appOperationalStatus, @@ -127,8 +122,28 @@ class _DashboardPageState extends State { const _QuickActionsCard(), ], ), - ), - ], + ]; + + if (isWide) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(flex: 2, child: mainContent[0]), + const SizedBox(width: AppSpacing.lg), + Expanded(flex: 1, child: mainContent[1]), + ], + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + mainContent[0], + const SizedBox(height: AppSpacing.lg), + mainContent[1], + ], + ); + }, ), ], ); From 908bf059fe1b80ac4bab0720312e5b946ced5e2d Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 4 Jul 2025 18:33:09 +0100 Subject: [PATCH 3/3] feat(dashboard): update quick actions card Refactors the `_QuickActionsCard` to include only "Create Headline", "Create Category", and "Create Source" actions. All actions are now represented by `ElevatedButton` widgets for a consistent appearance and navigate to their respective creation pages. --- lib/dashboard/view/dashboard_page.dart | 39 +++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/dashboard/view/dashboard_page.dart b/lib/dashboard/view/dashboard_page.dart index dcd5d42..a78010e 100644 --- a/lib/dashboard/view/dashboard_page.dart +++ b/lib/dashboard/view/dashboard_page.dart @@ -234,34 +234,33 @@ class _QuickActionsCard extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(AppSpacing.lg), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text(l10n.quickActions, style: theme.textTheme.titleLarge), const SizedBox(height: AppSpacing.md), - SizedBox( - width: double.infinity, - child: ElevatedButton.icon( - icon: const Icon(Icons.add_circle_outline), - label: Text(l10n.createHeadlineAction), - onPressed: () => context.goNamed(Routes.createHeadlineName), - ), + ElevatedButton.icon( + icon: const Icon(Icons.add_circle_outline), + label: Text(l10n.createHeadlineAction), + onPressed: () => context.goNamed(Routes.createHeadlineName), ), const SizedBox(height: AppSpacing.sm), - SizedBox( - width: double.infinity, - child: OutlinedButton.icon( - icon: const Icon(Icons.folder_open_outlined), - label: Text(l10n.manageContentAction), - onPressed: () => context.goNamed(Routes.contentManagementName), + ElevatedButton.icon( + icon: const Icon(Icons.create_new_folder_outlined), + label: Text(l10n.createCategory), + onPressed: () => context.goNamed(Routes.createCategoryName), + style: ElevatedButton.styleFrom( + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, ), ), const SizedBox(height: AppSpacing.sm), - SizedBox( - width: double.infinity, - child: OutlinedButton.icon( - icon: const Icon(Icons.settings_applications_outlined), - label: Text(l10n.appConfigAction), - onPressed: () => context.goNamed(Routes.appConfigurationName), + ElevatedButton.icon( + icon: const Icon(Icons.add_to_photos_outlined), + label: Text(l10n.createSource), + onPressed: () => context.goNamed(Routes.createSourceName), + style: ElevatedButton.styleFrom( + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, ), ), ],