How can we integrate Flutter with .Net core web API | Part-2: Building the Flutter App.
Tags: flutter, dotnet
Published: 2021-05-05 20:19:04

The application simply do the following activities.
  * Displaying the Services on the main screen
  * Showing the detail of every service listed on the main screen
  * It will have edit option for every service
  * It will have a delete option for every service.
	
This is the main page of the application that will display the services lists.

 ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jifed0suf77u8smf7tp8.jpg)

and this is the service add and update page. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihra9rt4nsln492l04bv.jpg)

and this one is the service detail page on this page we can delete and edit the single service. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tleievj5ue80lbqai68o.jpg)

so here we will follow some steps to buildthis application. 

#**Pre requests**

**1.Installing Android studio**
**2.Installing Flutter and dart**


**Step 1: Creating a new Flutter Project from an android studio or visual studio code.**
From the android studio go to **File** and click on the **New** then select **New Flutter Project** option.  

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owawad4pcvufnkg7mrzt.png)

Then you will get the following page. 
Click on the **Flutter Application** and click on the Next button

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kangr8oopcv4vuzd5gyi.png)
then here give the application a new name. and click on the Next button. 
 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2be3o6bvhf9wnie2n4z.png)
Then click on the Finish button at the bottom. 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xle1mlgswt010276ls8.png)
here we get a default code. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sbap92ztu7qhjekif4qy.png)

First, we should prepare a debugging emulator or connect our phone. and it will come at the top.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isoc0vzbjw6uzy41zvfm.png)
 
 after that click on the green run button at the top. you will get this page on the emulator. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj5qpg31uzgrcdxko4z3.jpg)

leave this code, for now, we will update it later. 
now create a new directory called **Service**  inside the **lib** package and inside this directory create the following directories.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rsjdhoeqlo8zu9p849rl.png)

Let us see step by step the code insides these directories.

#**What is Bloc State Management?**
**Bloc Overview**

Overall, Bloc attempts to make state changes predictable by regulating when a state change can occur and enforcing a single way to change state throughout an entire application.

Below are common developer needs that Bloc tries to address

* Working as efficiently as possible and reuse components both within your application and across other applications.
* Letting many developers to seamlessly work within a single code base
* following the same patterns and conventions Developing fast and reactive apps
* knowing what state your application is in at any point in time
* Easily testing every case to make sure our app is responding
appropriately
* Recording every single user interaction in your application so that you can make data-driven decisions

**Installing and Importing Bloc package**

*Installation*
Add the flutter_bloc package to your **pubspec.yaml** as a dependency

*dependencies:*
 *flutter_bloc: ^6.1.1*

*Import*
```dart
import 'package:flutter_bloc/flutter_bloc.dart';
```

**Bloc Architecture**

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxgg44hhua0kyub3w8e2.png)

**Bloc Architecture: Data Layer**

The data layer's responsibility is to retrieve/manipulate data from one or more sources The data layer can be split into two parts
     *Repository*
     *Data Provider*
This layer is the lowest level of the application and interacts with databases, network requests, and other asynchronous data sources

**Bloc Architecture: Data Layer -> Data Provider**

The data provider's responsibility is to provide raw data. It should be generic and versatile and it will usually expose simple APIs to perform CRUD operations. We might have a *createData*, *readData*, *updateData*, and *deleteData* method as part of our data layer.

Inside the **DataProvider** directory create the following two dart files.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cp5m1ca7ipj7jfx6psu2.png)
 
**Service_data.dart**

then inside the Service_data.dart file first add the necessary imports. 

```dart
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter_group_project/Service/Model/Service.dart';
import 'package:meta/meta.dart';
import 'package:http/http.dart' as HTTP;
```
create a class called **ServiceDataProvider**

```dart
class ServiceDataProvider {

}
```
then inside this class first define the **Url** for which it will fetch the data from the back-end API

```dart
final _baseUrl = 'http://192.168.42.232:5000/api';
```
Then define the httpClient

```dart

final http.Client httpClient;

```
next, add the constructor for the class.and inside the constructor  specify the necessary parameter . 

```dart
ServiceDataProvider({@required this.httpClient}) : assert(httpClient != null);
```

after this let's we add the code for the CRUD methods.
 
**createService**
this method will communicate with the back-end in order to create the data at the back-end database. 

