Blogging my journey of learning Full stack devlopment and creating an App to get a hands on knowledge.

Search This Blog

Wednesday 7 June 2023

Building a Recipe Creator App with Flutter and OpenAI ChatGPT API

The app will allow users to enter ingredients in the textbox and they will get the personalized recipe recommendation based on their inputs through the capabilities of OpenAI .

Step 1: Create a new Flutter project

Step 2: Add Dependencies

dependencies:

  http: ^0.13.0

Step 3: Design the App UI and  Integrate OpenAI API with Flutter UI





Preview of the App:



Check out the Git Code here

Read More

Friday 2 June 2023

Building a Travel Itinerary App with Flutter and OpenAI ChatGPT

In this technical blog post, we will walk through the process of creating a travel itinerary app using Flutter and integrating the OpenAI ChatGPT API. By leveraging the cross-platform capabilities of Flutter and the conversational intelligence of ChatGPT, we can develop an app that assists users in planning their trips and generates personalized itineraries based on their preferences.

Step 1: Setting Up the Development Environment

Install Flutter: Follow the official Flutter installation guide for your operating system.

Set Up an Editor: Choose an IDE or text editor for Flutter development, such as Visual Studio Code or Android Studio, and install the necessary plugins and extensions.

Step 2: Creating a New Flutter Project

Open your terminal or command prompt and run the command flutter create your_app_name to create a new Flutter project.

Step 3: Adding Dependencies

  chat_gpt_sdk: ^2.1.7

Step 4: Designing the User Interface and Integrating OpenAI ChatGPT API

I developed a basic user interface using the Dart language to gather user input. The input will be used as a variable in the prompt for Chat GPT. Upon submission, the UI will generate a travel itinerary based on the provided user data.

OpenAI ChatGPT API:

 Create an OpenAI account and obtain an API key for authentication.You can find the API key at here.

Note: No free version of Chat GPT API is available now. However, you can start for free with $5 in free credit that can be used during your first 3 months. Check details here

Chat GPT SDK

There is a SDK wrapper for OpenAI's APIs in Flutter, which assists in seamlessly integrating ChatGPT into your Flutter applications.

Add Chat GPT SDK and import it in your file and use following code to request and get response from Open AI's Chat GPT.


Preview of the App





Check out the Git Code here

Read More

Wednesday 10 May 2023

Thursday 4 May 2023

Implementing BLOC design pattern for state management of Search Field in Flutter

 Business logic components (BLoC) allow you to separate the business logic from the UI. Using Bloc, we can easily separate the application into multiple layers, first we would have the presentation layer which would contain the UI/Views/widgets, then the business logic layer (Bloc) which will take care about the state changes and will have a dependency on the data access layer which contains a repository class which will act as an abstract class above the data access object classes.

Dependencies:

  • flutter_bloc: ^8.1.2
  • equatable: ^2.0.5
  • http: ^0.13.5

Code Implementation :

Let's build a simple app to implement this Bloc pattern. We will create a simple search field that will search recipe and give the the list of recipe based on your search. I have used Forkify API to search, view the recipe.

data/model/receipe.dart

class Recipe {
Recipe({
required this.publisher,
required this.title,
required this.sourceUrl,
required this.recipeId,
required this.imageUrl,
required this.socialRank,
required this.publisherUrl,
});

String publisher;
String title;
String sourceUrl;
String recipeId;
String imageUrl;
double socialRank;
String publisherUrl;

factory Recipe.fromJson(Map<String, dynamic> json) => Recipe(
publisher: json["publisher"],
title: json["title"],
sourceUrl: json["source_url"],
recipeId: json["recipe_id"],
imageUrl: json["image_url"],
socialRank: json["social_rank"]?.toDouble(),
publisherUrl: json["publisher_url"],
);

Map<String, dynamic> toJson() => {
"publisher": publisher,
"title": title,
"source_url": sourceUrl,
"recipe_id": recipeId,
"image_url": imageUrl,
"social_rank": socialRank,
"publisher_url": publisherUrl,
};
}
data/repositories/search_repositories.dart
import 'package:searchscreen/data/model/pizza.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
abstract class SearchRepository{
Future<List<Recipe>> searchPizza(String query);
}

class SearchRepositoryImpl implements SearchRepository{
List<Recipe> recipes=[];
@override
Future<List<Recipe>> searchPizza(query) async{
try{
var response= await http.get( Uri.parse('https://forkify-api.herokuapp.com/api/search?q=$query' ));
if (response.statusCode == 200) {
var data = json.decode(response.body);
recipes = Pizza
.fromJson(data)
.recipes;
return recipes;
} else
{
return recipes;
}
}
catch(error){
throw (error.toString());

}
}
}
bloc/search_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:searchscreen/bloc/search/search_event.dart';
import 'package:searchscreen/bloc/search/search_state.dart';
import 'package:searchscreen/data/model/pizza.dart';
import 'package:searchscreen/data/repositories/search_repository.dart';
class SearchBloc extends Bloc<SearchEvent,SearchState> {
final SearchRepository repository;

SearchBloc(this.repository) : super(SearchUninitialized()) {
on<Search>(
(event, emit) async {
try {
emit(SearchLoadingState());
final List<Recipe> recipes = await repository.searchPizza(event.query);

emit(SearchLoaded(recipes: recipes));
} catch (e,stackTrace) {
emit(SearchErrorState(message: e.toString()));
}
});
}
}

