New user
New user

Reputation: 147

How to developed pie chart from firestore in flutter

I'm new in flutter, I want to make pie chart but it must show the category that are stored in the firestore. How to show the pie chart based on the "category" that stored in the firestore? Anyone can help? Thanks

from this category (beauty)

In this code, I'm still using a sample data to store the pie chart. I want to change it based on the data that stored in the firestore.

Code

import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
//import 'package:cloud_firestore/cloud_firestore.dart';

class StatisticsExpense extends StatefulWidget {
  @override
  _StatisticsExpenseState createState() => _StatisticsExpenseState();
}

class _StatisticsExpenseState extends State<StatisticsExpense> {

  int key = 0;

  Map<String, double> dataMap = {
    "Food": 5,
    "Health": 3,
    "Social Life": 2,

  };

  List<Color> colorList = [
    Colors.red,
    Colors.yellow,
    Colors.green,
  ];

  Widget pieChartExampleOne(){
    return PieChart(
      key: ValueKey(key),
      dataMap: dataMap,
      initialAngleInDegree: 0,
      animationDuration: Duration(milliseconds: 2000),
      chartType: ChartType.ring,
      chartRadius: MediaQuery.of(context).size.width / 3.2,
      ringStrokeWidth: 32,
      colorList: colorList,
      chartLegendSpacing: 32,
      chartValuesOptions: ChartValuesOptions(
        showChartValuesOutside: true,
        showChartValuesInPercentage: true,
        showChartValueBackground: true,
        showChartValues: true,
        chartValueStyle: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.black
        )
      ),
      centerText: 'Expense',
      legendOptions: LegendOptions(
        showLegendsInRow: false,
        showLegends: true,
        legendShape: BoxShape.rectangle,
        legendPosition: LegendPosition.right,
        legendTextStyle: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.black,
        )
      ),
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(height: 50,),
            pieChartExampleOne(),
          ],
        ),
      )
    );
  }
}

Upvotes: 0

Views: 1524

Answers (1)

Sanjay TM
Sanjay TM

Reputation: 467

I hope you have already done the basic Firebase setup in your Flutter project.

First, create a model for Expenses:

class Expense {
  String amount;
  String category;
  String date;
  String description;

  Expense(
      {required this.amount,
      required this.category,
      required this.date,
      required this.description});
}

Create a method to get the map of category and its count

late List<Expense> _expense = [];

  Map<String, double> getCategoryData() {
    Map<String, double> catMap = {};
    for (var item in _expense) {
      print(item.category);
      if (catMap.containsKey(item.category) == false) {
        catMap[item.category] = 1;
      } else {
        catMap.update(item.category, (int) => catMap[item.category]! + 1);
        // test[item.category] = test[item.category]! + 1;
      }
      print(catMap);
    }
    return catMap;
  }

Then create a stream to get the firbase collection:

final Stream<QuerySnapshot> expStream =
        FirebaseFirestore.instance.collection('TransactionExpense').snapshots();

Warp the Pichart widget with "StreamBuilder" and set the stream:

StreamBuilder<Object>(
  stream: expStream,
  builder: (context, snapshot) {
    if (snapshot.hasError) {
       return Text("something went wrong");
    }
    if (snapshot.connectionState == ConnectionState.waiting) {
       return CircularProgressIndicator();
    }
    final data = snapshot.requireData;
    print("Data: $data");
    getExpfromSanapshot(data);
    return pieChartExampleOne();
  },
),

Create a method to convert snapshot data into a list of elements:

void getExpfromSanapshot(snapshot) {
  if (snapshot.docs.isNotEmpty) {
    _expense = [];
    for (int i = 0; i < snapshot.docs.length; i++) {
      var a = snapshot.docs[i];
      // print(a.data());
      Expense exp = Expense.fromJson(a.data());
      _expense.add(exp);
      // print(exp);
     }
   }
}

By doing this you can get the firestore data and plot it in a pichat, and this will be realtime (because of the StreamBuilder the Pichart will be updated as soon as data is updated to the firebase)

Complete code:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';

class StatisticsExpense extends StatefulWidget {
  @override
  _StatisticsExpenseState createState() => _StatisticsExpenseState();
}