First we have to define the method signature for the **createService** method as follows. 

```dart
Future<Service> createService(Service service) async {

}
```
then let us define the response 

```dart

final response = await httpClient.post(

)
```
Inside this **httpClient.post** method we should put some parameters which are essesntial for the http call.

**URL**
The first one is the *URL* this is the destination where the method invocation will go. 

```dart
 Uri.http('http://192.168.42.232:5000', '/api/services'),
```
**Header**

then we should give the *header*  information. on this information we have to tell the back-end the 
type of files we are passing.

```dart
headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
```

**Body**

then the last on is the body this will be the data that will be created at the server. 

```dart
 body: jsonEncode(<String, dynamic>{
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
```
The whole response code will look like the following. 

```dart
 final response = await httpClient.post(
      Uri.http('http://192.168.42.232:5000', '/api/services'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },

      body: jsonEncode(<String, dynamic>{
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
    );
```
after the response successfully define, based on the response that come from the server we will update the state

```dart
if (response.statusCode == 200) {
      return Service.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to create course.');
    }
```
The whole **createService** method code looks like this. 

```dart

 Future<Service> createService(Service service) async {

    final response = await httpClient.post(
      Uri.http('http://192.168.42.232:5000', '/api/services'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },

      body: jsonEncode(<String, dynamic>{
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
    );

    if (response.statusCode == 200) {
      return Service.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to create course.');
    }
  }
```
**getService**

```dart

Future<List<Service>> getServices() async {
    try{

     final response = await http.get('${_baseUrl}/services');
     if (response.statusCode == 200) {
       final services = jsonDecode(response.body) as List;
       return services.map((service) => Service.fromJson(service)).toList();
     } else {
       throw Exception('Failed to load courses');
     }
   }catch(e){
     print("Exception throuwn $e");
    }


  }
```

**deleteService**

```dart
Future<void> deleteService(int  id) async {
    final http.Response response = await http.delete(
      'http://192.168.43.163:5000/Service/$id',
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to delete course.');
    }

  }
```
**updateService**


```dart
Future<void> updateService(Service service) async {
    final http.Response response = await httpClient.put(
      'http://192.168.43.163:5000/Service/',
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, dynamic>{
        "serviceId":service.id,
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to update course.');
    }
  }
```

The overall **service_data.dart** code will be like the following. 

```dart 
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter_group_project/Service/Model/Service.dart';
import 'package:meta/meta.dart';
import 'package:http/http.dart' as http;

class ServiceDataProvider {
  final _baseUrl = 'http://192.168.42.232:5000/api';
  final http.Client httpClient;

  ServiceDataProvider({@required this.httpClient}) : assert(httpClient != null);

  Future<Service> createService(Service service) async {

    final response = await httpClient.post(
      Uri.http('http://192.168.42.232:5000', '/api/services'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },

      body: jsonEncode(<String, dynamic>{
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
    );

    if (response.statusCode == 200) {
      return Service.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to create course.');
    }
  }

  Future<List<Service>> getServices() async {
    try{

     final response = await http.get('${_baseUrl}/services');
     if (response.statusCode == 200) {
       final services = jsonDecode(response.body) as List;
       return services.map((service) => Service.fromJson(service)).toList();
     } else {
       throw Exception('Failed to load courses');
     }
   }catch(e){
     print("Exception throuwn $e");
    }


  }

  Future<void> deleteService(int  id) async {
    final http.Response response = await http.delete(
      'http://192.168.43.163:5000/Service/$id',
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to delete course.');
    }

  }

  Future<void> updateService(Service service) async {
    final http.Response response = await httpClient.put(
      'http://192.168.43.163:5000/Service/',
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, dynamic>{
        "serviceId":service.id,
        "serviceName": service.ServiceName,
        "description": service.Description,
        "category": service.Category,
        "initialPrice": service.InitialPrice,
        "intermediatePrice":service.IntermediatePrice,
        "advancedPrice":service.AdvancedPrice,

      }),
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to update course.');
    }
  }
}

```
**data_provider.dart**
this will export the **Service_data** add the following line of code inside.

```dart
export 'Service_data.dart';
```

**Bloc Architecture: Data Layer -> Repository**