bloc/search_event.dart

import 'package:equatable/equatable.dart';
abstract class SearchEvent extends Equatable{
const SearchEvent();
}
class Search extends SearchEvent{
late String query;
Search({required this.query});

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

bloc/search_state.dart


import 'package:equatable/equatable.dart';
import 'package:searchscreen/data/model/pizza.dart';
abstract class SearchState extends Equatable{

}
class SearchUninitialized extends SearchState{
@override
List<Object?> get props =>[];
}
class SearchLoadingState extends SearchState{

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

}
class SearchLoaded extends SearchState{
final List<Recipe> recipes;
SearchLoaded({required this.recipes});
@override
List<Object?> get props => [];

}

class SearchErrorState extends SearchState{
final String message;
SearchErrorState({required this.message});
@override
List<Object?> get props => [];

}

main.dart

import 'package:flutter/material.dart';
import 'package:searchscreen/bloc/search/search_bloc.dart';
import 'package:searchscreen/data/repositories/search_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:searchscreen/ui/search_view.dart';
void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return

RepositoryProvider(
create: (context) =>PizzaRepositoryImpl() ,
child: MultiBlocProvider(
providers: [
BlocProvider<PizzaBloc>(
create: (context) => PizzaBloc(PizzaRepositoryImpl()
)..add(FetchPizzaEvent()),lazy: false,),
BlocProvider<SearchBloc>(
create: (context) => SearchBloc(SearchRepositoryImpl()
))
],
child: MaterialApp(
title: 'Recipe Search App',
home: SearchView(),
)),
);

}
}

ui/search_view.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:searchscreen/bloc/search/search_bloc.dart';
import 'package:searchscreen/bloc/search/search_event.dart';
import 'package:searchscreen/bloc/search/search_state.dart';
import 'package:searchscreen/ui/list.dart';
import 'package:searchscreen/widgets/search_text_field.dart';

class SearchView extends StatefulWidget {
const SearchView({super.key});

@override
SearchViewState createState() => SearchViewState();
}

class SearchViewState extends State<SearchView> {


final TextEditingController _controller = TextEditingController();
@override
void initState() {
super.initState();
_controller.addListener(
() => context
.read<SearchBloc>()
.add(Search(query: _controller.text))
);

}
@override
void dispose() {
_controller.dispose();
super.dispose();
}


@override
Widget build(BuildContext context) {

return BlocConsumer<SearchBloc, SearchState>(

listener: (context, state) {
if (state is SearchErrorState) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
const SnackBar(content: Text("Failed to Load")),
);

}


},
builder: (context, state) {
return Scaffold(appBar: AppBar(
title: const Text(
'Recipes'
)
),body:ListView(
shrinkWrap: true,
children: [
Card (child: SearchTextField(
key: const Key('searchPage_searchTextField'),
controller: _controller,
),),
const Divider(),
if(state is SearchLoaded)
buildHintsList(state.recipes)
],
));

},
);
}

}


Output:









Git code : https://github.com/anjutus/searchscreendemo
Read More

Friday 31 March 2023

Add CORS configuration for your Firebase Storage

Firebase is using the same storage infrastructure as google cloud .

1. Go to https://console.cloud.google.com and select the dashboard of the project that contains the firebase storage.

2. On the top right, there will be a button named "Activate Cloud Shell", click on it, a terminal will open on the bottom of the page

Click on Open Editor

Click on File, and New file. 

3.Create new file with name cors.json, paste the following save.

[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]

