diff --git a/album/lib/albumspage.dart b/album/lib/albumspage.dart index 2ba88b3..55312eb 100644 --- a/album/lib/albumspage.dart +++ b/album/lib/albumspage.dart @@ -1,11 +1,14 @@ +import 'package:album/albumpage.dart'; +import 'package:album/createalbum.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:riviu_buku/models/album.dart'; -import 'package:album/albumpage.dart'; -import 'package:album/createalbum.dart'; +import 'package:riviu_buku/models/user.dart'; class AlbumsPage extends StatefulWidget { - AlbumsPage({Key? key}) : super(key: key); + final User user; + + AlbumsPage({Key? key, required this.user}) : super(key: key); @override _AlbumsPageState createState() => _AlbumsPageState(); @@ -18,12 +21,14 @@ class _AlbumsPageState extends State { final response = await http.get(Uri.parse('http://127.0.0.1:8000/album/json/')); if (response.statusCode == 200) { - return albumFromJson(response.body); + List albums = albumFromJson(response.body); + return albums.where((album) => album.fields.name.toLowerCase().contains(_searchQuery.toLowerCase())).toList(); } else { throw Exception('Failed to load albums'); } } + void viewAlbum(Album album) { Navigator.push( context, @@ -31,91 +36,104 @@ class _AlbumsPageState extends State { ); } - @override Widget build(BuildContext context) { + User user = widget.user; return Scaffold( appBar: AppBar( title: Text('Albums: Your Personal Book Collections'), ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Gather, organize, and share. Albums are an ideal way to group books.', - ), - TextField( - onChanged: (value) { - setState(() { - _searchQuery = value; - }); - }, - decoration: InputDecoration( - labelText: "Search albums...", - ), - ), - Expanded( // Wrap the FutureBuilder in an Expanded widget - child: FutureBuilder>( - future: fetchAlbums(), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - return GridView.builder( - itemCount: snapshot.data!.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, // change this number to adjust the number of items in a row - crossAxisSpacing: 4.0, - mainAxisSpacing: 4.0, - ), - itemBuilder: (BuildContext context, int index){ - return Card( - child: Stack( - children: [ - Positioned.fill( - child: Image.network(snapshot.data![index].fields.coverImage, fit: BoxFit.cover), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Gather, organize, and share. Albums are an ideal way to group books.', + ), + TextField( + onChanged: (value) { + setState(() { + _searchQuery = value; + }); + }, + decoration: InputDecoration( + labelText: "Search albums...", ), - Positioned( - bottom: 0, - left: 0, - right: 0, - child: Container( - color: Colors.black54, - padding: EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(snapshot.data![index].fields.name, style: TextStyle(color: Colors.white)), - Text(snapshot.data![index].fields.description, style: TextStyle(color: Colors.white)), - ElevatedButton( - onPressed: () => viewAlbum(snapshot.data![index]), - child: Text('View Album'), + ), + Expanded( + // Wrap the FutureBuilder in an Expanded widget + child: FutureBuilder>( + future: fetchAlbums(), + builder: (context, snapshot) { + if (snapshot.hasError) { + return Text('Error disini: ${snapshot.error}'); + } else if (snapshot.hasData) { + return GridView.builder( + itemCount: snapshot.data!.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + // change this number to adjust the number of items in a row + crossAxisSpacing: 4.0, + mainAxisSpacing: 4.0, ), - ], - ), - ), + itemBuilder: (BuildContext context, int index) { + return Card( + child: Stack( + children: [ + Positioned.fill( + child: Image.network( + snapshot.data![index].fields.coverImage, + fit: BoxFit.cover), + ), + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Container( + color: Colors.black54, + padding: EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text(snapshot.data![index].fields.name, + style: + TextStyle(color: Colors.white)), + Text( + snapshot + .data![index].fields.description, + style: + TextStyle(color: Colors.white)), + ElevatedButton( + onPressed: () => + viewAlbum(snapshot.data![index]), + child: Text('View Album'), + ), + ], + ), + ), + ), + ], + ), + ); + }, + ); + } else { + return CircularProgressIndicator(); + } + }, ), - ], - ), - ); - }, - ); - } else { - return CircularProgressIndicator(); - } - }, - ), - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( onPressed: () { // TODO: Implement create album functionality Navigator.push( context, - MaterialPageRoute(builder: (context) => CreateAlbumPage()), + MaterialPageRoute( + builder: (context) => CreateAlbumPage(user: user)), ); }, tooltip: 'Create an Album', diff --git a/album/lib/createalbum.dart b/album/lib/createalbum.dart index cb26fe6..e8ffc03 100644 --- a/album/lib/createalbum.dart +++ b/album/lib/createalbum.dart @@ -3,36 +3,45 @@ import 'package:riviu_buku/models/album.dart' as album; import 'package:riviu_buku/models/book.dart' as book; import 'package:http/http.dart' as http; import 'dart:convert'; +import 'package:riviu_buku/models/user.dart'; +import 'package:album/albumspage.dart'; +import 'package:review/reviewpage.dart'; class CreateAlbumPage extends StatefulWidget { + final User user; + CreateAlbumPage({Key? key, required this.user}) : super(key: key); @override _CreateAlbumPageState createState() => _CreateAlbumPageState(); + } class _CreateAlbumPageState extends State { final TextEditingController _nameController = TextEditingController(); final TextEditingController _descriptionController = TextEditingController(); final TextEditingController _searchController = TextEditingController(); - List _selectedBooks = []; + List _selectedBooks = []; + Map _books = {}; Future> fetchBooks() async { - var url = Uri.parse('http://127.0.0.1:8000/json/'); - var response = await http.get( - url, - headers: {"Content-Type": "application/json"}, - ); + final response = await http.get(Uri.parse('http://127.0.0.1:8000/json/')); - var data = jsonDecode(utf8.decode(response.bodyBytes)); - - List list_book = []; - for (var d in data) { - if (d != null) { - list_book.add(book.Book.fromJson(d)); - } + if (response.statusCode == 200) { + List books = book.bookFromJson(response.body); + return books.where((book) { + if (book.fields?.title == null) { + print('Title is null for book: ${book.pk}'); + } + if (_searchController.text == null) { + print('Search query is null'); + } + return book.fields?.title?.toLowerCase().contains(_searchController.text.toLowerCase() ?? '') ?? false; + }).toList(); + } else { + throw Exception('Failed to load books'); } - return list_book; } + Widget buildSelectedBooks() { return GridView.builder( itemCount: _selectedBooks.length, @@ -42,22 +51,38 @@ class _CreateAlbumPageState extends State { mainAxisSpacing: 4.0, ), itemBuilder: (BuildContext context, int index) { - book.Fields bookFields = _selectedBooks[index].fields!; - print(bookFields.toJson()); + book.Book selectedBook = _books[_selectedBooks[index]]!; + book.Fields bookFields = selectedBook.fields!; return GestureDetector( onTap: () { // TODO: Implement onTap functionality if needed }, child: Card( - child: Column( + child: Stack( + alignment: Alignment.topRight, children: [ - Expanded( - child: Image.network( - bookFields.coverImg ?? "", - fit: BoxFit.cover, + Column( + children: [ + Expanded( + child: Image.network( + bookFields.coverImg ?? "", + fit: BoxFit.cover, + ), + ), + Text((bookFields.title) ?? 'Default Title'), + ], + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: () { + setState(() { + _selectedBooks.removeAt(index); + }); + }, ), ), - Text((bookFields.title) ?? 'Default Title'), ], ), ), @@ -66,12 +91,8 @@ class _CreateAlbumPageState extends State { ); } - - - - Future createAlbum() async { - var url = Uri.parse('http://127.0.0.1:8000/album/create-album'); // replace with your Django server URL + var url = Uri.parse('http://127.0.0.1:8000/album/create-album-flutter/'); // replace with your Django server URL var response = await http.post( url, @@ -80,6 +101,7 @@ class _CreateAlbumPageState extends State { 'name': _nameController.text, 'description': _descriptionController.text, 'books': _selectedBooks, + 'user': widget.user.username }), ); @@ -94,6 +116,7 @@ class _CreateAlbumPageState extends State { @override Widget build(BuildContext context) { + User user = widget.user; return Scaffold( appBar: AppBar( title: Text('Create a new album'), @@ -153,26 +176,42 @@ class _CreateAlbumPageState extends State { mainAxisSpacing: 4.0, ), itemBuilder: (BuildContext context, int index) { - return GestureDetector( - onTap: () { - setState(() { - if (snapshot.data![index].pk != null) { - _selectedBooks.add(snapshot.data![index]); - } - }); - }, - child: Card( - child: Column( - children: [ - Expanded( - child: Image.network( - snapshot.data![index].fields?.coverImg ?? "", - fit: BoxFit.cover, - ), + return Card( + child: Column( + children: [ + Expanded( + child: Image.network( + snapshot.data![index].fields?.coverImg ?? "", + fit: BoxFit.cover, ), - Text((snapshot.data![index].fields?.title) ?? 'Default Title'), - ], - ), + ), + Text((snapshot.data![index].fields?.title) ?? 'Default Title'), + ElevatedButton( + onPressed: () { + setState(() { + if (snapshot.data![index].pk != null) { + _selectedBooks.add(snapshot.data![index].pk!); + _books[snapshot.data![index].pk!] = snapshot.data![index]; + } + }); + }, + child: Text('Add to Album'), + ), + ElevatedButton( + onPressed: () {Navigator.push( + context, + MaterialPageRoute( + builder: (context){ + return ReviewPage( + book: snapshot.data![index], user: user, + ); + } + ), + ); + }, + child: Text('View Book'), + ), + ], ), ); }, @@ -192,6 +231,11 @@ class _CreateAlbumPageState extends State { ElevatedButton( onPressed: () { // TODO: Implement create album functionality + createAlbum(); + Navigator.push( + context, + MaterialPageRoute(builder: (context) => AlbumsPage(user: user)), + ); }, child: Text('Create'), ), diff --git a/lib/authentication/menu.dart b/lib/authentication/menu.dart index fc5e077..89cee64 100644 --- a/lib/authentication/menu.dart +++ b/lib/authentication/menu.dart @@ -47,7 +47,7 @@ class MyHomePage extends StatelessWidget { case "Albums": Navigator.push( context, - MaterialPageRoute(builder: (context) => AlbumsPage()), + MaterialPageRoute(builder: (context) => AlbumsPage(user: user)), ); break; }