The repository layer is a wrapper around one or more data providers with which the Bloc Layer communicates. It can interact with multiple data providers and perform transformations on the data before handing the result to the business logic layer.

Inside the **Repository** directory let us create the following two dart files. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgtnhkt7oxqkitymurqr.png)

Then inside the  **Service_repository.dart** file we are going to create a function for all of the data provider **CRUD** method. 
this method will serve as a mediator between the **business logic layer** and the **data access layer**.

```dart
import 'package:flutter_group_project/Service/Model/Service.dart';
import 'package:meta/meta.dart';
import '../Service.dart';

class ServiceRepository {
  final ServiceDataProvider dataProvider;

  ServiceRepository({@required this.dataProvider})
      : assert(dataProvider != null);

  Future<Service> createService(Service service) async {
    return await dataProvider.createService(service);
  }

  Future<List<Service>> getServices() async {
    print("This is the getService method");
    return await dataProvider.getServices();
  }

  Future<void> updateService(Service service) async {
    await dataProvider.updateService(service);
  }

  Future<void> deleteService(int  id) async {
    await dataProvider.deleteService(id);
  }
}
```
The **repository.dart** file does nothing but exporting the *Service_repository.dart*.

```dart
export 'Service_repository.dart';
```
**Bloc Architecture: Business Logic Layer**

The business logic layer's responsibility is to respond to input from the presentation layer with new states. This layer can depend on one or more repositories to retrieve data needed to
build up the application state. Think of the business logic layer as the **bridge** between the user interface (presentation layer) and the data layer.
The business logic layer is notified of events/actions from the presentation layer and then communicates with the repository in order to build a new state for the presentation layer to consume.

From the **Bloc** directory create the following dart files.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94ir4jxolph1qixxa82m.png)

The bloc state management has three different elements.
 
* State
* Event
* bloc

**State**
The State will represent the state for the application. this will be the defined state that the app will possess. 

open **Service_state.dart** file and add the following code inside.

```dart
import 'package:equatable/equatable.dart';
import 'package:flutter_group_project/Service/Service.dart';


class ServiceState extends Equatable {
  const ServiceState();

  @override
  List<Object> get props => [];
}
class ServiceLoading extends ServiceState {}

class ServicesLoadSuccess extends ServiceState{
  final List<Service> services;

  ServicesLoadSuccess([this.services = const []]);

  @override
  List<Object> get props => [services];
}

class ServiceOperationFailure extends ServiceState {}
```
As you can see from the code we have three different states. **ServiceLoading**,**ServicesLoadSuccess**,**ServiceOperationFailer**

**Event**
The event means the operation that will take place in the application. this will be the same as the **CRUD**  operation that we have registered in the data provider.

For this open the **Service_event.dart** file and add the following code inside.

```dart
import 'package:equatable/equatable.dart';
import 'package:flutter_group_project/Service/Model/Service.dart';
import '';

abstract class ServiceEvent extends Equatable {
  const ServiceEvent();
}

class ServiceLoad extends ServiceEvent {
  const ServiceLoad();

  @override
  List<Object> get props => [];
}

class ServiceCreate extends ServiceEvent {
  final Service service;

  const ServiceCreate(this.service);

  @override
  List<Object> get props => [service];

  @override
  String toString() => 'Service Created {service: $service}';
}

class ServiceUpdate extends ServiceEvent {
  final Service service;

  const ServiceUpdate(this.service);

  @override
  List<Object> get props => [service];

  @override
  String toString() => 'Service Updated {service: $service}';
}

class ServiceDelete extends ServiceEvent {
  final Service service;

  const ServiceDelete(this.service);

  @override
  List<Object> get props => [service];

  @override
  toString() => 'Service Deleted {service: $service}';
}
```
here we have 4 different Events These are listed below with their correspondence data provider method.

* ServiceLoad   ->  getServices()
* ServiceCreate ->  createService()
* ServiceUpdate ->  updateService()
* ServiceDelete ->  deleteService()

**bloc** 

This dart file will map every event invoked by the presentation layer to the state. then it will send the updated state back to the presentation layer.

open the **Service_bloc.dart** file and add the following code.