4.On your Firebase Console and select "Storage" and  get your storage bucket URL (e.g gs://)

5.Then open the terminal again and paste following

       gsutil cors set cors.json gs://<your-cloud-storage-bucket>         

The CORS error should be gone for Storage for which we added the configuration. It wont be applied to other storage bucket

Read More

Firebase Firestore Database and Storage implementation for Flutter Project

  1. From your Flutter project directory, run the following command to install the core plugin:

    flutter pub add firebase_core

  2. Add following code to the root of your Flutter project,  

    import'package:firebase_core/firebase_core.dart'; import'firebase_options.dart'; Future main()async{ WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(  options:DefaultFirebaseOptions.currentPlatform); runApp(constMyApp()); }

  3. Run the following command to install the core plugin:

    flutter pub add cloud_firestore
    flutter pub add firebase_storage


  4. Once complete, rebuild your Flutter application:

    flutter run

  5. Add the following code for Adding details in your Database(Image in Firebase Storage retrieve the URL to save it along with the details in Database )
    Code for Firestore database:
    import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_storage/firebase_storage.dart'; final incidentDetails =FirebaseFirestore.instance.collection('IncidentDetails'); // Call the incident's CollectionReference to add a new incident details incidentDetails.add({ 'incident_number': _formKey.currentState!.value['incidentnumber'], 'date_of_incident':formattedDateofIncident, 'incident_location':_formKey.currentState!.value['incidentlocation'], 'incident_priority': _formKey.currentState!.value['incidentpriority'], 'incident_type':_formKey.currentState!.value['incidenttype'], 'incident_description':_formKey.currentState!.value['incidentdescription'], 'incident_image':imageUrl, }).then((DocumentReference) { setState(() { submitMessage =true; ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content:Text("Submitted Succesfully!"), backgroundColor:Colors.teal, behavior:SnackBarBehavior.floating, duration:Duration(seconds: 5), )); _formKey.currentState?.reset(); }); }).catchError((error) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content:Text('Error $error'), backgroundColor:Colors.teal, behavior:SnackBarBehavior.floating, duration:const Duration(seconds: 5), )); });

    Code for FilePicker for selecting Image from my local drive and adding it in Storage:


    //File object PlatformFile? pickedFile; //File from the local drive stored in a byte format Uint8List? file; //Variable for storing URL of image fetched from firebase storage String? imageUrl; // Variable for file List<File?> files = []; final result = await FilePicker.platform .pickFiles(allowMultiple: false, type: FileType.image); if(result==null) { return; } setState(() { pickedFile= result.files.first; file= result.files.single.bytes; }); final filename='files/${pickedFile!.name}'; //Create reference for Firebase Storage Reference ref=FirebaseStorage.instance.ref().child(filename); //Add file UploadTask uploadTask=ref.putData(file!); //Wait for the Complete Response final TaskSnapshot taskSnapshot = await uploadTask.whenComplete(() {}); //get the image url imageUrl = await taskSnapshot.ref.getDownloadURL(); //file.clear(); setState(() { });


  6. Run your project and check for file creation in Firebase.(I encountered blocked by CORS error for Firebase Storage. So I had to Update my CORS policy for Storage of my project in Google Cloud Console ) . Here is link for it Click here
Read More

Monday 27 March 2023

Build and Deploy your Flutter GitHub Code on Web using Firebase Hosting.

 You can automate Flutter Web Deployments to Firebase Hosting using GitHub. After the configuration and setup ,all you need to do is push your local code to GitHub and view your application on web using URL .

Step 1 : Install the Firebase CLI 

https://firebase.google.com/docs/hosting/quickstart#install-cli

 

Step 2 : Initialize your project 

firebase init hosting:github

 

Step 3 :  Follow the CLI prompts, and the command will automatically take care of setting up the GitHub Action

Once the configuration is complete, there will be two new files written:

  • .firebaserc : Basic config for the project. It consist of your project name on firebase;
  • firebase.json: Additional config. Tells Firebase about the public folder, which files/folders to ignore

 

Step 4 : To automate the deployment process, we will write YAML code to script our CI/CD workflow using GitHub Actions.


Step 5: In .github/workflows/firebase_hosting_merge.yml paste the following code


name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - master
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 'Git Checkout'
        uses: actions/checkout@v3
      - name: 'Flutter setup'
        uses: subosito/flutter-action@v2
        with:
          channel: 'stable'
      - name: 'Run flutter pub get'
        run: flutter pub get
      - name: 'Build Web App'
        run: flutter build web --release
      - name: Deploy to Firebase
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets. Your secret key }}'
          channelId: live
          projectId: Your firebase project name



In .github/workflows/firebase_hosting_pull_request.yml paste the following code

name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
  build_and_preview:
    if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
    runs-on: ubuntu-latest
    steps:
      - name: 'Git Checkout'
        uses: actions/checkout@v3
      - name: 'Flutter setup'
        uses: subosito/flutter-action@v2
        with:
          channel: 'stable'
      - name: 'Run flutter pub get'
        run: flutter pub get
      - name: 'Build Web App'
        run: flutter build web --release
      - name: Deploy to Firebase
        uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.Your secret key }}'
          projectId: Your firebase project name



Step 6: You can customize the workflow according to your project’s needs. Finally, to see everything in action, all you need to do is commit and push your changes to the GitHub repository, and the workflow will automatically trigger and deploy the latest version of your app to Firebase Hosting. You can check the logs and details of the workflow run, even in real time, by clicking the Actions tab of your repository main page
Read More

Featured Post

Invoice Portal Project Links

Web App link for Invoice Portal  Invoice Portal App lets an user view and create an Invoice. Features: View the list of Number of Invoices b...

Powered by Blogger.

Popular Posts