|
| 1 | +/// Common widget builders for reducing duplication across screens. |
| 2 | +/// |
| 3 | +/// This file contains reusable widget builders that are used across multiple |
| 4 | +/// screens to maintain consistency and reduce code duplication. |
| 5 | +library; |
| 6 | + |
| 7 | +import 'package:flutter/material.dart'; |
| 8 | +import 'package:go_router/go_router.dart'; |
| 9 | +import 'navigation_helpers.dart'; |
| 10 | + |
| 11 | +/// Builds a loading scaffold with standard appearance. |
| 12 | +/// |
| 13 | +/// Used when data is being fetched to show a consistent loading state |
| 14 | +/// across all screens. |
| 15 | +/// |
| 16 | +/// Example: |
| 17 | +/// ```dart |
| 18 | +/// if (provider.isLoading) { |
| 19 | +/// return buildLoadingScaffold(); |
| 20 | +/// } |
| 21 | +/// ``` |
| 22 | +Widget buildLoadingScaffold() { |
| 23 | + return Scaffold( |
| 24 | + appBar: AppBar(title: const Text('Loading...')), |
| 25 | + body: const Center(child: CircularProgressIndicator()), |
| 26 | + ); |
| 27 | +} |
| 28 | + |
| 29 | +/// Builds a home button for the AppBar leading position. |
| 30 | +/// |
| 31 | +/// Shows a home button instead of the back button when navigation cannot pop. |
| 32 | +/// This ensures users can always navigate back to the festival home. |
| 33 | +/// |
| 34 | +/// The [festivalId] is used to navigate to the correct festival home page. |
| 35 | +/// |
| 36 | +/// Example: |
| 37 | +/// ```dart |
| 38 | +/// AppBar( |
| 39 | +/// leading: buildHomeLeadingButton(context, festivalId), |
| 40 | +/// ) |
| 41 | +/// ``` |
| 42 | +Widget? buildHomeLeadingButton(BuildContext context, String festivalId) { |
| 43 | + if (canPopNavigation(context)) { |
| 44 | + return null; // Use default back button |
| 45 | + } |
| 46 | + |
| 47 | + return Semantics( |
| 48 | + label: 'Go to home screen', |
| 49 | + hint: 'Double tap to return to drinks list', |
| 50 | + button: true, |
| 51 | + child: IconButton( |
| 52 | + icon: const Icon(Icons.home), |
| 53 | + onPressed: () => context.go(buildFestivalHome(festivalId)), |
| 54 | + tooltip: 'Home', |
| 55 | + ), |
| 56 | + ); |
| 57 | +} |
| 58 | + |
| 59 | +/// Builds a breadcrumb-style title for the AppBar. |
| 60 | +/// |
| 61 | +/// Shows a primary title with the festival name as a subtitle for context. |
| 62 | +/// This provides consistent navigation breadcrumbs across detail screens. |
| 63 | +/// |
| 64 | +/// The [title] is the main heading (e.g., brewery name, style name, drink name). |
| 65 | +/// The [festivalName] appears as a smaller subtitle below the title. |
| 66 | +/// |
| 67 | +/// Example: |
| 68 | +/// ```dart |
| 69 | +/// AppBar( |
| 70 | +/// title: buildBreadcrumbTitle( |
| 71 | +/// context, |
| 72 | +/// title: 'IPA', |
| 73 | +/// festivalName: 'Cambridge Beer Festival 2025', |
| 74 | +/// ), |
| 75 | +/// ) |
| 76 | +/// ``` |
| 77 | +Widget buildBreadcrumbTitle( |
| 78 | + BuildContext context, { |
| 79 | + required String title, |
| 80 | + required String festivalName, |
| 81 | +}) { |
| 82 | + final theme = Theme.of(context); |
| 83 | + |
| 84 | + return Column( |
| 85 | + mainAxisSize: MainAxisSize.min, |
| 86 | + crossAxisAlignment: CrossAxisAlignment.start, |
| 87 | + children: [ |
| 88 | + Text( |
| 89 | + title, |
| 90 | + style: theme.textTheme.titleLarge, |
| 91 | + overflow: TextOverflow.ellipsis, |
| 92 | + ), |
| 93 | + Text( |
| 94 | + festivalName, |
| 95 | + style: theme.textTheme.bodySmall?.copyWith( |
| 96 | + color: theme.colorScheme.onSurfaceVariant, |
| 97 | + ), |
| 98 | + overflow: TextOverflow.ellipsis, |
| 99 | + ), |
| 100 | + ], |
| 101 | + ); |
| 102 | +} |
0 commit comments