```dart
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:flutter_group_project/Service/Bloc/bloc.dart';
import 'package:flutter_group_project/Service/Repository/Service_repository.dart';


class ServiceBloc extends Bloc<ServiceEvent, ServiceState> {
  final ServiceRepository serviceRepository;

  ServiceBloc({@required this.serviceRepository})
      : assert(serviceRepository != null),
        super(ServiceLoading());

  @override
  Stream<ServiceState> mapEventToState(ServiceEvent event) async* {
    if (event is ServiceLoad) {
      print("Service load method");
      yield ServiceLoading();

      try {
        final services = await serviceRepository.getServices();
        print("This is the service $services");
        yield ServicesLoadSuccess(services);
      } catch (_) {
        yield ServiceOperationFailure();
      }
    }

    if (event is ServiceCreate) {
      try {
        await serviceRepository.createService(event.service);
        final services = await serviceRepository.getServices();
        yield ServicesLoadSuccess(services);
      } catch (_) {
        yield ServiceOperationFailure();
      }
    }

    if (event is ServiceUpdate) {
      try {
        await serviceRepository.updateService(event.service);
        final services = await serviceRepository.getServices();
        yield ServicesLoadSuccess(services);
      } catch (_) {
        yield ServiceOperationFailure();
      }
    }

    if (event is ServiceDelete) {
      try {
        await serviceRepository.deleteService(event.service.id);
        final services = await serviceRepository.getServices();
        yield ServicesLoadSuccess(services);
      } catch (e) {
        print("Error de,ete=$e");
        yield ServiceOperationFailure();
      }
    }
  }
}
```
and finally, there is one file that remained called **bloc.dart** this file will export all three files once. so in other than importing all three files separately importing only this file will make our code simpler and minimize the line of code.

```dart
export 'Service_bloc.dart';
export 'Service_state.dart';
export 'Service_event.dart';
```

If you came from the react js web development background, this type of state management is exactly the same as the **React Redux** state management

* Bloc  ->  Reducer
* State ->  State
* Event ->  Action

**Bloc Architecture: Presentation Layer**

The presentation layer's responsibility is to figure out how to render itself based on one or more bloc states In addition, it should handle user input and application lifecycle events Most applications flows will start with an AppStart event which triggers the application to fetch some data to present to the user
In this scenario, the presentation layer would add an AppStart event.

We are going to build the **UI** on this step. 
In the **Screen** directory,  create the following dart files. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f3b8ubd6hz40v09g35pd.png)

The main page of the app looks like the following.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbukw7twju82pfsbwqxf.jpg)

First, there will be an import from the above. we are gonna import all the necessary packages we need to integrate the **UI** with the business logic and for layouts.


```dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_group_project/Service/Bloc/bloc.dart';
import 'package:flutter_group_project/Service/Screen/ServiceCreateUpdateScreen.dart';
import 'package:flutter_group_project/Service/Screen/screens.dart';
import 'dart:math';

```
Create a class called ServiceMainScreen and define the class **routeName** as Static. 
```dart
class ServiceMainScreen extends StatelessWidget {
  static const routeName='/category_screen';
}
```

The first method we are going to use is a **buildSectionTitle** and this method is used to build a custom text widget for the title. 

```dart
Widget buildSectionTitle(BuildContext context, String text){
    return  Container(

      margin: EdgeInsets.symmetric(
        vertical: 10,

      ),
      child: Text('${text}',
        style: Theme.of(context).textTheme.headline6,),
    );
  }
```
and next, we have here a **buildContainer** method that used to build a container, we will use this method later. 

```dart

Widget buildContainer(BuildContext context , Widget child){
    return Container(
      height: MediaQuery.of(context).size.height * 0.5 ,
      width:MediaQuery.of(context).size.width * 0.90 ,
      decoration: BoxDecoration(
        color:Colors.white,
        border:Border.all(
            color:Colors.grey
        ),
        borderRadius: BorderRadius.circular(10),


      ),
      child:child,
    );
  }
```
**Build Method**
This is the defualt method that will be overriden. this method will start rendering the application so that the app start the building process from this method. 

It have a BuildContext parameter. 

```dart

 @override
  Widget build(BuildContext context) {
    Random random = new Random();
    int randomNumber = random.nextInt(6);

	// return statment here
}
```
we will use the random number later. 

the build methos should return a widget.we are going to return a **Scaffold** from the build method. 

```dart
return Scaffold(
// 
)
```
the scaffold widget have might have different named parameters depending on the app we are building for this application we are
going to use the following named parameters inside the **Scaffold** widget.
  *  appBar
  *  body
  *  floatingActionbutton
  *  floatingActionButtonLocation
  *  bottomNavigationBar

**appBar**

This is the top navigation bar. 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/errl1ylrjkq7klhb8jb4.png)
```dart
appBar: AppBar(title: Text('Category Name'), actions: [
          PopupMenuButton(
              icon: Icon(Icons.refresh),
              itemBuilder: (_) => [
                    PopupMenuItem(
                      child: Text('Refresh'),
                      value: () {},
                    ),
                    PopupMenuItem(
                      child: Text('Show All'),
                      value: null,
                    ),
                  ]),
        ]),
``` 
**body**
This is the main portion of the application, it will cover the place other than the **bottomNavigationBar** and the **floatingActionButton**

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0u64bcx7e633kdg9asbj.png)


Because the whole page will scroll we have to held using a **singleChildScrolView** at the top.

```dart
body: SingleChildScrollView(
          child: Column(
              children: [
                 // Childrens will come here
               ]
          )
```
Then inside the children widget we have the following childrent respectively. 
      * Image Section
      * Text Section
      * List View

**Image Section**

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0afw00fdozin70zhalb.png)
```dart
 Container(
              height: MediaQuery.of(context).size.width * 0.5,
              width: double.infinity,
              child: Image.asset("Assets/assets/wood.jpg"),
            ),
```

**Text Section**

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gfcxg97ojsmiv85t40d3.png)

```dart
buildSectionTitle(context, 'Services'),
```
If you remember in the above we have implemented this **buildSectionTitle** method, so that we are using it here  to build a custome text Wdiget.

**List View**
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wiyfbmtfxmvnp24udpev.png)
 
This section is the place where the **Services** that came from the back-end will be displayed, so this widget is a replaceble widget depending on the new state that came. 
we are going to use our **Bloc** concept here. 

**Core Concepts of Bloc: BlocBuilder**

BlocBuilder is a Flutter widget which requires a Bloc and a builder function BlocBuilder handles building the widget in response to new states The builder function will potentially be called many times and should be a pure function that returns a widget in response to the state.

Next to the **Service** title section put the following **blocBuilder** method signature.

```dart
	BlocBuilder<ServiceBloc, ServiceState>(builder: (_, state) {
		// remainging code here
	}
```
Then inside this method let us add our business logic, this page only loads data from the **businessLogicLayer** so the possible states will be the following. 
  *  ServiceOperationFailure
  *  ServicesLoadSuccess

so let us do a confition for these states.

**ServiceOperationFailure**
we do not have much to do here only return a Text.
```dart
 if (state is ServiceOperationFailure) {
                return Text('Could not do Service  operation');
              }
```
**ServicesLoadSuccess**
here our on this condition our list view will be build depending on the States that come from **businessLogicLayer**.
```dart
if (state is ServicesLoadSuccess) {
                final services = state.services;
                return buildContainer(
                    context,
                    ListView.builder(
                        itemCount: services.length,
                        itemBuilder: (ctx, index) => Column(children: [
                              Container(
                                decoration: BoxDecoration(
                                    color: Colors.white38,
                                    borderRadius: BorderRadius.circular(20)),
                                height:
                                    MediaQuery.of(context).size.height * 0.15,
                                margin: EdgeInsets.all(4),
                                padding: EdgeInsets.all(4),
                                child: Card(
                                  elevation: 5,
                                  margin: EdgeInsets.symmetric(
                                      vertical: 8, horizontal: 5),
                                  child: Center(
                                    child: ListTile(
                                      leading: CircleAvatar(
                                        backgroundImage: AssetImage(
                                            'Assets/assets/fixit.png'),
                                      ),
                                      title: Text(
                                        services[index].ServiceName != null
                                            ? services[index].ServiceName
                                            : "place holder",
                                        style: Theme.of(context)
                                            .textTheme
                                            .headline6,
                                      ),
                                      subtitle: Text(
                                        services[index].Description != null
                                            ? services[index].Description
                                            : "Place holder",
                                      ),
                                      trailing: MediaQuery.of(context)
                                                  .size
                                                  .width >
                                              450
                                          ? FlatButton.icon(
                                              textColor:
                                                  Theme.of(context).errorColor,
                                              icon: Icon(
                                                Icons.delete_forever,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            )
                                          : IconButton(
                                              icon: Icon(
                                                Icons.star_border,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            ),
                                      onTap: () => Navigator.of(context)
                                          .pushNamed(ServiceDetail.routeName,
                                              arguments: services[index]),
                                    ),

                                  ),
                                ),
                              )
                            ])));
              }
```
then on the defualt position let us return a progress indicator.
```dart
return CircularProgressIndicator();
```
The overall **BlocBuilder** code will looks like the following. 

