Final
Final
Final
The intention of this project was to develop a mobile e-commerce app. While developing this
platform, the present pandemic dilemma was borne in mind. After pondering about all these
concerns, it was determined to create a user-friendly e -commerce application that allows users to
make their life easier by purchasing online. The app was made utilizing Android Studio and the
flutter framework. For design purposes, GitHub was used. The application architecture was built
using the MVVM paradigm, which incorporates all the well-known provider patterns. The
databases were built with Google Firebase and were developed to authenticate current users or
allow customers to generate an id by signing up. The free source platforms were used to gather all
the product information. Further development ideas were also examined. The project launched
with only a rudimentary grasp of the dart language. Many obstacles and disappointments arose
along the road, all of which served as excellent learning opportunities. A better appreciation of
how to structure a redevelopment, how to better organize and manage the codebase, and what
incremental benefits can be gained by utilizing the flutter framework all seem to be vital insights.
TABLE OF CONTENTS
PAGE
S.NO CONTENT NO
1. Introduction
2. System Specification
2.1 Hardware specification
2.2 Software specification
2.3 Shopping Cart specification
System Analysis
3.1 About Flutter
3. 3.2 About Dart language
3.3 About Google FireBase
System Design
4.1 Use Case Diagram
4. 4.2 Class Diagram
4.3 Sequence Diagram
5 System Implementtion
6. Conclusion
7. Future Enhancement
8. Bibliography
Appendices
9. 9.1 Sample Code
9.2 Sample Screenshots
1.INTRODUCTION
In this thesis, the Flutter technology is utilized to develop an e-commerce mobile application. E -
commerce, or electronic commerce, is a technique of purchasing goods and services through the
internet that is growing in popularity and effectiveness for online businesses. Ecommerce offers a
number of benefits, the most significant of which is that it is inexpensive and convenient.
As a consequence, we may describe e-commerce as the process of buying and selling goods and
services through the internet, whether inside a country or across the globe. These companies have
their own mobile apps or websites where customers may explore a range of products and services.
They have a choice of payment alternatives if they purchase anything and need to pay for it,
including (credit card, debit card, PayPal). utilizing a website or a smartphone app the order is
shipped to the customer's address after confirmation. If required, customers can follow the status
of their orders. All of these things happen on the internet. (A Review of Narrative Literature of e-
commerce, 2017). This application's main purpose and goal is to empower and assist a person in
accessing e-commerce platforms so that they may do their own online shopping.
Purpose:
In recent years, online purchasing has become increasingly popular. People all around the world
prefer to buy things online rather than in stores, which is why Amazon and other similar online
retailers are not only successful but also increasing interest in online commerce. (Darrell, 2011).
In today's world, though, innovation is assisting us in breaking down some of these barriers by
using computer frameworks to aid us with various forms of labour. As we all know, the world of
online purchasing is quickly developing. As a result, e-commerce apps have already developed
various new tatics and technologies for giving information to individuals. These ideas and
technologies, however, provide a number of challenges and concerns for people.
Project Scope :
• Application must start when client clicks on app icon
• Application must show the home page of the application first
• Application must provide the selected category’s content list for the client
• Client must be able to view the products
• Client must be able to view the products image
• Application must provide the selected product’s description for the client
• Client must be able to add the product to the cart
• Application should add the product to the customer’s shopping cart.
• Application must provide the customer’s information form for the client.
• Client must send the provided credentials to the application.
Domain Study :
The history of e-commerce dates back more than 50 years, when early inventions such as EDI
(Electronic Data Interchange) and teleshopping were shown in the 1970s, paving the way for today's e-
commerce companies. The history of e-commerce is inextricably linked to the history of the internet.
When the internet was invented in the 1990s, online shopping became possible. Since then, Amazon
has become one of the most popular e-commerce sites in the United States, with hundreds of e-
commerce enterprises springing up as a result. (Every day online marketing, no date).
Michael Aldrich demonstrated e-shopping by connecting a phone connection to an adjustable TV
and a transaction-processing computer. (Aldricharchive, no date)
While desktop spending has remained stable throughout the year, the worldwide market for online
business transactions has grown at an annual rate of 33.7 percent since 2016. This happens as a
result of customers' continuous preparation with each screen tap.
The creation of mobile applications for e-commerce enterprises appears to be a long-term trend,
according to simple reasoning. Nothing suggests that the worldwide public will soon reject
smartphones. Diverse internet shopping, on the other hand, is predicted to reach $3.5 trillion by
2021. (Shopify, no date).
The e-Commerce business is experiencing the most notable growth of adaptable arrangements
being prompted by the need to meet client needs in the context of rising online sales. Customers
want the ability to purchase items and services at any time and from any location, without having
to travel. Customers choose various e -commerce applications or websites to purchase things
because they advance faster, give more comfort, and are more flexible.
For As a mobile application developer, it's important to remember the
distinctions between mobile development and more traditional software
development. Consider how varied the settings for utilizing mobile apps vs
desktop computers can be, for example, recognizing the constraints and
complexities of a touch-based user interface, and considering the unique security
vulnerabilities that mobile technologies provide. A mobile developer should also
be mindful of the importance of user experience and the fact that most users are
acclimated to a certain operating system's design guidelines.
Home Screen
As our Home screen has following categories Shirts, shoes, and purse. Every product is associated
with a specific category. We have made a dart file name as Angel_Home_Screen.Dart. In this file
our main home categories are managed. Then we make a file name as prepare_data. In this file we
make a class Data_View_Model.
As we use provider patterns for this application, so the main class extends change notifier. By
using this provider pattern listen about the list that are prepared in this class. When any change
occur in this class then it will notify to provider about change. Basically, this is the best thing in
providers for managing data in application.
Favourites
Adding to favorites is a prevalent feature in many applications. It enables the users to mark or save
images, addressed, links or others stuff for easy future reference. In this article, we are going to see
how to implement favorites or add to favorites feature in a flutter application. This article list two
methods to do so. In the first method, we will add a simple (stateless widget) icon that changes
color on tap, to mark a card for future reference. In the second example, we will be implementing
a comparatively complex favorite feature which will involve StateFul widgets, saving the data in a
set, and then displaying it on another screen.
Cart Screen:
In Add to cart screen we are using stateful widget. In Stateful widget we call its state. In Its state
we are using scaffold widget. Scaffold is a layout of our whole screen which gives us many things
like App Bar, Body and many more. We are using column widget to align in vertically direction.
In column we have a children. In Children we are using list view. In list view widget all the
selected items are arranged.
Session check also included in add to cart functionality. If a user login to their account, then its
session started then they will purchase product by using add to cart functionality. It is very good
practice to use session in purchasing points to authenticate user.
We are fetching a data in our list view which index marked as true. In every item in list view, we
are making edit and delete button. Below list view we are using elevation button to proceed to
checkout. Elevation button has a on tap functionality. We set checkout page path in on tap
functionality.
Order Screen:
In order screen, the FutureBuilder Widget is used to create widgets based on the latest snapshot
of interaction with a Future. It is necessary for Future to be obtained earlier either
through a change of state or change in dependencies. FutureBuilder is a Widget that will help
you to execute some asynchronous function and based on that function’s result your UI will
update. FutureBuilder is Stateful by nature i.e it maintains its own state as we do
in StatefulWidgets. And display the calculation of total amount among with DateTime.
Manage Product:
In this class we are managing our all products, categories as well as cart. We are managing all the
stuff in a single file in order to reduce no of files and optimization of code. In this class we make a
method for each functionality. In this class we make get purse function in order to get all products
in a purse. We make get shoe ad get shirts as well in a same logic. When we click, notifier note
the change and send to the listener that is call in init() function. Then home screen data index is
updated and across index specific category products are call and display in a home screen.
Logout:
When we press the logout button in the drawer it should logout and redirect to the register screen,
but users data will be saved the last login account. logout() async {
await auth.logut();
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LogOutScreen()));
}
2.SYSTEM SPECIFICATION
System specification is key information for programming, testing & implementing the project. The
specification should delineate the user requirements. It must reflect the actual application to be
handled by the system & include system objectives, flowcharts, input/output requirements, file
structure & cost. In addition, it also contains non-functional requirements. Non-functional
requirements impose constraints on the design or implementation (such as performance
engineering requirements, quality standards, or design constraints)
3.1 Flutter:
This application is built on Flutter technology. Flutter offers several advantages because it is
a Google product. The following is a quick overview of flutter.
The app development process is revolutionized by Flutter. You can design, test, and publish
stunning mobile, web, desktop, and embedded apps by writing one-time code. Google built Flutter
as an open-source project. It's used to make hybrid apps for Android, iOS, Linux, macOS,
Windows, Google Fuchsia, and the web from a single codebase. (Flutter, no date)
You can develop and iterate quickly using Hot Reload. You'll observe changes very immediately
after updating the code, with no loss of state. Maintain every pixel to create unique, responsive
designs that look and feel great on every device.
Every component in flutter is referred to as a widget. It is entirely widget based. Stateless or stateful
widgets are available. There are several states in a stateful widget, not just one. They have the ability to
modify their state in response to user interest. A Stateless widget, on the other hand, is a static widget
that is utilized for static data or functionality. It is devoid of any state. We need to utilize it in some
circumstances because we work with static data. (AppDividend, no date)
Flutter is an open-source project, anybody may use and contribute to it at any level. It's better to use it
and offer your passion for Google technology by becoming a Google contributor. Flutter has a massive
user base since it is a Google product, and Google is the most widely used search engine on the planet.
Flutter outperforms other hybrid solutions in terms of cost. It's one of the many advantages of flutter.
Flutter developers may encrypt app data with both asymmetric and symmetric keys using the iOS
SecKey API and the Common Crypto library. Flutter code is written in Dart, which has many cryptos
and encrypts libraries that employ various cryptographic hashing and encryption techniques.
3.2 Dart Language :
Dart is a client-oriented programming language that enables rapid app development across all
platforms. Its primary goal is to create one of the most productive languages on a variety of platforms.
Both the server and the user will benefit from it. The Dart SDK includes the Dart VM compiler as well
as the dart2js tool, which generates the JavaScript version of a Dart Script so that it may be executed
on sites that don't support Dart. It is a very similar object-oriented programming language to C++.
Dart is a popular programming language for
creating single-page websites and online apps. (Dart, no date).
Dart is designed to provide logic and, as a result, a beautiful user interface. For mobile, desktop, and
backend apps, compile specialized machine code. Alternatively, for web use, compile to JavaScript.
In the software Development Life Cycle, the output of the system requirement analysis phase can
be considered as an input to the system design phase. The architectural description of a System
with details about its components and sub components is called System design. The pictorial
description of the system, modules, and sub systems gives a proper overview of the system and its
design details. Through UML diagrams we specify and visualize various aspects of a System and
its architecture. Security, Reliability, being able to deliver desired output to end users based on
available resources and that the system is responsive and dynamically changes are some of the
important aspects ensured by the System Design.
6. Conclusion
Technology has made significant progress over the years to provide consumers a better online
shopping experience and will continue to do so for years to come. With the rapid growth of
products and brands, people have speculated that online shopping will overtake in-store shopping.
While this has been the case in some areas, there is still demand for brick and mortar stores in
market areas where the consumer feels more comfortable seeing and touching the product being
bought. However, the availability of online shopping has produced a more educated consumer that
can shop around with relative ease without having to spend a large amount of time. In exchange,
online shopping has opened up doors to many small retailers that would never be in business if
they had to incur the high cost of owning a brick and mortar store. At the end, it has been a win-
win situation for both consumer and sellers.
7.Future scope
Online purchasing has grown increasingly popular in recent years. People all over the world prefer
to purchase online rather than go to the store, which is why Amazon and other similar online stores
are not only profitable but also generating interest in online business. Many new strategies and
technologies have been created in e-commerce apps to offer users with information. Online
commerce is experiencing considerable development all around the world.
We've provided answers, but they'll need some time and resources. This App will provide users
with modules to help them with their task. The player's major goal in building the app was to
prioritize quality above quantity. As previously indicated, more modules and functionality will be
introduced soon to make the program more solid and adaptable.
The primary goal and aim of this program are to enable and assist people in using an e -commerce-
based platform, which is widely utilized throughout the world for online shopping and purchase of
commodities and products nowadays. As a result, individuals may enjoy, conveniently access, and
purchase all things through internet shopping and feel fully integrated into society. Our effort will
not end here; we will continue to improve the software and provide new features for those who are
unable to perceive the world from any angle (completely blind people). We'll aim to include a
feature that makes this app totally accessible to blind people; they'll be able to control it with their
voice and dress themselves according to their preferences. We'll be adding additional features as
time goes on.
8.Bibliography
Login Screen:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/auth.dart';
import '../models/http_exception.dart';
return Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xffe44f28),
Color(0x66e44f28),
Color(0xcce44f28),
Color(0xffe44f28),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.only(bottom: 5.0),
padding: EdgeInsets.symmetric(
vertical: 10, horizontal: 90.0),
child: Image(
image: AssetImage('assets/images/logo.png'),
)),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
// const AuthCard({
// Key key,
// }) : super(key:
key); @override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard>
with SingleTickerProviderStateMixin {
final GlobalKey<FormState> _formKey =
GlobalKey(); AuthMode _authMode =
AuthMode.Login; Map<String, String> _authData = {
'email': '',
'password':
'', };
var _isLoading = false;
final _passwordController =
TextEditingController(); //animation
late AnimationController _controller; late
Animation<Offset> _slideAnimation; late
Animation<double> _opacityAnimation;
@override
void initState() {
super.initState();
_controller =
AnimationController( vsync: this,
duration: Duration(
milliseconds: 300,
),
);
_slideAnimation = Tween<Offset>(begin: Offset(0, -1.5), end: Offset(0, 0))
.animate(
CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn));
_opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
),
);
// _heightAnimation.addListener(() => setState(() {}));
}
@override
void dispose() {
// TODO: implement dispose
_controller.dispose();
super.dispose();
}
void _showErrorDialog(String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('An error occured!'),
content: Text(message),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Okay'))
],
));
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
_controller.forward();
} else {
setState(() {
_authMode =
AuthMode.Login; });
_controller.reverse();
}
}
@override
Widget build(BuildContext context) {
final deviceSize =
MediaQuery.of(context).size; return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeIn,
height: _authMode == AuthMode.Signup ? 320 : 260,
// height: _heightAnimation.value.height,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
// BoxConstraints(minHeight: _heightAnimation.value.height),
width: deviceSize.width * 0.75,
padding: EdgeInsets.all(16.0),
child: Form( key:
_formKey,
child: SingleChildScrollView( child:
Column(
children: <Widget>[
TextFormField(
'E-Mail',
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('@'))
{ return 'Invalid email!';
}
return
null; },
onSaved: (value) {
_authData['email'] = value!;
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value!.isEmpty || value.length < 5)
{ return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value!;
},
),
// if (_authMode == AuthMode.Signup)
AnimatedContainer(
constraints: BoxConstraints(
minHeight: _authMode == AuthMode.Signup ? 60 : 0,
maxHeight: _authMode == AuthMode.Signup ? 120 :
0), duration: Duration(milliseconds: 300),
curve: Curves.easeIn,
child: FadeTransition( opacity:
_opacityAnimation, child:
SlideTransition(
position: _slideAnimation,
child: TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration:
InputDecoration(labelText: 'Confirm
Password'), obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
),
),
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
Container(
width: double.infinity,
child: TextButton(
child: Text(
_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.deepOrange,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5))),
),
onPressed: _submit,
),
),
Container(
width: double.infinity,
child: TextButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} '),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.deepOrange,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5))),
),
onPressed: _switchAuthMode,
),
),
],
),
),
),
),
);
}
}
Home Screen:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/app_drawer.dart';
import '../widgets/products_grid.dart';
import '../widgets/badge.dart';
import '../providers/cart.dart';
import '../screens/cart_screen.dart';
import '../screens/cart_screen.dart';
import '../providers/products.dart';
enum FilterOptions {
Favorite,
All,
}
class ProductsOverviewScreen extends StatefulWidget
{ @override
State<ProductsOverviewScreen> createState() => _ProductsOverviewScreenState();
}
class _ProductsOverviewScreenState extends State<ProductsOverviewScreen>
{ var _showOnlyFavorites = false;
var _isInit = true;
var _isLoading = false;
@override
void initState() {
// TODO: implement initState
// Provider.of<Products>(context).fetchAndSetProducts(); this wont
work super.initState();
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
if (_isInit) {
setState(() {
_isLoading = true;
});
Provider.of<Products>(context).fetchAndSetProducts().then((_)
{ setState(() {
_isLoading =
false; });
});
}
_isInit = false;
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('MyShop'),
actions: [
PopupMenuButton(
onSelected: (FilterOptions selectedValue) {
setState(() {
if (selectedValue == FilterOptions.Favorite) {
_showOnlyFavorites = true;
} else {
_showOnlyFavorites = false;
}
});
},
icon: Icon(Icons.more_vert),
itemBuilder: (_) => [
PopupMenuItem(
child: Text('Only Favorite'),
value: FilterOptions.Favorite,
),
PopupMenuItem(
child: Text('Show All'),
value: FilterOptions.All,
),
],
),
Consumer<Cart>(
builder: (_, cart, ch) => Badge(
value: cart.itemCount.toString(),
child: ch!,
),
child: IconButton(
icon: Icon(
Icons.shopping_cart,
),
onPressed: () {
Navigator.of(context).pushNamed(CartScreen.routeName);
},
),
),
],
),
drawer: AppDrawer(),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: ProductsGrid(_showOnlyFavorites),
);
}
}
Cart Screen:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/cart_item.dart';
import '../providers/cart.dart' show Cart;
import '../providers/orders.dart';
class CartScreen extends StatelessWidget {
static const routeName = '/cart';
@override
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(
title: Text('Your Cart'),
),
body: Column(children: [
Card(
margin: EdgeInsets.all(15),
child: Padding(
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total',
style: TextStyle(fontSize: 20),
),
Spacer(),
Chip(
label: Text(
'\₹${cart.totalAmount.toStringAsFixed(2)}',
style: TextStyle(color: Colors.white),
),
backgroundColor:
Theme.of(context).primaryColor, ),
// TextButton(
// onPressed: () {
// Provider.of<Orders>(context, listen: false).addOrder(
// cart.items.values.toList(),
// cart.totalAmount,
// );
// cart.clear();
// },
// child: Text('Order Now'))
]),
),
),
SizedBox(
height: 10,
),
Expanded(
child: ListView.builder(
itemCount: cart.items.length,
itemBuilder: ((context, index) => CartItem(
cart.items.values.toList()[index].id,
cart.items.keys.toList()[index],
cart.items.values.toList()[index].title,
cart.items.values.toList()[index].quantity,
cart.items.values.toList()[index].price))),
),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: cart.totalAmount <= 0
? null :(){
Provider.of<Orders>(context, listen:
false).addOrder( cart.items.values.toList(),
cart.totalAmount,
);
cart.clear();
},
child: Text('Order Now'),
),
),
],
)
]),
);
}
}
Order Screen :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/orders.dart' show Orders;
import '../widgets/order_item.dart';
import '../widgets/app_drawer.dart';
@override
Widget build(BuildContext context) {
final ordersData =
Provider.of<Orders>(context); return Scaffold(
appBar: AppBar(title: Text('Your Orders')),
drawer: AppDrawer(),
body: ListView.builder(
itemCount: ordersData.orders.length,
itemBuilder: ((context, index) => OrderItem(ordersData.orders[index])),
),
);
}
}
UserProduct Screen :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/products.dart';
import '../widgets/user_product_item.dart';
import '../widgets/app_drawer.dart';
import '../screens/edit_product_screen.dart';
AppBar(
IconButton(
onPressed: () {
Navigator.of(context).pushNamed(EditProductScreen.routeName);
},
icon: Icon(Icons.add))
],
),
drawer: AppDrawer(),
body: FutureBuilder(
future: _refershProducts(context),
builder: (ctx, snapshot) =>
snapshot.connectionState == ConnectionState.waiting
? Center(
child: CircularProgressIndicator(),
)
: RefreshIndicator(
onRefresh: () => _refershProducts(context),
child: Consumer<Products>(
builder: (ctx, productsData, _) => Padding(
padding: EdgeInsets.all(8),
child: ListView.builder(
itemCount: productsData.items.length,
itemBuilder: (_, index) => Column(
children: [
UserProductItem(
productsData.items[index].id,
productsData.items[index].title,
productsData.items[index].imageUrl,
),
Divider()
],
),
),
),
),
),
),
);
}
}
super.initState();
}
@override
void dispose() {
_priceFocusNode.dispose();
_descriptionFocusNode.dispose();
_imageUrlController.dispose();
_imageUrlFocusNode.dispose();
_imageUrlFocusNode.removeListener(_updateImageUrl);
super.dispose();
}
void _updateImageUrl() {
if (!_imageUrlFocusNode.hasFocus) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Product'),
actions: [
IconButton(
onPressed: _saveForm,
icon: Icon(Icons.save),
),
],
),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: Padding(
padding: EdgeInsets.all(17),
child: Form(
key: _form,
child: ListView(
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'Title',
),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_priceFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'Please provide a value';
}
return null;
},
onSaved: (String? value) {
_editedProduct = Product(
id: '',
title: value!,
description: _editedProduct.description,
price: _editedProduct.price,
imageUrl: _editedProduct.imageUrl);
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Price'),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
focusNode: _priceFocusNode,
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_descriptionFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'Please enter the price';
}
if (double.tryParse(value) == null) {
return 'Please enter a valid number';
}
if (double.parse(value) <= 0) {
return 'please enter a number greater than Zero';
}
},
onSaved: (String? value) {
_editedProduct = Product(
id: '',
title: _editedProduct.title,
description: _editedProduct.description,
price: double.parse(value!),
imageUrl: _editedProduct.imageUrl);
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Description'),
maxLines: 3,
keyboardType: TextInputType.multiline,
focusNode: _descriptionFocusNode,
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a description';
}
if (value.length < 10) {
return 'Should be at least 10 characters long.';
}
return null;
},
onSaved: (String? value) {
_editedProduct = Product(
id: '',
title: _editedProduct.title,
description: value!,
price: _editedProduct.price,
imageUrl: _editedProduct.imageUrl);
},
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(
top: 8,
right: 10,
),
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey),
),
child: _imageUrlController.text.isEmpty
? Text('Enter a URl')
: FittedBox(
child: Image.network(
),
),
),
Expanded(
child: TextFormField(
decoration:
InputDecoration(labelText: 'Image URL'),
keyboardType: TextInputType.url,
textInputAction: TextInputAction.done,
onEditingComplete: () {
setState(() {});
},
controller: _imageUrlController,
focusNode: _imageUrlFocusNode,
onFieldSubmitted: (_) {
_saveForm();
},
onSaved: (String? value) {
_editedProduct = Product(
id: '',
title: _editedProduct.title,
description: _editedProduct.description,
price: _editedProduct.price,
imageUrl: value!);
},
validator: (value) {
if (value!.isEmpty) {
return 'Please enter an image URL.';
}
if (!value.startsWith('http') &&
!value.startsWith('https')) {
return 'Please enter a valid URL.';
}
// if (!value.endsWith('.png') &&
// !value.endsWith('.jpg') &&
// !value.endsWith('.jpeg')) {
// return 'Please enter a valid image URL.';
// }
return null;
}),
),
],
)
],
)),
),
);
}
}
9.2 Sample Screenshot :
Login Screen:
SignUp Screen:
Product Overview Screen:
Order Screen:
SideDrawer Screen: