From 6e19603125afeff6b42acddc63ac38be09860702 Mon Sep 17 00:00:00 2001 From: tentamdin Date: Sun, 19 Jan 2025 15:38:00 +0530 Subject: [PATCH 1/3] update home screen with new design --- lib/ui/screen/home_screen.dart | 135 ++++++++++++++++++++--------- lib/ui/screen/skeleton_screen.dart | 49 +++++++++-- lib/util/enum.dart | 2 +- 3 files changed, 139 insertions(+), 47 deletions(-) diff --git a/lib/ui/screen/home_screen.dart b/lib/ui/screen/home_screen.dart index 2b4f78d..3a69b6e 100644 --- a/lib/ui/screen/home_screen.dart +++ b/lib/ui/screen/home_screen.dart @@ -4,8 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:gompa_tour/ui/screen/deities_list_screen.dart'; import 'package:gompa_tour/ui/screen/festival_list_screen.dart'; -import 'package:gompa_tour/ui/screen/organization_list_screen.dart'; import 'package:gompa_tour/ui/screen/orginatzations_screen.dart'; +import 'package:gompa_tour/ui/screen/qr_screen.dart'; import 'package:gompa_tour/util/enum.dart'; class HomeScreen extends ConsumerWidget { @@ -13,31 +13,86 @@ class HomeScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return SingleChildScrollView( - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _buildCard( - MenuType.deities, - 'assets/images/buddha.png', - context, + return Column( + children: [ + _buildHeader(context), + _buildSearchBar(context), + const Divider(), + Expanded( + child: GridView.count( + crossAxisCount: 2, + padding: EdgeInsets.all(8), + mainAxisSpacing: 16, + crossAxisSpacing: 16, + children: [ + _buildCard( + MenuType.deities, + 'assets/images/buddha.png', + context, + ), + _buildCard( + MenuType.organization, + 'assets/images/potala2.png', + context, + ), + _buildCard( + MenuType.pilgrimage, + 'assets/images/duchen.png', + context, + ), + _buildCard( + MenuType.festival, + 'assets/images/duchen.png', + context, + ), + ], ), - const SizedBox(height: 16), - _buildCard( - MenuType.organization, - 'assets/images/potala2.png', - context, + ), + const SizedBox(height: 32), + ], + ); + } + + Widget _buildHeader(BuildContext context) { + return Column( + children: [ + Text( + 'Department of Religion and Culture', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 16), - _buildCard( - MenuType.festival, - 'assets/images/duchen.png', - context, + ), + Text( + 'Central Tibetan Administration', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 32), + ), + ], + ); + } + + Widget _buildSearchBar(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric( + horizontal: 28, + vertical: 16, + ), + child: SearchBar( + backgroundColor: WidgetStateProperty.resolveWith( + (states) => Colors.white, + ), + controller: TextEditingController(), + leading: Icon(Icons.search), + trailing: [ + IconButton( + icon: Icon(Icons.qr_code), + onPressed: () {}, + ) ], + hintText: 'Search here....', ), ); } @@ -59,27 +114,27 @@ class HomeScreen extends ConsumerWidget { } }, child: Card( - color: Colors.blue, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Image.asset( + color: Colors.white, + child: Column( + children: [ + Flexible( + child: Image.asset( imagePath, - height: 140, + height: 120, fit: BoxFit.contain, ), - const SizedBox(height: 8), - Text( - _getTitle(type, context), - style: const TextStyle( - color: Colors.white, - fontSize: 22, - fontWeight: FontWeight.bold, - ), + ), + Text( + _getTitle(type, context), + style: const TextStyle( + color: Colors.black, + fontSize: 22, + fontWeight: FontWeight.bold, ), - ], - ), + ), + Text("199"), + const SizedBox(height: 8), + ], ), ), ); @@ -93,6 +148,8 @@ class HomeScreen extends ConsumerWidget { return AppLocalizations.of(context)!.organizations; case MenuType.festival: return AppLocalizations.of(context)!.festival; + case MenuType.pilgrimage: + return "Pilgrimage"; } } } diff --git a/lib/ui/screen/skeleton_screen.dart b/lib/ui/screen/skeleton_screen.dart index 456b053..2e81d41 100644 --- a/lib/ui/screen/skeleton_screen.dart +++ b/lib/ui/screen/skeleton_screen.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_switch/flutter_switch.dart'; +import 'package:gompa_tour/states/language_state.dart'; import 'package:gompa_tour/ui/screen/qr_screen.dart'; import 'package:gompa_tour/ui/screen/search_screen.dart'; import 'package:gompa_tour/ui/screen/settings_screen.dart'; @@ -16,6 +18,7 @@ class SkeletonScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final int? navIndex = ref.watch(bottomNavProvider) as int?; + final currentLanguage = ref.watch(languageProvider).currentLanguage; // Tab configuration List> tabConfigurations = _tabConfiguration(context); @@ -32,14 +35,46 @@ class SkeletonScreen extends ConsumerWidget { //extendBodyBehindAppBar: true, appBar: currentTab['title'] != null ? AppBar( - title: currentTab['title'] == "home" - ? Image.asset( - 'assets/images/logo.png', - height: 40, - ) - : Text(currentTab['title']), - centerTitle: true, + backgroundColor: Colors.white, + leading: Padding( + padding: const EdgeInsets.only(left: 12), + child: Image.asset( + 'assets/images/logo.png', + height: 40, + ), + ), + title: Text( + "Neykor", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + centerTitle: false, elevation: 1, + actions: [ + currentTab["title"] == "home" + ? FlutterSwitch( + width: 60, + height: 30, + toggleSize: 20, + valueFontSize: 12.0, + value: currentLanguage == LanguageState.TIBETAN, + activeText: "བོད།", + inactiveText: "EN", + showOnOff: true, + onToggle: (val) { + ref.read(languageProvider.notifier).setLanguage(val + ? LanguageState.TIBETAN + : LanguageState.ENGLISH); + }, + ) + : const SizedBox(), + IconButton( + icon: const Icon(Icons.more_vert), + onPressed: () {}, + ), + ], ) : null, body: AnimatedSwitcher( diff --git a/lib/util/enum.dart b/lib/util/enum.dart index 68a8436..6ab5eed 100644 --- a/lib/util/enum.dart +++ b/lib/util/enum.dart @@ -1,2 +1,2 @@ // create enum -enum MenuType { festival, organization, deities } +enum MenuType { festival, organization, deities, pilgrimage } From 054919dc0deef9811adf2be20d588eb25a6dfdb1 Mon Sep 17 00:00:00 2001 From: tentamdin Date: Mon, 20 Jan 2025 09:39:37 +0530 Subject: [PATCH 2/3] update home UI - kebab menu, total counts, --- lib/repo/database_repository.dart | 9 ++ lib/states/deties_state.dart | 10 ++ lib/states/festival_state.dart | 6 ++ lib/states/organization_state.dart | 5 + lib/ui/screen/home_screen.dart | 159 ++++++++++++++++++++++------- lib/ui/screen/skeleton_screen.dart | 92 +++++++++++++++-- lib/ui/widget/bottom_nav_bar.dart | 4 - 7 files changed, 238 insertions(+), 47 deletions(-) diff --git a/lib/repo/database_repository.dart b/lib/repo/database_repository.dart index a8dab82..b7fdef8 100644 --- a/lib/repo/database_repository.dart +++ b/lib/repo/database_repository.dart @@ -107,6 +107,15 @@ class DatabaseRepository { ); } + // get to total number of items in the database + Future getCount() async { + final db = await dbHelper.database; + final count = Sqflite.firstIntValue( + await db.rawQuery('SELECT COUNT(*) FROM $tableName'), + ); + return count ?? 0; + } + Future> getSortedPaginatedOrganization( int page, int pageSize, String category) async { final db = await dbHelper.database; diff --git a/lib/states/deties_state.dart b/lib/states/deties_state.dart index 5ac08c1..f98a745 100644 --- a/lib/states/deties_state.dart +++ b/lib/states/deties_state.dart @@ -11,6 +11,7 @@ class DeityListState { final int page; final int pageSize; final String? error; + final int total; DeityListState({ required this.deities, @@ -19,6 +20,7 @@ class DeityListState { required this.page, required this.pageSize, this.error, + required this.total, }); factory DeityListState.initial() { @@ -28,6 +30,7 @@ class DeityListState { hasReachedMax: false, page: 0, pageSize: 20, + total: 0, ); } @@ -38,6 +41,7 @@ class DeityListState { int? page, int? pageSize, String? error, + int? total, }) { return DeityListState( deities: deities ?? this.deities, @@ -46,6 +50,7 @@ class DeityListState { page: page ?? this.page, pageSize: pageSize ?? this.pageSize, error: error ?? this.error, + total: total ?? this.total, ); } } @@ -120,6 +125,11 @@ class DeityNotifier extends StateNotifier { } } + // get the total number of deties in the database + Future getDeitiesCount() async { + return await repository.getCount(); + } + void clearSearchResults() { state = DeityListState.initial(); } diff --git a/lib/states/festival_state.dart b/lib/states/festival_state.dart index 8045355..2856e18 100644 --- a/lib/states/festival_state.dart +++ b/lib/states/festival_state.dart @@ -74,6 +74,12 @@ class FestivalNotifier extends StateNotifier { } } + // to get the total number of festivals + Future getFestivalCount() async { + final totalFestivals = await repository.getCount(); + return totalFestivals; + } + void clearSearchResults() { state = FestivalListState.initial(); } diff --git a/lib/states/organization_state.dart b/lib/states/organization_state.dart index 4f96ccc..081c1b3 100644 --- a/lib/states/organization_state.dart +++ b/lib/states/organization_state.dart @@ -130,6 +130,11 @@ class OrganizationNotifier extends StateNotifier { } } + // get total number of organizations + Future getOrganizationCount() async { + return await repository.getCount(); + } + void clearSearchResults() { state = OrganizationListState.initial(); } diff --git a/lib/ui/screen/home_screen.dart b/lib/ui/screen/home_screen.dart index 3a69b6e..b48b1d4 100644 --- a/lib/ui/screen/home_screen.dart +++ b/lib/ui/screen/home_screen.dart @@ -2,52 +2,76 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import 'package:gompa_tour/states/bottom_nav_state.dart'; +import 'package:gompa_tour/states/deties_state.dart'; +import 'package:gompa_tour/states/festival_state.dart'; +import 'package:gompa_tour/states/organization_state.dart'; +import 'package:gompa_tour/states/recent_search.dart'; +import 'package:gompa_tour/states/search_state.dart'; import 'package:gompa_tour/ui/screen/deities_list_screen.dart'; import 'package:gompa_tour/ui/screen/festival_list_screen.dart'; import 'package:gompa_tour/ui/screen/orginatzations_screen.dart'; -import 'package:gompa_tour/ui/screen/qr_screen.dart'; import 'package:gompa_tour/util/enum.dart'; +import 'package:gompa_tour/util/search_debouncer.dart'; -class HomeScreen extends ConsumerWidget { +class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _HomeScreenState(); +} + +class _HomeScreenState extends ConsumerState { + final TextEditingController _searchController = TextEditingController(); + final FocusNode _searchFocusNode = FocusNode(); + final _searchDebouncer = SearchDebouncer(); + + int totalDeity = 0; + int totalOrganization = 0; + int totalFestival = 0; + + @override + void initState() { + super.initState(); + _loadCounts(); + } + + void _loadCounts() async { + totalDeity = + await ref.read(detiesNotifierProvider.notifier).getDeitiesCount(); + totalOrganization = await ref + .read(organizationNotifierProvider.notifier) + .getOrganizationCount(); + totalFestival = + await ref.read(festivalNotifierProvider.notifier).getFestivalCount(); + } + + void _performSearch(String query) async { + if (query.isEmpty || query.length < 3) { + _clearSearchResults(); + return; + } + + _searchDebouncer.run( + query, + onSearch: (q) => + ref.read(searchNotifierProvider.notifier).searchAcrossTables(q), + onSaveSearch: (q) => + ref.read(recentSearchesProvider.notifier).addSearch(q), + onClearResults: _clearSearchResults, + ); + } + + @override + Widget build(BuildContext context) { + final searchState = ref.watch(searchNotifierProvider); + return Column( children: [ _buildHeader(context), _buildSearchBar(context), const Divider(), - Expanded( - child: GridView.count( - crossAxisCount: 2, - padding: EdgeInsets.all(8), - mainAxisSpacing: 16, - crossAxisSpacing: 16, - children: [ - _buildCard( - MenuType.deities, - 'assets/images/buddha.png', - context, - ), - _buildCard( - MenuType.organization, - 'assets/images/potala2.png', - context, - ), - _buildCard( - MenuType.pilgrimage, - 'assets/images/duchen.png', - context, - ), - _buildCard( - MenuType.festival, - 'assets/images/duchen.png', - context, - ), - ], - ), - ), + _buildCategoryCards(context), const SizedBox(height: 32), ], ); @@ -84,12 +108,23 @@ class HomeScreen extends ConsumerWidget { backgroundColor: WidgetStateProperty.resolveWith( (states) => Colors.white, ), - controller: TextEditingController(), + controller: _searchController, + focusNode: _searchFocusNode, leading: Icon(Icons.search), trailing: [ + if (_searchController.text.isNotEmpty) + IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + _searchController.clear(); + _clearSearchResults(); + }, + ), IconButton( icon: Icon(Icons.qr_code), - onPressed: () {}, + onPressed: () { + ref.read(bottomNavProvider.notifier).setAndPersistValue(2); + }, ) ], hintText: 'Search here....', @@ -97,7 +132,45 @@ class HomeScreen extends ConsumerWidget { ); } - Widget _buildCard(MenuType type, String imagePath, BuildContext context) { + Widget _buildCategoryCards(BuildContext context) { + return Expanded( + child: GridView.count( + crossAxisCount: 2, + padding: EdgeInsets.all(8), + mainAxisSpacing: 16, + crossAxisSpacing: 16, + children: [ + _buildCard( + MenuType.deities, + 'assets/images/buddha.png', + context, + totalDeity, + ), + _buildCard( + MenuType.organization, + 'assets/images/potala2.png', + context, + totalOrganization, + ), + _buildCard( + MenuType.pilgrimage, + 'assets/images/duchen.png', + context, + totalFestival, + ), + _buildCard( + MenuType.festival, + 'assets/images/duchen.png', + context, + totalFestival, + ), + ], + ), + ); + } + + Widget _buildCard( + MenuType type, String imagePath, BuildContext context, int count) { return GestureDetector( onTap: () { switch (type) { @@ -132,7 +205,7 @@ class HomeScreen extends ConsumerWidget { fontWeight: FontWeight.bold, ), ), - Text("199"), + Text(count.toString()), const SizedBox(height: 8), ], ), @@ -152,4 +225,16 @@ class HomeScreen extends ConsumerWidget { return "Pilgrimage"; } } + + @override + void dispose() { + _searchController.dispose(); + _searchFocusNode.dispose(); + _searchDebouncer.dispose(); + super.dispose(); + } + + void _clearSearchResults() { + ref.read(searchNotifierProvider.notifier).clearSearchResults(); + } } diff --git a/lib/ui/screen/skeleton_screen.dart b/lib/ui/screen/skeleton_screen.dart index 2e81d41..84d6c71 100644 --- a/lib/ui/screen/skeleton_screen.dart +++ b/lib/ui/screen/skeleton_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_switch/flutter_switch.dart'; import 'package:gompa_tour/states/language_state.dart'; +import 'package:gompa_tour/states/theme_mode_state.dart'; import 'package:gompa_tour/ui/screen/qr_screen.dart'; import 'package:gompa_tour/ui/screen/search_screen.dart'; import 'package:gompa_tour/ui/screen/settings_screen.dart'; @@ -27,15 +28,16 @@ class SkeletonScreen extends ConsumerWidget { HomeScreen(), MapScreen(), QrScreen(), - SearchScreen(), SettingsScreen(), ]; + final themeMode = ref.watch(themeProvider).themeMode; + return Scaffold( //extendBodyBehindAppBar: true, appBar: currentTab['title'] != null ? AppBar( - backgroundColor: Colors.white, + backgroundColor: Colors.white, leading: Padding( padding: const EdgeInsets.only(left: 12), child: Image.asset( @@ -70,10 +72,88 @@ class SkeletonScreen extends ConsumerWidget { }, ) : const SizedBox(), - IconButton( - icon: const Icon(Icons.more_vert), - onPressed: () {}, - ), + MenuAnchor( + builder: (BuildContext context, MenuController controller, + Widget? child) { + return IconButton( + onPressed: () { + if (controller.isOpen) { + controller.close(); + } else { + controller.open(); + } + }, + icon: const Icon(Icons.more_vert), + tooltip: 'Show menu', + ); + }, + style: MenuStyle( + padding: WidgetStateProperty.all( + EdgeInsets.all(12.0), + ), + shape: WidgetStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + minimumSize: WidgetStateProperty.all(Size(190, 48))), + menuChildren: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(AppLocalizations.of(context)!.theme, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + )), + const SizedBox(width: 20), + FlutterSwitch( + width: 55, + height: 30, + toggleSize: 20, + value: themeMode == ThemeMode.dark, + activeIcon: Icon(Icons.dark_mode, size: 15), + inactiveIcon: Icon(Icons.light_mode, size: 15), + onToggle: (val) { + ref.read(themeProvider).themeMode = + val ? ThemeMode.dark : ThemeMode.light; + }, + ), + ], + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(AppLocalizations.of(context)!.language, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + )), + const SizedBox(width: 20), + FlutterSwitch( + width: 55, + height: 30, + toggleSize: 20, + valueFontSize: 12.0, + value: currentLanguage == LanguageState.TIBETAN, + activeText: "བོད།", + inactiveText: "EN", + showOnOff: true, + onToggle: (val) { + ref.read(languageProvider.notifier).setLanguage( + val + ? LanguageState.TIBETAN + : LanguageState.ENGLISH); + }, + ), + ], + ), + ]), + // IconButton( + // icon: const Icon(Icons.more_vert), + // onPressed: () {}, + // ), ], ) : null, diff --git a/lib/ui/widget/bottom_nav_bar.dart b/lib/ui/widget/bottom_nav_bar.dart index 9335408..81bcaff 100644 --- a/lib/ui/widget/bottom_nav_bar.dart +++ b/lib/ui/widget/bottom_nav_bar.dart @@ -52,10 +52,6 @@ class BottomNavBar extends ConsumerWidget { icon: const Icon(Icons.qr_code), label: AppLocalizations.of(context)!.qr, ), - BottomNavigationBarItem( - icon: const Icon(Icons.search), - label: AppLocalizations.of(context)!.search, - ), BottomNavigationBarItem( icon: const Icon(Icons.settings), label: AppLocalizations.of(context)!.settings, From bb6f06c354f67ed58e01aa07a77fb6558c30a6e4 Mon Sep 17 00:00:00 2001 From: tentamdin Date: Mon, 20 Jan 2025 23:15:51 +0530 Subject: [PATCH 3/3] add all search logic and result UI --- lib/ui/screen/home_screen.dart | 131 ++++++++++++++++++++---------- lib/ui/widget/bottom_nav_bar.dart | 2 +- 2 files changed, 89 insertions(+), 44 deletions(-) diff --git a/lib/ui/screen/home_screen.dart b/lib/ui/screen/home_screen.dart index b48b1d4..4337305 100644 --- a/lib/ui/screen/home_screen.dart +++ b/lib/ui/screen/home_screen.dart @@ -11,6 +11,7 @@ import 'package:gompa_tour/states/search_state.dart'; import 'package:gompa_tour/ui/screen/deities_list_screen.dart'; import 'package:gompa_tour/ui/screen/festival_list_screen.dart'; import 'package:gompa_tour/ui/screen/orginatzations_screen.dart'; +import 'package:gompa_tour/ui/widget/search_card_item.dart'; import 'package:gompa_tour/util/enum.dart'; import 'package:gompa_tour/util/search_debouncer.dart'; @@ -72,7 +73,12 @@ class _HomeScreenState extends ConsumerState { _buildSearchBar(context), const Divider(), _buildCategoryCards(context), - const SizedBox(height: 32), + _buildSearchResults(context, searchState), + searchState.isLoading + ? const Center( + child: CircularProgressIndicator(), + ) + : const SizedBox(), ], ); } @@ -112,14 +118,15 @@ class _HomeScreenState extends ConsumerState { focusNode: _searchFocusNode, leading: Icon(Icons.search), trailing: [ - if (_searchController.text.isNotEmpty) - IconButton( - icon: const Icon(Icons.clear), - onPressed: () { - _searchController.clear(); - _clearSearchResults(); - }, - ), + _searchController.text.isNotEmpty + ? IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + _searchController.clear(); + _clearSearchResults(); + }, + ) + : const SizedBox(), IconButton( icon: Icon(Icons.qr_code), onPressed: () { @@ -128,45 +135,64 @@ class _HomeScreenState extends ConsumerState { ) ], hintText: 'Search here....', + onChanged: (value) { + _performSearch(value); + }, ), ); } Widget _buildCategoryCards(BuildContext context) { - return Expanded( - child: GridView.count( - crossAxisCount: 2, - padding: EdgeInsets.all(8), - mainAxisSpacing: 16, - crossAxisSpacing: 16, - children: [ - _buildCard( - MenuType.deities, - 'assets/images/buddha.png', - context, - totalDeity, - ), - _buildCard( - MenuType.organization, - 'assets/images/potala2.png', - context, - totalOrganization, - ), - _buildCard( - MenuType.pilgrimage, - 'assets/images/duchen.png', - context, - totalFestival, - ), - _buildCard( - MenuType.festival, - 'assets/images/duchen.png', - context, - totalFestival, - ), - ], - ), - ); + return _searchController.text.isEmpty + ? Expanded( + child: Center( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 600), // Optional: limits max width + child: Center( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 600), // Optional: limits max width + child: GridView.count( + crossAxisCount: 2, + padding: EdgeInsets.all(8), + mainAxisSpacing: 16, + crossAxisSpacing: 16, + shrinkWrap: true, + childAspectRatio: 1, + children: [ + _buildCard( + MenuType.deities, + 'assets/images/buddha.png', + context, + totalDeity, + ), + _buildCard( + MenuType.organization, + 'assets/images/potala2.png', + context, + totalOrganization, + ), + _buildCard( + MenuType.pilgrimage, + 'assets/images/duchen.png', + context, + totalFestival, + ), + _buildCard( + MenuType.festival, + 'assets/images/duchen.png', + context, + totalFestival, + ), + ], + ), + ), + ), + ), + ), + ) + : const SizedBox(); } Widget _buildCard( @@ -213,6 +239,25 @@ class _HomeScreenState extends ConsumerState { ); } + Widget _buildSearchResults(BuildContext context, SearchState searchState) { + if (searchState.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } + return searchState.results.isNotEmpty + ? Expanded( + child: ListView.builder( + itemCount: searchState.results.length, + itemBuilder: (context, index) { + final searchableItem = searchState.results[index]; + return SearchCardItem(searchableItem: searchableItem); + }, + ), + ) + : const SizedBox(); + } + String _getTitle(MenuType type, BuildContext context) { switch (type) { case MenuType.deities: diff --git a/lib/ui/widget/bottom_nav_bar.dart b/lib/ui/widget/bottom_nav_bar.dart index 81bcaff..cbbfa30 100644 --- a/lib/ui/widget/bottom_nav_bar.dart +++ b/lib/ui/widget/bottom_nav_bar.dart @@ -53,7 +53,7 @@ class BottomNavBar extends ConsumerWidget { label: AppLocalizations.of(context)!.qr, ), BottomNavigationBarItem( - icon: const Icon(Icons.settings), + icon: const Icon(Icons.person), label: AppLocalizations.of(context)!.settings, ), ],