Project Aplikasi Expense Tracker – Part 1

Pada modul ini kita akan learning by doing. Aplikasi expense tracker akan mencatat pengeluaran dan menampilkan dalam bentuk list serta graph. User dapat menambahkah dan menghapus expense.

Pada part 1 aplikasi masih setengah jadi, pada part 2 akan perbaiki, agar paham tujuan dari perbaikan tersebut.

Instalasi Paket Pihak Ketiga

Pada aplikasi ini digunakan third party library yaitu intl. Untuk itu perlu ditambahkan pada file pubspec.yaml. Untuk info versi package terbaru lihat di https://pub.dev/packages/intl#-installing-tab-

Penambahan paket harus memperhatikan identasi, perhatikan gambar dibawah. intl: ^0.16.1 ditambahkan sejajar dengan flutter.

Setelah ditambahkan, tekan tombol save, maka otomatis flutter akan melakukan download dan disimpan di direktori project kita. (lihat bagian modal box dipojok kanan bawah).

Code Aplikasi

Buat aplikasi baru, silakan beri nama sesuai keperluan Anda. Isi main.dart adalah seperti berikut:

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import './trans.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final List<Trans> trans = [
    Trans(
        id: 'a001',
        title: 'Notebook Aspire A5',
        amount: 8200000,
        txdate: DateTime.now()),
    Trans(
        id: 'a002',
        title: 'Samsung Galaxy A5',
        amount: 3200000,
        txdate: DateTime.now()),
  ];

  // String titleInp, amountInp;
  final titleCtrl = TextEditingController();
  final amountCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expense Tracker'),
      ),
      body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Card(
              color: Colors.blue,
              child: Text('Chart'),
            ),
            Card(
              child: Container(
                padding: EdgeInsets.all(7),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    TextField(
                      decoration: InputDecoration(labelText: 'Title'),
                      // onChanged: (val) => titleInp = val,
                      controller: titleCtrl,
                    ),
                    TextField(
                      decoration: InputDecoration(labelText: 'Amount'),
                      // onChanged: (val) => amountInp = val,
                      controller: amountCtrl,
                    ),
                    FlatButton(
                      onPressed: () {
                        print(titleCtrl.text);
                      },
                      child: Text('Add Expense'),
                      textColor: Colors.red,
                    ),
                  ],
                ),
              ),
            ),
            Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: trans.map((trx) {
                return Card(
                  child: Row(
                    children: <Widget>[
                      Container(
                        padding: EdgeInsets.all(6),
                        margin: EdgeInsets.symmetric(
                          vertical: 10,
                          horizontal: 15,
                        ),
                        decoration: BoxDecoration(
                            border: Border.all(color: Colors.red, width: 2)),
                        child: Text(
                          // 'Rp. ${trx.amount}',
                          NumberFormat.currency(
                                  symbol: 'Rp. ', decimalDigits: 0)
                              .format(trx.amount),
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 14,
                              color: Colors.red),
                        ),
                      ),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(
                            trx.title,
                            style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 12,
                            ),
                          ),
                          Text(
                            DateFormat.yMMMd().format(trx.txdate),
                            style: TextStyle(fontSize: 10, color: Colors.grey),
                          ),
                        ],
                      )
                    ],
                  ),
                );
              }).toList(),
            ),
          ]),
    );
  }
}

File trans.dart untuk class dari transaksi expense

import 'package:flutter/foundation.dart';

class Trans {
  final String id;
  final String title;
  final double amount;
  final DateTime txdate;

  Trans(
      {@required this.id,
      @required this.title,
      @required this.amount,
      @required this.txdate});
}

Penjelasan Code trans.dart

trans.dart adalah class untuk mendefinisikan isi transaksi expense. Memiliki empat property yaitu id, title, amount dan date.

Constructor Trans akan mengisi nilai property tersebut. Digunakan @required untuk menunjukan bahwa parameter ini wajib. @required diperoleh dari library foundation.dart, oleh karena itu harus diimport.

Penjelasan Code main.dart

Import library yang diperlukan, yaitu material.dart dan intl.dart, kita juga menggunakan class untuk menyimpan transaksi expense.

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import './trans.dart';

Fungsi main, fungsi utama dari dart akan memanggil MyApp().

void main() => runApp(MyApp());

Class MyApp adalah stateless widget, yang akan memanggil build method dengan property home yang akan diisi dari hasil return class MyHomePage().

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

Class MyHomePage berisi struktur widget dari aplikasi. Tidak akan dibahas property dan styling widget, karena dapat dilihat dengan detail di flutter widget catalog. Kita akan soroti beberapa bagian penting saja.

Code dibawah adalah untuk membuat data expense dengan menggunakan class trans.dat. Untuk saat ini data yang digunakan adalah data dummy, agar kita bisa melakukan desain useri interface.

final List<Trans> trans = [
    Trans(
        id: 'a001',
        title: 'Notebook Aspire A5',
        amount: 8200000,
        txdate: DateTime.now()),
    Trans(
        id: 'a002',
        title: 'Samsung Galaxy A5',
        amount: 3200000,
        txdate: DateTime.now()),
  ];

Variable titleCtrl dan amountCtrl adalah TextEditingController yang digunakan untuk mendapatkan value yang diisi oleh user pada widget TextField.

final titleCtrl = TextEditingController();
final amountCtrl = TextEditingController();
TextField(
  decoration: InputDecoration(labelText: 'Title'),
  controller: titleCtrl,
),
TextField(
  decoration: InputDecoration(labelText: 'Amount'),
  controller: amountCtrl,
),

NumberFormat adalah fungsi yang digunakan untuk melakukan formating dari package yang kita install (intl.dart). Silakan lihat dokumentasi detail di https://api.flutter.dev/flutter/intl/intl-library.html.

NumberFormat kita gunakan pada bagian menampilkan amount dari expense dan date formating agar bisa dibaca lebih nyaman.

NumberFormat.currency(symbol: 'Rp. ', decimalDigits: 0).format(trx.amount),
Text(DateFormat.yMMMd().format(trx.txdate), style: TextStyle(fontSize: 10, color: Colors.grey),),

Kesimpulan

Aplikasi kita akan menerima expense dari user input, lalu ditampilkan dalam list dan chart.

Kita akan memisahkan aplikasi kedalam beberapa widget yaitu: widget untuk menangani list expense, form expense.

Perubahan diatas akan kita lakukan pada Part 2.

Sharing is caring:

Leave a Comment