```dart
            BlocBuilder<ServiceBloc, ServiceState>(builder: (_, state) {

              if (state is ServiceOperationFailure) {
                return Text('Could not do Service  operation');
              }
              if (state is ServicesLoadSuccess) {
                final services = state.services;
                return buildContainer(
                    context,
                    ListView.builder(
                        itemCount: services.length,
                        itemBuilder: (ctx, index) => Column(children: [
                              Container(
                                decoration: BoxDecoration(
                                    color: Colors.white38,
                                    borderRadius: BorderRadius.circular(20)),
                                height:
                                    MediaQuery.of(context).size.height * 0.15,
                                margin: EdgeInsets.all(4),
                                padding: EdgeInsets.all(4),
                                child: Card(
                                  elevation: 5,
                                  margin: EdgeInsets.symmetric(
                                      vertical: 8, horizontal: 5),
                                  child: Center(
                                    child: ListTile(
                                      leading: CircleAvatar(
                                        backgroundImage: AssetImage(
                                            'Assets/assets/fixit.png'),
                                      ),
                                      title: Text(
                                        services[index].ServiceName != null
                                            ? services[index].ServiceName
                                            : "place holder",
                                        style: Theme.of(context)
                                            .textTheme
                                            .headline6,
                                      ),
                                      subtitle: Text(
                                        services[index].Description != null
                                            ? services[index].Description
                                            : "Place holder",
                                      ),
                                      trailing: MediaQuery.of(context)
                                                  .size
                                                  .width >
                                              450
                                          ? FlatButton.icon(
                                              textColor:
                                                  Theme.of(context).errorColor,
                                              icon: Icon(
                                                Icons.delete_forever,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            )
                                          : IconButton(
                                              icon: Icon(
                                                Icons.star_border,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            ),
                                      onTap: () => Navigator.of(context)
                                          .pushNamed(ServiceDetail.routeName,
                                              arguments: services[index]),
                                    ),

                                  ),
                                ),
                              )
                            ])));
              }
              return CircularProgressIndicator();
            }),
```
So by this we have finalized the **body**.

**floatingActionButton**
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alq07yn4hvqyqf2ta1eu.png)
This action button will be use to add additional services.
 
```dart
floatingActionButton: FloatingActionButton(
          onPressed: () => Navigator.of(context).pushNamed(
            AddUpdateService.routeName,
            arguments: ServiceArgument(edit: false),
          ),
          child: Icon(Icons.add),
        ),
```
To make the **floatingActionButton** have a dom shaped and stayed at the center of the bottom navigation bar let us give it the follwoing property. 
```dart
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
```

**bottomNavigationBar**

This part have no any functionality for this application but incase of a serious project we can give it some actoin to perform. here it is just a default for a decorating the layout. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbulkdl1cwxfqd1qbqvf.png)

```dart
bottomNavigationBar: BottomAppBar(
          color: Theme.of(context).primaryColor,
          shape: CircularNotchedRectangle(),
          child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                IconButton(
                  icon: Icon(Icons.search),
                  color: Colors.white,
                  onPressed: () {
                    print("search icon button have been clicked");
                  },
                ),
                IconButton(
                  icon: Icon(Icons.note),
                  color: Colors.white,
                  onPressed: () {
                    print("the note icon button have been clicked");
                  },
                )
              ]),
        )
```
The whole **ServiceMainScreen.dart** file will be as the follwoing. 

```dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_group_project/Service/Bloc/bloc.dart';
import 'package:flutter_group_project/Service/Screen/ServiceCreateUpdateScreen.dart';
import 'package:flutter_group_project/Service/Screen/screens.dart';
import 'dart:math';

class ServiceMainScreen extends StatelessWidget {
  static const routeName = '/category_screen';

  Widget buildSectionTitle(BuildContext context, String text) {
    return Container(
      margin: EdgeInsets.symmetric(
        vertical: 10,
      ),
      child: Text(
        '${text}',
        style: Theme.of(context).textTheme.headline6,
      ),
    );
  }

  Widget buildContainer(BuildContext context, Widget child) {
    return Container(
      height: MediaQuery.of(context).size.height * 0.5,
      width: MediaQuery.of(context).size.width * 0.90,
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border.all(color: Colors.grey),
        borderRadius: BorderRadius.circular(10),
      ),
      child: child,
    );
  }

  @override
  Widget build(BuildContext context) {
    Random random = new Random();
    int randomNumber = random.nextInt(6);

    print(randomNumber);

    return Scaffold(
        appBar: AppBar(title: Text('Category Name'), actions: [
          PopupMenuButton(
              icon: Icon(Icons.refresh),
              itemBuilder: (_) => [
                    PopupMenuItem(
                      child: Text('Refresh'),
                      value: () {},
                    ),
                    PopupMenuItem(
                      child: Text('Show All'),
                      value: null,
                    ),
                  ]),
        ]),
        body: SingleChildScrollView(
          child: Column(children: [
            Container(
              height: MediaQuery.of(context).size.width * 0.5,
              width: double.infinity,
              child: Image.asset("Assets/assets/wood.jpg"),
            ),
//           ingredient
            buildSectionTitle(context, 'Services'),

            BlocBuilder<ServiceBloc, ServiceState>(builder: (_, state) {

              if (state is ServiceOperationFailure) {
                return Text('Could not do Service  operation');
              }
              if (state is ServicesLoadSuccess) {
                final services = state.services;
                return buildContainer(
                    context,
                    ListView.builder(
                        itemCount: services.length,
                        itemBuilder: (ctx, index) => Column(children: [
                              Container(
                                decoration: BoxDecoration(
                                    color: Colors.white38,
                                    borderRadius: BorderRadius.circular(20)),
                                height:
                                    MediaQuery.of(context).size.height * 0.15,
                                margin: EdgeInsets.all(4),
                                padding: EdgeInsets.all(4),
                                child: Card(
                                  elevation: 5,
                                  margin: EdgeInsets.symmetric(
                                      vertical: 8, horizontal: 5),
                                  child: Center(
                                    child: ListTile(
                                      leading: CircleAvatar(
                                        backgroundImage: AssetImage(
                                            'Assets/assets/fixit.png'),
                                      ),
                                      title: Text(
                                        services[index].ServiceName != null
                                            ? services[index].ServiceName
                                            : "place holder",
                                        style: Theme.of(context)
                                            .textTheme
                                            .headline6,
                                      ),
                                      subtitle: Text(
                                        services[index].Description != null
                                            ? services[index].Description
                                            : "Place holder",
                                      ),
                                      trailing: MediaQuery.of(context)
                                                  .size
                                                  .width >
                                              450
                                          ? FlatButton.icon(
                                              textColor:
                                                  Theme.of(context).errorColor,
                                              icon: Icon(
                                                Icons.delete_forever,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            )
                                          : IconButton(
                                              icon: Icon(
                                                Icons.star_border,
                                                color: Theme.of(context)
                                                    .errorColor,
                                              ),
                                            ),
                                      onTap: () => Navigator.of(context)
                                          .pushNamed(ServiceDetail.routeName,
                                              arguments: services[index]),
                                    ),

                                  ),
                                ),
                              )
                            ])));
              }
              return CircularProgressIndicator();
            }),
          ]),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => Navigator.of(context).pushNamed(
            AddUpdateService.routeName,
            arguments: ServiceArgument(edit: false),
          ),
          child: Icon(Icons.add),
        ),

        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        bottomNavigationBar: BottomAppBar(
          color: Theme.of(context).primaryColor,
          shape: CircularNotchedRectangle(),
          child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                IconButton(
                  icon: Icon(Icons.search),
                  color: Colors.white,
                  onPressed: () {
                    print("search icon button have been clicked");
                  },
                ),
                IconButton(
                  icon: Icon(Icons.note),
                  color: Colors.white,
                  onPressed: () {
                    print("the note icon button have been clicked");
                  },
                )
              ]),
        ));
  }
}
```