class _StatisticsExpenseState extends State<StatisticsExpense> {
  int key = 0;

  late List<Expense> _expense = [];

  Map<String, double> getCategoryData() {
    Map<String, double> catMap = {};
    for (var item in _expense) {
      print(item.category);
      if (catMap.containsKey(item.category) == false) {
        catMap[item.category] = 1;
      } else {
        catMap.update(item.category, (int) => catMap[item.category]! + 1);
        // test[item.category] = test[item.category]! + 1;
      }
      print(catMap);
    }
    return catMap;
  }

  List<Color> colorList = [
    Color.fromRGBO(82, 98, 255, 1),
    Color.fromRGBO(46, 198, 255, 1),
    Color.fromRGBO(123, 201, 82, 1),
    Color.fromRGBO(255, 171, 67, 1),
    Color.fromRGBO(252, 91, 57, 1),
    Color.fromRGBO(139, 135, 130, 1),
  ];

  Widget pieChartExampleOne() {
    return PieChart(
      key: ValueKey(key),
      dataMap: getCategoryData(),
      initialAngleInDegree: 0,
      animationDuration: Duration(milliseconds: 2000),
      chartType: ChartType.ring,
      chartRadius: MediaQuery.of(context).size.width / 3.2,
      ringStrokeWidth: 32,
      colorList: colorList,
      chartLegendSpacing: 32,
      chartValuesOptions: ChartValuesOptions(
          showChartValuesOutside: true,
          showChartValuesInPercentage: true,
          showChartValueBackground: true,
          showChartValues: true,
          chartValueStyle:
              TextStyle(fontWeight: FontWeight.bold, color: Colors.black)),
      centerText: 'Expense',
      legendOptions: LegendOptions(
          showLegendsInRow: false,
          showLegends: true,
          legendShape: BoxShape.rectangle,
          legendPosition: LegendPosition.right,
          legendTextStyle: TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.black,
          )),
    );
  }

  @override
  Widget build(BuildContext context) {
    final Stream<QuerySnapshot> expStream =
        FirebaseFirestore.instance.collection('TransactionExpense').snapshots();

    void getExpfromSanapshot(snapshot) {
      if (snapshot.docs.isNotEmpty) {
        _expense = [];
        for (int i = 0; i < snapshot.docs.length; i++) {
          var a = snapshot.docs[i];
          // print(a.data());
          Expense exp = Expense.fromJson(a.data());
          _expense.add(exp);
          // print(exp);
        }
      }
    }

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(
              height: 50,
            ),
            StreamBuilder<Object>(
              stream: expStream,
              builder: (context, snapshot) {
                if (snapshot.hasError) {
                  return Text("something went wrong");
                }
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return CircularProgressIndicator();
                }
                final data = snapshot.requireData;
                print("Data: $data");
                getExpfromSanapshot(data);
                return pieChartExampleOne();
              },
            ),
          ],
        ),
      ),
    );
  }
}

class Expense {
  String amount;
  String category;
  String date;
  String description;

  Expense(
      {required this.amount,
      required this.category,
      required this.date,
      required this.description});

  factory Expense.fromJson(Map<String, dynamic> json) {
    return Expense(
      amount: json['amount'],
      category: json['category'],
      date: json['date'],
      description: json['description'],
    );
  }
}

// Sample data for PiChart
Map<String, double> dataMap = {
  "Food": 4,
  "Health": 3,
  "Social Life": 2,
};

// Sample data for Expense list
List<Expense> getExpenseList() {
  final List<Expense> chartData = [
    Expense(
        amount: "RM100",
        category: "Food",
        date: "Jan 15, 2021",
        description: "Break fast"),
    Expense(
        amount: "RM200",
        category: "Health",
        date: "Feb 15, 2021",
        description: "Workout"),
    Expense(
        amount: "RM200",
        category: "Health",
        date: "Feb 15, 2021",
        description: "Workout"),
    Expense(
        amount: "RM45",
        category: "Health",
        date: "Feb 25, 2021",
        description: "Workout"),
    Expense(
        amount: "RM80",
        category: "Social Life",
        date: "Feb 26, 2021",
        description: "Social Media"),
  ];
  return chartData;
}

Upvotes: 2

Related Questions