diff --git a/assets/profile_pic.jpg b/assets/profile_pic.jpg new file mode 100644 index 0000000..00f1a6d Binary files /dev/null and b/assets/profile_pic.jpg differ diff --git a/lib/add_book_screen.dart b/lib/add_book_screen.dart new file mode 100644 index 0000000..4787d44 --- /dev/null +++ b/lib/add_book_screen.dart @@ -0,0 +1,103 @@ + +import 'package:book_store_app/book.dart'; +import 'package:book_store_app/input_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class AddBookScreen extends StatefulWidget { + const AddBookScreen({Key? key}) : super(key: key); + + @override + State createState() => _AddBookScreenState(); +} + +class _AddBookScreenState extends State { + TextEditingController bookNameCon = TextEditingController(); + + TextEditingController authorNameCon = TextEditingController(); + + TextEditingController priceCon = TextEditingController(); + + TextEditingController imageLinkCon = TextEditingController(); + + TextEditingController descriptionCon = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xfffdfdfd), + appBar: AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new), + onPressed: () => Navigator.of(context).pop(), + ), + iconTheme: const IconThemeData( + ), + actions: const [ + Padding( + padding: EdgeInsets.only(right: 20), + child: Icon(Icons.more_vert,size: 30,)) + ], + toolbarHeight: 110, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark + ), + backgroundColor: const Color(0xfffdfdfd), + elevation: 0, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: ListView( + children: [ + const Padding( + padding: EdgeInsets.only(bottom: 40), + child: Text( "Add Book", + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold + ), + ), + ), + InputField(hint: "Book Name",numberOfLines: 1,controller: bookNameCon,), + InputField(hint: "Author Name",numberOfLines: 1,controller: authorNameCon,), + InputField(hint: "Price",numberOfLines: 1,controller: priceCon,), + InputField(hint: "Image Link",numberOfLines: 1,controller: imageLinkCon,), + InputField(hint: "Description",numberOfLines: 4,controller: descriptionCon,), + + TextButton(onPressed: () { + Book.add( + bookName: bookNameCon.text, + authorName: authorNameCon.text, + price: priceCon.text, + bookImage: imageLinkCon.text, + description: descriptionCon.text, + ); + + Navigator.pop(context); + }, + child: Container( + alignment: Alignment.center, + width: 300, + height: 70, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(20) + ), + child: Text("Add", + style: TextStyle( + color: Colors.white, + fontSize: 18 + ), + ), + ) + + ) + ], + ), + ) + ); + } +} + + diff --git a/lib/book.dart b/lib/book.dart new file mode 100644 index 0000000..48359a5 --- /dev/null +++ b/lib/book.dart @@ -0,0 +1,56 @@ + + +import 'dart:ffi'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class Book{ + final String bookName ; + final String authorName; + final String price; + final ImageProvider bookImage; + final String description; + bool isBought = false; + int rate = random.nextInt(2) + 3; + + + + Book({required this.bookName, required this.authorName, required this.price,required this.bookImage, required this.description}); + + + + static Random random = Random(); + static RxList library = [].obs; + static RxString search = "".obs; + + + static add({required bookName, required authorName, required price,required bookImage, required description}){ + bookImage = NetworkImage(bookImage); + library.add(Book(bookName: bookName, authorName: authorName, price: price, bookImage: bookImage, description: description)); + } + + + static List returnLibrary (bool allBooks){ + if(allBooks == false){ + return library.where((p) => p.isBought == true).toList(); + } + else{ + return library.where((e) => e.bookName.contains(Book.search)).toList(); + } + + } + +} + + +/* +* Book( + bookName: "bookName", + authorName: "authorName", + price: "99.99", + bookImage: NetworkImage("https://d1csarkz8obe9u.cloudfront.net/posterpreviews/yellow-business-leadership-book-cover-design-template-dce2f5568638ad4643ccb9e725e5d6ff.jpg?ts=1637017516"), + description: "fffffffffffffffff" + ) +* */ \ No newline at end of file diff --git a/lib/book_details_screen.dart b/lib/book_details_screen.dart new file mode 100644 index 0000000..e082d74 --- /dev/null +++ b/lib/book_details_screen.dart @@ -0,0 +1,192 @@ +import 'package:book_store_app/main.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'book.dart'; + +class BookDetailsScreen extends StatelessWidget { + const BookDetailsScreen({Key? key, required this.book}) : super(key: key); + + final Book book; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xfffdfdfd), + appBar: AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new), + onPressed: () => Navigator.of(context).pop(), + ), + iconTheme: const IconThemeData( + ), + actions: const [ + Padding( + padding: EdgeInsets.only(right: 20), + child: Icon(Icons.more_vert,size: 30,)) + ], + toolbarHeight: 100, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark + ), + backgroundColor: const Color(0xfffdfdfd), + elevation: 0, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + + children: [ + Center( + child: Container( + margin: EdgeInsets.only(bottom: 10), + width: 200, + height: 250, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + image: DecorationImage(image: book.bookImage,fit: BoxFit.fill) + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 10,bottom: 10), + child: Text("${book.bookName}", + style: TextStyle( + color: Color(0xff535458), + fontWeight: FontWeight.bold, + fontSize: 24 + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text("${book.authorName}", + style: TextStyle( + color: Color(0xffc8c8c9) + ), + ), + ), + Container( + margin: EdgeInsets.only(bottom: 10), + width: 160, + child: Row( + children: [ + Stars(value: book.rate,), + SizedBox(width: 10,), + Text("${book.rate}",style: TextStyle(fontWeight: FontWeight.bold),), + Text("/5",style: TextStyle(color: Colors.grey),) + ], + ) + ), + Container( + width: double.maxFinite, + height: 100, + child: Text("${book.description}", + style: TextStyle( + color: Color(0xff9e9ea0) + ), + ), + ), + Container( + height: 150, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Container( + width: 150, + height: 50, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Color(0xfff9f9f9), + boxShadow: [ + BoxShadow( + color: Colors.black38.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 5), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon(Icons.view_list,size: 30,), + Text("Preview",style: TextStyle(fontWeight: FontWeight.bold),) + + ], + ), + ), + Container( + width: 150, + height: 50, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Color(0xfff9f9f9), + boxShadow: [ + BoxShadow( + color: Colors.black38.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 5), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon(Icons.reviews_rounded,size: 30,), + Text("Review",style: TextStyle(fontWeight: FontWeight.bold),) + + ], + ), + ), + + ], + ), + GestureDetector( + onTap: (){ + book.isBought = true; + Navigator.pop(context); + + }, + child: Container( + margin: EdgeInsets.only(top: 30), + alignment: Alignment.center, + width: 320, + height: 70, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(20) + ), + child: Text(r"Buy Now for $""${book.price}", + style: TextStyle( + color: Colors.white, + fontSize: 18 + ), + ), + ), + ) + ], + + ), + ) + ], + ), + ), + ); + } +} + + +/* +* + margin: EdgeInsets.only(right: 20), + width: 300, + height: 350, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + image: DecorationImage(image: book.bookImage,fit: BoxFit.fill) + ), + +* */ \ No newline at end of file diff --git a/lib/book_view_list.dart b/lib/book_view_list.dart new file mode 100644 index 0000000..35617f5 --- /dev/null +++ b/lib/book_view_list.dart @@ -0,0 +1,89 @@ + +import 'package:book_store_app/book.dart'; +import 'package:book_store_app/book_details_screen.dart'; +import 'package:book_store_app/main.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class BookViewList extends StatelessWidget { + const BookViewList({Key? key, required this.allBooks,}) : super(key: key); + + final bool allBooks; + + @override + Widget build(BuildContext context) { + + return Expanded( + child: Obx(() { + return ListView( + padding: const EdgeInsets.only(bottom: 100), + + children: Book.returnLibrary(allBooks).map((e) => GestureDetector( + onTap: (){ + Navigator.push( + context, + MaterialPageRoute(builder: (context) => BookDetailsScreen(book: e,)), + + ); + }, + child: BookVeiwCard(book: e) + )).toList(), + ); + } + ), + ); + } +} + +class BookVeiwCard extends StatelessWidget { + const BookVeiwCard({Key? key, required this.book,}) : super(key: key); + final Book book; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(bottom: 20), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 20), + width: 100, + height: 150, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + image: DecorationImage(image: book.bookImage,fit: BoxFit.fill) + ), + ), + Container( + height: 140, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("${book.bookName}", + style: TextStyle( + color: Color(0xff535458), + fontWeight: FontWeight.bold, + fontSize: 20 + ), + ), + Text("${book.authorName}", + style: TextStyle( + color: Color(0xffc8c8c9) + ), + ), + Text(r"$""${book.price}", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15 + ), + ), + Stars(value: book.rate,) + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/cart_screen.dart b/lib/cart_screen.dart new file mode 100644 index 0000000..6d9dd07 --- /dev/null +++ b/lib/cart_screen.dart @@ -0,0 +1,53 @@ +import 'package:book_store_app/book_view_list.dart'; +import 'package:book_store_app/floating_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class CartScreen extends StatelessWidget { + const CartScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xfffdfdfd), + appBar: AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new), + onPressed: () => Navigator.of(context).pop(), + ), + iconTheme: const IconThemeData( + ), + actions: const [ + Padding( + padding: EdgeInsets.only(right: 20), + child: Icon(Icons.more_vert,size: 30,)) + ], + toolbarHeight: 110, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark + ), + backgroundColor: const Color(0xfffdfdfd), + elevation: 0, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(bottom: 30), + child: Text('Cart', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold + ),), + ), + BookViewList(allBooks: false,), + FloatingBar(iconCondition: false,), + ], + ), + ), + ); + } +} diff --git a/lib/floating_bar.dart b/lib/floating_bar.dart new file mode 100644 index 0000000..8d68f30 --- /dev/null +++ b/lib/floating_bar.dart @@ -0,0 +1,77 @@ + +import 'package:book_store_app/add_book_screen.dart'; +import 'package:book_store_app/book.dart'; +import 'package:book_store_app/cart_screen.dart'; +import 'package:book_store_app/main.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class FloatingBar extends StatefulWidget { + const FloatingBar({Key? key, required this.iconCondition,}) : super(key: key); + final bool iconCondition; + + @override + State createState() => _FloatingBarState(); +} + +class _FloatingBarState extends State { + @override + Widget build(BuildContext context) { + return Align( + alignment: Alignment.bottomCenter, + child: Container( + width: 220, + height: 70, + margin: EdgeInsets.only(bottom: 40), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Color(0xfff9f9f9), + boxShadow: [ + BoxShadow( + color: Colors.black38.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 5), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + GestureDetector( + onTap: (){ + Book.search.value = ""; + Navigator.push( + context, + MaterialPageRoute(builder: (context) => MyApp()), + ); + }, + child: Icon(Icons.home_outlined, size: 30,color: (widget.iconCondition)? Colors.black : Colors.grey,) + ), + GestureDetector( + onTap: (){ + Book.search.value = ""; + Navigator.push( + context, + MaterialPageRoute(builder: (context) => CartScreen()), + + ); + }, + child: Icon(Icons.shopping_cart_outlined, size: 26,color: (!widget.iconCondition)? Colors.black : Colors.grey) + ), + GestureDetector( + onTap: (){ + Book.search.value = ""; + Navigator.push( + context, + MaterialPageRoute(builder: (context) => AddBookScreen()), + + ); + }, + child: Icon(Icons.add, size: 30,color: Colors.grey,) + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/input_field.dart b/lib/input_field.dart new file mode 100644 index 0000000..3ad7814 --- /dev/null +++ b/lib/input_field.dart @@ -0,0 +1,43 @@ + +import 'package:flutter/material.dart'; + +class InputField extends StatefulWidget { + const InputField({Key? key, required this.numberOfLines, required this.hint, required this.controller,}) : super(key: key); + + final int numberOfLines; + final String hint; + final TextEditingController controller; + + @override + State createState() => _InputFieldState(); +} + +class _InputFieldState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(right: 20, left: 20, bottom: 20), + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black38.withOpacity(0.05), + blurRadius: 20, + offset: const Offset(0, -10), + ), + ], + ), + child: TextField( + controller: widget.controller, + maxLines: widget.numberOfLines, + style: TextStyle(fontSize: 18,), + decoration: InputDecoration( + border: UnderlineInputBorder(borderSide: BorderSide.none,borderRadius: BorderRadius.circular(8)), + hintText: '${widget.hint}', + fillColor: Colors.white, + filled: true, + ), + ), + ); + } +} + diff --git a/lib/main.dart b/lib/main.dart index bcc58f7..326d60d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,10 @@ +import 'package:book_store_app/book_view_list.dart'; +import 'package:book_store_app/floating_bar.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'profile_row.dart'; +import 'search_text_field.dart'; +import 'dart:math'; void main() { runApp(const MyApp()); @@ -9,12 +15,64 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return const MaterialApp( + return MaterialApp( home: Scaffold( - body: Center( - child: Text("Book Store App"), + backgroundColor: const Color(0xfffdfdfd), + appBar: AppBar( + toolbarHeight: 20, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark + ), + backgroundColor: const Color(0xfffdfdfd), + elevation: 0, + ), + body: Stack( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ProfileRow(), + SearchTextField(), + Container( + margin: EdgeInsets.only(top: 30,bottom: 30), + child: Text('Book List', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold + ),), + ), + BookViewList(allBooks: true,), + ], + ), + ), + FloatingBar(iconCondition: true,) + ], ), ), ); } } + + +class Stars extends StatelessWidget { + const Stars({Key? key, required this.value}) : super(key: key); + final int value; + + @override + Widget build(BuildContext context) { + return Row( + children: List.generate(5, (index) { + if (index < value) { + return Icon(Icons.star, color: Color(0xffffc628)); + } + else { + return Icon(Icons.star, color: Colors.grey.withOpacity(0.2)); + } + + }), + ); + } +} diff --git a/lib/profile_row.dart b/lib/profile_row.dart new file mode 100644 index 0000000..6a89d56 --- /dev/null +++ b/lib/profile_row.dart @@ -0,0 +1,38 @@ + +import 'package:flutter/material.dart'; + +class ProfileRow extends StatelessWidget { + const ProfileRow({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(top: 10,bottom: 30), + child: Row( + children: [ + Container( + height: 60, + width: 60, + margin: const EdgeInsets.only(right: 10), + decoration: BoxDecoration( + image: const DecorationImage(image: AssetImage('assets/profile_pic.jpg')), + borderRadius: BorderRadius.circular(10), + ), + ), + + const Expanded( + child: Text("Hi, Ali", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16 + ), + ) + ), + const Icon(Icons.more_vert), + ], + ), + ); + } +} diff --git a/lib/search_text_field.dart b/lib/search_text_field.dart new file mode 100644 index 0000000..caa46db --- /dev/null +++ b/lib/search_text_field.dart @@ -0,0 +1,42 @@ + +import 'package:book_store_app/book.dart'; +import 'package:flutter/material.dart'; + +class SearchTextField extends StatefulWidget { + const SearchTextField({Key? key,}) : super(key: key); + + @override + State createState() => _SearchTextFieldState(); +} + +class _SearchTextFieldState extends State { + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black38.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 5), + ), + ], + ), + child: TextField( + + onChanged: (x){ + Book.search.value = x; + }, + controller: TextEditingController(), + style: TextStyle(fontSize: 18), + decoration: InputDecoration( + border: UnderlineInputBorder(borderSide: BorderSide.none,borderRadius: BorderRadius.circular(8)), + hintText: 'Search ..', + suffixIcon: Icon(Icons.search,size: 30,color: Color(0xffa1a4b5),), + fillColor: Colors.white, + filled: true, + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 7bc8bdd..62f34da 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -74,6 +74,13 @@ packages: description: flutter source: sdk version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.5" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cd0f457..7af4bcc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ dependencies: flutter: sdk: flutter + get: any + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -39,6 +41,7 @@ dev_dependencies: flutter_test: sdk: flutter + # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your @@ -51,6 +54,8 @@ dev_dependencies: # The following section is specific to Flutter packages. flutter: + assets: + - assets/profile_pic.jpg # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in