diff --git a/client/lib/api_service/catalog_service.dart b/client/lib/api_service/catalog_service.dart index 38645af32fffa766635b0d154aa832f61b81ec6c..63c1d7c9aa09e6d59bd4a2c0590c5ecf8396c84b 100644 --- a/client/lib/api_service/catalog_service.dart +++ b/client/lib/api_service/catalog_service.dart @@ -73,6 +73,50 @@ class CatalogService { } } +class SearchResponse { + final List<Book2> books; + + const SearchResponse({ + required this.books, + }); + + factory SearchResponse.fromJson(List<dynamic> json) { + List<Book2> books = []; + dynamic booksJson = json; + for (int i = 0; i < booksJson.length; i++) { + books.add(Book2.fromJson(booksJson[i])); + } + ; + return SearchResponse(books: books); + } +} + +class SearchService { + final API api = const API(baseUrl: BASE_URL); + + Future<ResponseBase<SearchResponse>> getSearchPageData(String query) async { + String urlSearch = "book/search/" + query; + try { + dynamic response = await api.get(urlSearch); + return ResponseBase.fromJson( + response, SearchResponse.fromJson(response["data"])); + } catch (e) { + rethrow; + } + } + + Future<ResponseBase<SearchResponse>> getFilterPageData(String query) async { + String urlSearch = "book/category/" + query; + try { + dynamic response = await api.get(urlSearch); + return ResponseBase.fromJson( + response, SearchResponse.fromJson(response["data"])); + } catch (e) { + rethrow; + } + } +} + class BookService { final API api = const API(baseUrl: BASE_URL); diff --git a/client/lib/api_service/payment_service.dart b/client/lib/api_service/payment_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..d827b35658630e8f1a9731dade66b3d343d692fb --- /dev/null +++ b/client/lib/api_service/payment_service.dart @@ -0,0 +1,69 @@ +import 'package:client/api_service/api_base.dart'; +import 'package:client/constants.dart'; +import 'package:client/model/book.dart'; +import 'package:client/model/payment.dart'; +import 'package:client/model/response_base.dart'; + +class PaymentResponse { + final int amount; + final String email; + final Book3 book; + final String status; + final Metadata metadata; + + const PaymentResponse({ + required this.amount, + required this.email, + required this.book, + required this.status, + required this.metadata, + }); + + factory PaymentResponse.fromJson(Map<String, dynamic> json) { + return PaymentResponse( + amount: json["amount"], + email: json["email"], + book: Book3.fromJson(json["book"]), + status: json["status"], + metadata: Metadata.fromJson(json["metadata"])); + } +} + +class PaymentService { + final API api = const API(baseUrl: BASE_URL); + + // Future<ResponseBase<LoginResponse>> login( + // String email, String password) async { + // try { + // dynamic response = await api + // .post("user/login", body: {"email": email, "password": password}); + // var result = ResponseBase.fromJson( + // response, LoginResponse.fromJson(response["data"])); + // var pref = await SharedPreferences.getInstance(); + // pref.setString("token", result.data.token); + // return ResponseBase.fromJson( + // response, LoginResponse.fromJson(response["data"])); + // } catch (e) { + // rethrow; + // } + // } + + Future<ResponseBase<PaymentResponse>> buy({ + required String book_id, + required String payment_method, + required String phonebook, + }) async { + try { + dynamic response = await api.post("transaction/buy", body: { + "book_id": book_id, + "payment_method": payment_method, + "phonebook": phonebook, + }); + + return ResponseBase.fromJson( + response, PaymentResponse.fromJson(response["data"])); + } catch (e) { + rethrow; + } + } +} diff --git a/client/lib/components/screens/filter/filter_page.dart b/client/lib/components/screens/filter/filter_page.dart index 42c189a23df6830933f8878b25356e5e2f87d492..d837ec704164d02ad57887709520ec515d0ff423 100644 --- a/client/lib/components/screens/filter/filter_page.dart +++ b/client/lib/components/screens/filter/filter_page.dart @@ -1,3 +1,4 @@ +import 'package:client/api_service/catalog_service.dart'; import 'package:client/components/screens/resultSearch/result_filter.dart'; import 'package:client/model/category.dart'; import 'package:client/styles.dart'; @@ -5,25 +6,42 @@ import 'package:flutter/material.dart'; import 'package:filter_list/filter_list.dart'; List<Category> userList = [ - const Category(id: 1, name: "Sport"), - const Category(id: 2, name: "Education"), - const Category(id: 3, name: "Arts"), - const Category(id: 4, name: "Food"), - const Category(id: 5, name: "Motorcycle"), - const Category(id: 6, name: "Toys"), - const Category(id: 7, name: "Animal"), - const Category(id: 8, name: "Fruis"), - const Category(id: 9, name: "Happy"), - const Category(id: 10, name: "Romance"), - const Category(id: 11, name: "Comedy"), - const Category(id: 12, name: "Horror"), - const Category(id: 13, name: "Thriller"), + Category(id: 1, name: "Comic"), + Category(id: 2, name: "Novel"), + Category(id: 3, name: "Education"), + Category(id: 4, name: "Children"), + Category(id: 5, name: "Technology"), ]; -class FilterPage extends StatelessWidget { - const FilterPage({Key? key, this.selectedUserList}) : super(key: key); - final List<Category>? selectedUserList; +class Filterpage extends StatefulWidget { + const Filterpage({Key? key}) : super(key: key); + @override + _FilterpageState createState() => _FilterpageState(); +} + +class _FilterpageState extends State<Filterpage> { + // const _FilterpageState({Key? key, this.selectedUserList}) : super(key: key); + List<Category> selectedUserList = []; + List<Category> listCategory = []; + + final CatalogService catalogService = CatalogService(); + void initData() async { + final homeData = (await catalogService.getHomePageData()).data; + listCategory = homeData.categories; + print(listCategory); + setState(() { + listCategory = listCategory; + }); + userList = listCategory; + } + + @override + void initState() { + super.initState(); + initData(); + } + Widget build(BuildContext context) { Widget back() { return Container( diff --git a/client/lib/components/screens/resultSearch/element_result.dart b/client/lib/components/screens/resultSearch/element_result.dart index 107ec916978aa0a5db12044e473052fa82323819..996df9f92ffb0da4099dbcb5e34cecc9fb7c75ea 100644 --- a/client/lib/components/screens/resultSearch/element_result.dart +++ b/client/lib/components/screens/resultSearch/element_result.dart @@ -1,3 +1,6 @@ +import 'package:client/components/detail/detail_book.dart'; +// import 'package:client/components/screens/filter/filterPage.dart'; +// import 'package:client/screens/login/LoginPage.dart'; import 'package:flutter/material.dart'; import '../../../styles.dart'; @@ -5,6 +8,7 @@ import '../../../styles.dart'; class ElementBook extends StatelessWidget { const ElementBook({ Key? key, + required this.id, required this.image, required this.title, required this.author, @@ -12,6 +16,7 @@ class ElementBook extends StatelessWidget { required this.rating, }) : super(key: key); + final int id; final String image; final String title; final String author; @@ -20,68 +25,78 @@ class ElementBook extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.only(top: 20), - height: 220, - padding: const EdgeInsets.all(10), - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - border: Border.all(style: BorderStyle.none), - boxShadow: const [ - BoxShadow(color: Colors.black38, spreadRadius: 0, blurRadius: 1), - ]), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.asset(image, width: 122), - const SizedBox(width: 30), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Text( - title, - style: bookTitle.copyWith(fontSize: 16), - textAlign: TextAlign.start, - ), - Text( - author, - style: textauthor.copyWith(fontSize: 14), - textAlign: TextAlign.start, - ), - Row( - children: [ - Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 15), - decoration: BoxDecoration( - color: blueLight, - borderRadius: BorderRadius.circular(20), - ), - child: Text( - category, - style: bookTitle.copyWith( - fontSize: 12, color: Colors.white), - textAlign: TextAlign.start, - )), - const SizedBox(width: 20), - const Icon( - Icons.star_rate_rounded, - color: Color.fromARGB(255, 255, 187, 0), - size: 20.0, - semanticLabel: 'Ratings', + return InkWell( + onTap: () => { + // print(title), + // Navigator.push( + // context, MaterialPageRoute(builder: (context) => Filterpage())) + }, + child: Container( + margin: EdgeInsets.only(top: 20), + height: 220, + padding: EdgeInsets.all(10), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + border: Border.all(style: BorderStyle.none), + boxShadow: [ + BoxShadow(color: Colors.black38, spreadRadius: 0, blurRadius: 1), + ]), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset(image, width: 122), + SizedBox(width: 30), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text( + title, + style: bookTitle.copyWith(fontSize: 16), + textAlign: TextAlign.start, + ), + Container( + width: 200, + child: Text( + author, + style: textauthor.copyWith(fontSize: 14), + textAlign: TextAlign.justify, ), - Text( - rating.toString(), - style: bookTitle.copyWith(fontSize: 13), - textAlign: TextAlign.start, - ), - ], - ) - ]) - ], + ), + Row( + children: [ + Container( + padding: + EdgeInsets.symmetric(vertical: 8, horizontal: 15), + decoration: BoxDecoration( + color: blueLight, + borderRadius: BorderRadius.circular(20), + ), + child: Text( + category, + style: bookTitle.copyWith( + fontSize: 12, color: Colors.white), + textAlign: TextAlign.start, + )), + SizedBox(width: 20), + Icon( + Icons.star_rate_rounded, + color: Color.fromARGB(255, 255, 187, 0), + size: 20.0, + semanticLabel: 'Ratings', + ), + Text( + rating.toString(), + style: bookTitle.copyWith(fontSize: 13), + textAlign: TextAlign.start, + ), + ], + ) + ]) + ], + ), ), ); } diff --git a/client/lib/components/screens/resultSearch/result_filter.dart b/client/lib/components/screens/resultSearch/result_filter.dart index cccf9270883caa5b7bb2c2326fa673023798758d..628705efcb0270ee71e5bec5c9e6d7b882454430 100644 --- a/client/lib/components/screens/resultSearch/result_filter.dart +++ b/client/lib/components/screens/resultSearch/result_filter.dart @@ -1,7 +1,12 @@ +import 'dart:convert'; +import 'package:client/api_service/catalog_service.dart'; +import 'package:client/components/detail/detail_book.dart'; +// import 'package:client/components/screens/filter/filterPage.dart'; import 'package:client/components/screens/filter/filter_page.dart'; import 'package:client/components/screens/resultSearch/element_result.dart'; import 'package:client/components/screens/resultSearch/result_search.dart'; import 'package:client/model/book.dart'; +import 'package:client/screens/home/bottom_navbar.dart'; import 'package:client/styles.dart'; import 'package:flutter/material.dart'; @@ -152,8 +157,43 @@ class ResultFilter extends StatefulWidget { } class _ResultSearchState extends State<ResultFilter> { + List<Book2> jsonBook = []; + final SearchService searchService = SearchService(); + void initData() async { + print(widget.category); + final searchData = + (await searchService.getFilterPageData(widget.category)).data; + jsonBook = searchData.books; + + print(jsonBook); + // print(bookList); + + setState(() { + jsonBook = jsonBook; + }); + } + @override + void initState() { + super.initState(); + initData(); + } + Widget build(BuildContext context) { + Widget header() { + return Container( + alignment: AlignmentDirectional.topStart, + child: Row( + children: [ + Text( + 'Ensiklopedi.id', + style: titleText, + ), + const Spacer(), + ], + )); + } + //FITUR SEARCH Widget searchField() { return Row( @@ -165,6 +205,17 @@ class _ResultSearchState extends State<ResultFilter> { () => word = value, )), decoration: InputDecoration( + prefixIcon: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BottomNavbar())); + }, + child: Container( + padding: EdgeInsets.all(10), + child: Icon(Icons.arrow_back, color: Colors.black)), + ), hintText: 'Find your favorite books', fillColor: searchBackground, filled: true, @@ -193,7 +244,7 @@ class _ResultSearchState extends State<ResultFilter> { InkWell( onTap: () { Navigator.push(context, - MaterialPageRoute(builder: (context) => const FilterPage())); + MaterialPageRoute(builder: (context) => Filterpage())); }, child: Container( margin: const EdgeInsets.only(left: 10), @@ -207,70 +258,86 @@ class _ResultSearchState extends State<ResultFilter> { ); } - // ignore: non_constant_identifier_names - Widget ListResult() { - return SingleChildScrollView( - scrollDirection: Axis.vertical, - padding: const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: <Widget>[ - ElementBook( - image: 'assets/image/manager_path.jpg', - title: 'The Manager\'s Path', - author: bookList[1].author, - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/making-a-manager.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - ], - )); + // Widget ListResult() { + // return SingleChildScrollView( + // scrollDirection: Axis.vertical, + // padding: EdgeInsets.symmetric(horizontal: 0), + // child: Column( + // children: <Widget>[ + // ElementBook( + // image: 'assets/image/manager_path.jpg', + // title: 'The Manager\'s Path', + // author: bookList[1].author, + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/making-a-manager.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // ], + // )); + // } + + Widget ListResult2() { + return ListView.builder( + shrinkWrap: true, + padding: EdgeInsets.symmetric(horizontal: 0), + itemCount: jsonBook.length, + itemBuilder: (BuildContext context, int index) { + return ElementBook( + id: jsonBook[index].id, + image: bookList[index].cover, + title: jsonBook[index].title, + author: jsonBook[index].author, + category: widget.category, + rating: 3.8, + ); + }); } return Scaffold( @@ -293,7 +360,9 @@ class _ResultSearchState extends State<ResultFilter> { style: titleSearch, textAlign: TextAlign.left, )), - ListResult() + jsonBook.length == 0 + ? Center(child: Text("Kosong")) + : ListResult2() ], )), ], diff --git a/client/lib/components/screens/resultSearch/result_search.dart b/client/lib/components/screens/resultSearch/result_search.dart index 343934eb954726ea0a1793be46eec33bbc1b5522..8f2a3995bb1ff25188ae05acba0e1e6f92039fff 100644 --- a/client/lib/components/screens/resultSearch/result_search.dart +++ b/client/lib/components/screens/resultSearch/result_search.dart @@ -1,11 +1,13 @@ +import 'package:client/api_service/catalog_service.dart'; import 'package:client/components/screens/filter/filter_page.dart'; import 'package:client/components/screens/resultSearch/element_result.dart'; import 'package:client/model/book.dart'; +import 'package:client/screens/home/bottom_navbar.dart'; import 'package:client/styles.dart'; import 'package:flutter/material.dart'; -List<Book> bookList = [ - const Book( +const List<Book> bookList = [ + Book( id: 1, title: "Management Book", price: 10000, @@ -150,7 +152,46 @@ class ResultSearch extends StatefulWidget { } class _ResultSearchState extends State<ResultSearch> { + late ScrollController _controller; + _scrollListener() { + if (_controller.offset >= _controller.position.maxScrollExtent && + !_controller.position.outOfRange) { + setState(() { + //you can do anything here + }); + } + if (_controller.offset <= _controller.position.minScrollExtent && + !_controller.position.outOfRange) { + setState(() { + //you can do anything here + }); + } + } + + List<Book2> jsonBook = []; + final SearchService searchService = SearchService(); + void initData() async { + print(widget.query); + final searchData = + (await searchService.getSearchPageData(widget.query)).data; + jsonBook = searchData.books; + + print(jsonBook); + // print(bookList); + + setState(() { + jsonBook = jsonBook; + }); + } + @override + void initState() { + _controller = ScrollController(); + _controller.addListener(_scrollListener); //the listener for up and down. + super.initState(); + initData(); + } + Widget build(BuildContext context) { //FITUR SEARCH Widget searchField() { @@ -159,10 +200,21 @@ class _ResultSearchState extends State<ResultSearch> { children: <Widget>[ Flexible( child: TextField( - onSubmitted: (value) => (setState( + onChanged: (value) => (setState( () => word = value, )), decoration: InputDecoration( + prefixIcon: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BottomNavbar())); + }, + child: Container( + padding: EdgeInsets.all(10), + child: Icon(Icons.arrow_back, color: Colors.white)), + ), hintText: 'Find your favorite books', fillColor: searchBackground, filled: true, @@ -171,7 +223,14 @@ class _ResultSearchState extends State<ResultSearch> { borderRadius: BorderRadius.circular(15), borderSide: BorderSide.none), suffixIcon: InkWell( - onTap: () {}, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ResultSearch( + query: word, + ))); + }, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( @@ -186,7 +245,7 @@ class _ResultSearchState extends State<ResultSearch> { InkWell( onTap: () { Navigator.push(context, - MaterialPageRoute(builder: (context) => const FilterPage())); + MaterialPageRoute(builder: (context) => Filterpage())); }, child: Container( margin: const EdgeInsets.only(left: 10), @@ -200,70 +259,94 @@ class _ResultSearchState extends State<ResultSearch> { ); } - // ignore: non_constant_identifier_names - Widget ListResult() { - return SingleChildScrollView( - scrollDirection: Axis.vertical, - padding: const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: <Widget>[ - ElementBook( - image: 'assets/image/manager_path.jpg', - title: 'The Manager\'s Path', - author: bookList[1].author, - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/making-a-manager.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - const SizedBox(width: 20), - const ElementBook( - image: 'assets/image/effective-se.jpg', - title: 'The Manager\'s Path', - author: 'Camille Fournier', - category: 'Education', - rating: 4.8, - ), - ], - )); + Widget ResultElement() { + return Container( + child: Text('Element Result'), + ); + } + + // Widget ListResult() { + // return SingleChildScrollView( + // scrollDirection: Axis.vertical, + // padding: EdgeInsets.symmetric(horizontal: 0), + // child: Column( + // children: <Widget>[ + // ElementBook( + // image: 'assets/image/manager_path.jpg', + // title: 'The Manager\'s Path', + // author: bookList[1].author, + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/making-a-manager.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // SizedBox(width: 20), + // ElementBook( + // image: 'assets/image/effective-se.jpg', + // title: 'The Manager\'s Path', + // author: 'Camille Fournier', + // category: 'Education', + // rating: 4.8, + // ), + // ], + // )); + // } + + Widget ListResult2() { + return ListView.builder( + shrinkWrap: true, + controller: _controller, + padding: EdgeInsets.symmetric(horizontal: 0), + itemCount: jsonBook.length, + itemBuilder: (BuildContext context, int index) { + return ElementBook( + id: jsonBook[index].id, + image: bookList[index].cover, + title: jsonBook[index].title, + author: jsonBook[index].author, + // category: jsonBook[index].category[0], + category: jsonBook[index].category[0], + rating: 3.8, + ); + }); } return Scaffold( @@ -274,6 +357,7 @@ class _ResultSearchState extends State<ResultSearch> { padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 25), decoration: BoxDecoration(color: backgroundColor), child: Column( + verticalDirection: VerticalDirection.down, children: [ searchField(), Container( @@ -286,9 +370,11 @@ class _ResultSearchState extends State<ResultSearch> { style: titleSearch, textAlign: TextAlign.left, )), - widget.query == "" - ? const Text("Tidak ada Buku") - : ListResult() + jsonBook.length == 0 + ? SizedBox( + height: 700, + child: Center(child: Text("Tidak ada Buku"))) + : ListResult2() ], )), ], diff --git a/client/lib/model/book.dart b/client/lib/model/book.dart index 8b2ce4b34bfa7d1d7d4ca9ea9168e1883e42ca93..f945910bae2e2ddf040c7a0c916c34d7cd00a7bd 100644 --- a/client/lib/model/book.dart +++ b/client/lib/model/book.dart @@ -1,4 +1,4 @@ -import 'category.dart'; +import 'dart:ffi'; class Book { final String title; @@ -42,3 +42,82 @@ class Book { ); } } + +class Book2 { + final String title; + final int price; + final String author; + final String cover; + final bool IsOwned; + final int id; + final List<String> category; + + const Book2({ + required this.title, + required this.price, + required this.author, + required this.cover, + required this.IsOwned, + required this.id, + required this.category, + }); + + factory Book2.fromJson(Map<String, dynamic> json) { + List<String> categories = []; + dynamic categoriesJson = json["category"]; + for (int i = 0; i < categoriesJson.length; i++) { + categories.add((categoriesJson[i])); + } + return Book2( + title: json["title"], + price: json["price"], + author: json["author"], + cover: json["cover"], + IsOwned: json["isOwned"], + id: json["id"], + category: categories, + ); + // category: json["category"]); + } +} + +class Book3 { + final String title; + final int price; + final String author; + final String description; + final String cover; + final String content; + final int id; + final List<String> category; + + const Book3({ + required this.title, + required this.price, + required this.author, + required this.cover, + required this.description, + required this.content, + required this.id, + required this.category, + }); + + factory Book3.fromJson(Map<String, dynamic> json) { + List<String> categories = []; + dynamic categoriesJson = json["category"]; + for (int i = 0; i < categoriesJson.length; i++) { + categories.add((categoriesJson[i])); + } + return Book3( + title: json["title"], + price: json["price"], + author: json["author"], + cover: json["cover"], + content: json["content"], + description: json["description"], + id: json["id"], + category: categories, + ); + // category: json["category"]); + } +} diff --git a/client/lib/model/payment.dart b/client/lib/model/payment.dart new file mode 100644 index 0000000000000000000000000000000000000000..43b056bd300a640c4cafc1433703f416f5520c2a --- /dev/null +++ b/client/lib/model/payment.dart @@ -0,0 +1,17 @@ +class Metadata { + final String payment_method; + + const Metadata({required this.payment_method}); + + factory Metadata.fromJson(Map<String, dynamic> json) { + return Metadata( + payment_method: json["payment_method"], + ); + } +} + +class MetadataPost { + final String phone_number; + + const MetadataPost({required this.phone_number}); +} diff --git a/client/lib/screens/home/katalog/katalog_page.dart b/client/lib/screens/home/katalog/katalog_page.dart index e91ffe96e2519bd3d567e071105a41ecfb9ff3bd..77f4a5756740b95b984776c3bb1d11b722ebeb95 100644 --- a/client/lib/screens/home/katalog/katalog_page.dart +++ b/client/lib/screens/home/katalog/katalog_page.dart @@ -35,6 +35,7 @@ class _KatalogState extends State<Katalog> { var bookId = []; var jsonBookTitle_temp = []; var jsonOwned_temp = []; + String querySearch = ''; List<Collection> myItems = []; final CatalogService catalogService = CatalogService(); @@ -91,12 +92,19 @@ class _KatalogState extends State<Katalog> { )); } + void changeQuery(String value) { + setState(() { + querySearch = value; + }); + } + //FITUR SEARCH Widget searchField() { return Container( margin: const EdgeInsets.only(right: 0), height: 50, child: TextField( + onChanged: (value) => {changeQuery(value)}, decoration: InputDecoration( hintText: 'Find your favorite books', fillColor: searchBackground, @@ -110,8 +118,8 @@ class _KatalogState extends State<Katalog> { Navigator.push( context, MaterialPageRoute( - builder: (context) => const ResultSearch( - query: '', + builder: (context) => ResultSearch( + query: querySearch, ))); }, child: Container( diff --git a/client/lib/screens/payment/paymentPage.dart b/client/lib/screens/payment/paymentPage.dart new file mode 100644 index 0000000000000000000000000000000000000000..810138d35505c21a51ea9f60b405e26aa4c5ae5b --- /dev/null +++ b/client/lib/screens/payment/paymentPage.dart @@ -0,0 +1,326 @@ +// ignore_for_file: deprecated_member_use + +import 'package:client/constants.dart'; +import 'package:client/screens/home/bottom_navbar.dart'; +import 'package:client/styles.dart'; + +import 'package:flutter/material.dart'; + +class PaymentPage extends StatefulWidget { + const PaymentPage( + {Key? key, + // required this.index, + required this.buy, + required this.category, + required this.title, + required this.image, + required this.price, + required this.rating, + required this.author}) + : super(key: key); + + // final int index; + final bool buy; + final String category; + final String title; + final String image; + final int price; + final double rating; + final String author; + + @override + _DetailState createState() => _DetailState(); +} + +class _DetailState extends State<PaymentPage> { + // int get index => widget.index; + bool get buy => widget.buy; + String get category => widget.category; + String get title => widget.title; + String get image => widget.image; + int get price => widget.price; + double get rating => widget.rating; + String get author => widget.author; + + String phoneNumber = ''; + + void onChangePhone(String newValue) { + setState(() { + phoneNumber = newValue; + }); + // print(phoneNumber); + } + + void onClickBuy() { + if (phoneNumber == '') { + showDialog( + context: context, + builder: (BuildContext ctx) => AlertDialog( + title: const Text("Error"), + content: Text("Phone Number is Required."), + actions: <Widget>[ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: const Text("Ok")) + ], + )); + } else { + showDialog( + context: context, + builder: (BuildContext ctx) => AlertDialog( + title: const Text("Buy Success"), + content: Text("Your phone number is " + phoneNumber), + actions: <Widget>[ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: const Text("Ok")) + ], + )); + } + } + + @override + Widget build(BuildContext context) { + Widget payment() { + return ListView(children: [ + Container( + alignment: Alignment.center, + child: Column(children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.asset( + image, + width: 190, + )), + Container( + margin: const EdgeInsets.only(top: 20), + width: 250, + alignment: Alignment.center, + child: Text( + title, + maxLines: 2, + textAlign: TextAlign.center, + style: const TextStyle( + fontFamily: "Poppins", + fontSize: 14, + fontWeight: FontWeight.w600, + color: Color.fromARGB(255, 0, 0, 0)), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FittedBox( + alignment: Alignment.center, + // fit: BoxFit.contain, + child: Container( + margin: const EdgeInsets.only(top: 15), + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 13), + decoration: BoxDecoration( + color: blueLight, + borderRadius: BorderRadius.circular(20), + ), + child: Text( + category, + style: seeMoreText, + textAlign: TextAlign.center, + ))), + Container( + margin: const EdgeInsets.only(top: 10, left: 20), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: Image.asset("assets/icon/star.png", + width: 15)), + Text( + rating.toString(), + style: const TextStyle( + fontFamily: "Poppins", + fontSize: 12, + fontWeight: FontWeight.w600), + ), + ])), + ], + ), + Container( + margin: const EdgeInsets.only(top: 30), + padding: + const EdgeInsets.symmetric(vertical: 25, horizontal: 25), + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(25), + topRight: Radius.circular(25)), + boxShadow: const [ + BoxShadow( + color: Colors.black38, + spreadRadius: 0, + blurRadius: 1), + ], + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + "Total Payment", + style: TextStyle( + fontFamily: "Poppins", + fontSize: 16, + fontWeight: FontWeight.w700), + ), + buy == true + ? Text( + "You already have this!", + style: TextStyle( + fontFamily: "Poppins", + fontSize: 14, + fontWeight: FontWeight.w500, + color: blueDark), + ) + : price == 0 + ? Text( + "Free", + style: TextStyle( + fontFamily: "Poppins", + fontSize: 14, + fontWeight: FontWeight.w500, + color: blueDark), + ) + : Text( + "Rp" + price.toString() + ",-", + style: TextStyle( + fontFamily: "Poppins", + fontSize: 14, + fontWeight: FontWeight.w500, + color: blueDark), + ) + ], + ), + Container( + margin: const EdgeInsets.only(top: 30), + height: 325, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only( + bottom: 20, left: 40, right: 40), + child: Text( + "Are you sure you want to buy this book?", + style: paymentText, + textAlign: TextAlign.center, + ), + ), + Container( + width: 300, + margin: const EdgeInsets.only(bottom: 20), + child: TextField( + onChanged: onChangePhone, + decoration: InputDecoration( + errorText: + phoneNumber != '' ? null : "*Required", + hintText: "Phone Number", + hintStyle: + const TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color.fromARGB( + 255, 243, 241, 241), + width: 0)), + fillColor: const Color.fromARGB( + 255, 243, 241, 241), + filled: true), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(right: 5), + child: RaisedButton( + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 60), + shape: RoundedRectangleBorder( + side: BorderSide(color: blueDark), + borderRadius: + BorderRadius.circular(30.0), + ), + onPressed: () { + onClickBuy(); + }, + color: blueDark, + textColor: Colors.white, + child: Text('Buy now', + style: buttonPaymentText)), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: RaisedButton( + padding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 60), + shape: RoundedRectangleBorder( + side: BorderSide(color: blueDark), + borderRadius: + BorderRadius.circular(30.0), + ), + onPressed: () { + Navigator.pop(context); + }, + color: Colors.white, + textColor: + Color.fromRGBO(33, 150, 243, 1), + child: Text('Cancel', + style: buttonPaymentText)), + ) + ], + ) + ], + ), + ), + ], + )) + ])) + ]); + } + + return Scaffold( + backgroundColor: const Color(0xFFF9F8F8), + appBar: AppBar( + automaticallyImplyLeading: false, + toolbarHeight: 100, + backgroundColor: Colors.transparent, + elevation: 0, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 5, + child: Container( + alignment: Alignment.center, + child: Text( + "Confirm Payment", + textAlign: TextAlign.center, + maxLines: 2, + style: const TextStyle( + fontFamily: 'Poppins', + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + )), + ) + ], + )), + body: payment(), + ); // This trailing comma makes auto-formatting nicer for build method. + } +} diff --git a/client/lib/screens/splash/Splash.dart b/client/lib/screens/splash/Splash.dart index d1f57ed3048f35194aca132997643072c883e03c..5f6141f9b025c881d26f62a4d2e5d632df4eedcf 100644 --- a/client/lib/screens/splash/Splash.dart +++ b/client/lib/screens/splash/Splash.dart @@ -1,3 +1,5 @@ +import 'package:client/screens/payment/paymentPage.dart'; +import 'package:client/styles.dart'; // ignore_for_file: file_names import 'package:flutter/material.dart'; diff --git a/client/lib/styles.dart b/client/lib/styles.dart index f013356841f06f95dc11d60aed0a386d53b0ca2b..022dac223bfb761046eb6aec6628952992c074a1 100644 --- a/client/lib/styles.dart +++ b/client/lib/styles.dart @@ -52,4 +52,13 @@ TextStyle titleSearch = GoogleFonts.poppins( TextStyle textauthor = GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, + color: Color.fromARGB(125, 0, 0, 0)); + +TextStyle paymentText = GoogleFonts.poppins( + fontSize: 24, + fontWeight: FontWeight.w700, + color: Color.fromARGB(125, 0, 0, 0)); +TextStyle buttonPaymentText = GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, color: const Color.fromARGB(125, 0, 0, 0));