diff --git a/lib/src/screens/explore.dart b/lib/src/screens/explore.dart index de6681f..b5c9c7c 100644 --- a/lib/src/screens/explore.dart +++ b/lib/src/screens/explore.dart @@ -1,24 +1,94 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; -import 'details.dart'; // Import the DetailsScreen +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +import 'category.dart'; +import 'itemcards.dart'; +import 'trends.dart'; +import 'details.dart'; class ExploreScreen extends StatefulWidget { const ExploreScreen({super.key}); @override - _ExploreScreenState createState() => _ExploreScreenState(); + State createState() => _ExploreScreenState(); } class _ExploreScreenState extends State { List books = []; + List filteredBooks = []; + bool isLoading = true; + bool _isSearchVisible = false; + final TextEditingController _searchController = TextEditingController(); + final FocusNode _searchFocusNode = FocusNode(); @override void initState() { super.initState(); + fetchBooks(); + _searchController.addListener(_filterBooks); } + Future fetchBooks() async { + await dotenv.load(fileName: "assets/config/.env"); + try { + final response = await Dio().get('${dotenv.env['API_BASE_URL']}/books'); + if (response.statusCode == 200) { + if (mounted) { + setState(() { + books = response.data; + filteredBooks = books; + isLoading = false; + }); + } + } else { + throw Exception('Failed to load books'); + } + } catch (e) { + if (mounted) { + setState(() { + isLoading = false; + }); + } + if (kDebugMode) { + print('Error fetching books: $e'); + } + } + } + void _filterBooks() { + setState(() { + filteredBooks = books + .where((book) => + book['title'].toLowerCase().contains(_searchController.text.toLowerCase())) + .toList(); + if (kDebugMode) { + print('Filtered Books: ${filteredBooks.length}'); + } + }); + } + + void _toggleSearchBar() { + setState(() { + _isSearchVisible = !_isSearchVisible; + if (_isSearchVisible) { + _searchFocusNode.requestFocus(); + } else { + _searchFocusNode.unfocus(); + _searchController.clear(); + filteredBooks = books; + } + }); + } + + @override + void dispose() { + _searchController.removeListener(_filterBooks); + _searchController.dispose(); + _searchFocusNode.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -26,19 +96,103 @@ class _ExploreScreenState extends State { // the major Material Components. return Scaffold( appBar: AppBar( - title: const Text('Example title'), - actions: const [ + title: _isSearchVisible + ? TextField( + controller: _searchController, + focusNode: _searchFocusNode, + decoration: const InputDecoration( + hintText: 'Search...', + border: InputBorder.none, + ), + style: const TextStyle(color: Colors.black), + ) + : const Text('Search', + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w800, + color: Colors.black, + ), + ), + actions: [ IconButton( - icon: Icon(Icons.search), + icon: Icon(_isSearchVisible ? Icons.close : Icons.search), tooltip: 'Search', - onPressed: null, + onPressed: _toggleSearchBar, ), ], ), - // body is the majority of the screen. - body: const Center( - child: Text('Hello, world!'), - ), + body: isLoading + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + const SizedBox(height: 5), + const CategoryCard(), + const SizedBox(height: 5), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: filteredBooks.map((book) { + return InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DetailsScreen( + imageUrl: book['cover_url'] ?? 'assets/images/imgae_not.jpg', + title: book['title'] ?? 'Unknown Title', + author: book['author'] ?? 'Unknown Author', + description: book['description'] ?? 'No description available.', + bookUrl: book['pdf_url'], + ), + ), + ); + }, + child: ItemCards( + imagepic: book['cover_url'] ?? 'assets/images/imgae_not.jpg', + text1: book['title'] ?? 'Unknown Title', + text2: book['author'] ?? 'Unknown Author', + ), + ); + }).toList(), + ), + ), + const SizedBox(height: 10), + const Trends(), + const SizedBox(height: 15), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: books.map((book) { + return InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DetailsScreen( + imageUrl: book['cover_url'] ?? 'assets/images/imgae_not.jpg', + title: book['title'] ?? 'Unknown Title', + author: book['author'] ?? 'Unknown Author', + description: book['description'] ?? 'No description available.', + bookUrl: book['pdf_url'], + ), + ), + ); + }, + child: ItemCards( + imagepic: book['cover_url'] ?? 'assets/images/imgae_not.jpg', + text1: book['title'] ?? 'Unknown Title', + text2: book['author'] ?? 'Unknown Author', + ), + ); + }).toList(), + ), + ), + const SizedBox(height: 20), + ], + ), + ), ); } } diff --git a/lib/src/screens/homepage.dart b/lib/src/screens/homepage.dart index 9a4e70d..ee39dba 100644 --- a/lib/src/screens/homepage.dart +++ b/lib/src/screens/homepage.dart @@ -27,29 +27,29 @@ class _HomePageState extends State { fetchBooks(); } -Future fetchBooks() async { - await dotenv.load(fileName: "assets/config/.env"); - try { - final response = await Dio().get('${dotenv.env['API_BASE_URL']}/books'); - if (response.statusCode == 200) { + Future fetchBooks() async { + await dotenv.load(fileName: "assets/config/.env"); + try { + final response = await Dio().get('${dotenv.env['API_BASE_URL']}/books'); + if (response.statusCode == 200) { + if (mounted) { + setState(() { + books = response.data; + isLoading = false; + }); + } + } else { + throw Exception('Failed to load books'); + } + } catch (e) { if (mounted) { setState(() { - books = response.data; isLoading = false; }); } - } else { - throw Exception('Failed to load books'); - } - } catch (e) { - if (mounted) { - setState(() { - isLoading = false; - }); + print('Error fetching books: $e'); } - print('Error fetching books: $e'); } -} diff --git a/lib/src/widgets/bottomnav.dart b/lib/src/widgets/bottomnav.dart index ee38eeb..a0b1f22 100644 --- a/lib/src/widgets/bottomnav.dart +++ b/lib/src/widgets/bottomnav.dart @@ -56,4 +56,4 @@ class _BottomNavBarState extends State { ]), ); } -} +} \ No newline at end of file