Post Detail

Post #96

Flutter Jour Quatre Part 1

Flutter Jour Quatre

Fin PDF 2

Le Fichier main.dart

  1/// main.dart
  2
  3import 'package:depenses/widgets/transaction_list.dart';
  4import 'package:flutter/material.dart';
  5
  6import './models/transaction.dart';
  7
  8import './widgets/new_transaction.dart';
  9import './widgets/chart.dart';
 10
 11void main() => runApp(MyApp());
 12
 13class MyApp extends StatelessWidget {
 14  @override
 15  Widget build(BuildContext context) {
 16    return MaterialApp(
 17      title: 'Dépenses personnelles',
 18      theme: ThemeData(
 19        primarySwatch: Colors.purple,
 20        accentColor: Colors.amber,
 21        errorColor: Colors.red,
 22        fontFamily: 'Quicksand',
 23        appBarTheme: AppBarTheme(
 24          textTheme: ThemeData.light().textTheme.copyWith(
 25                title: TextStyle(
 26                  fontFamily: 'OpenSans',
 27                  fontWeight: FontWeight.bold,
 28                  fontSize: 18,
 29                ),
 30                button: TextStyle(
 31                  color: Colors.white,
 32                ),
 33              ),
 34        ),
 35      ),
 36      home: MyHomePage(),
 37    );
 38  }
 39}
 40
 41class MyHomePage extends StatefulWidget {
 42  @override
 43  _MyHomePageState createState() => _MyHomePageState();
 44}
 45
 46class _MyHomePageState extends State<MyHomePage> {
 47  final titleController = TextEditingController();
 48  final amountController = TextEditingController();
 49
 50  List<Transaction> get _recentTransactions {
 51    return _userTransactions.where((transaction) {
 52      return transaction.date.isAfter(
 53        DateTime.now().subtract(
 54          Duration(days: 7),
 55        ),
 56      );
 57    }).toList();
 58  }
 59
 60  final List<Transaction> _userTransactions = [
 61    Transaction(
 62      id: 't1',
 63      title: 'Chaussures',
 64      amount: 169.99,
 65      date: DateTime.now(),
 66    ),
 67    Transaction(
 68      id: 't2',
 69      title: 'Courses',
 70      amount: 128.50,
 71      date: DateTime.now(),
 72    ),
 73  ];
 74
 75  void _addNewTransaction(
 76      String newTitle, double newAmount, DateTime chosenDate) {
 77    final newTransaction = Transaction(
 78        title: newTitle,
 79        amount: newAmount,
 80        date: chosenDate,
 81        id: DateTime.now().toString());
 82
 83    setState(() {
 84      _userTransactions.add(newTransaction);
 85    });
 86  }
 87
 88  void _deleteTransaction(String id) {
 89    setState(() {
 90      _userTransactions.removeWhere((transaction) => transaction.id == id);
 91    });
 92  }
 93
 94  void _startAddNewTransaction(BuildContext context) {
 95    showModalBottomSheet(
 96        context: context,
 97        builder: (_) {
 98          return NewTransaction(_addNewTransaction);
 99        });
100  }
101
102  @override
103  Widget build(BuildContext context) {
104    return Scaffold(
105      appBar: AppBar(
106        title: Text('Dépenses personnelles'),
107        actions: <Widget>[
108          IconButton(
109            icon: Icon(Icons.add),
110            onPressed: () => _startAddNewTransaction(context),
111          ),
112        ],
113      ),
114      body: SingleChildScrollView(
115        child: Column(
116          mainAxisAlignment: MainAxisAlignment.start,
117          crossAxisAlignment: CrossAxisAlignment.stretch,
118          children: <Widget>[
119            Chart(_recentTransactions),
120            TransactionList(_userTransactions, _deleteTransaction),
121          ],
122        ),
123      ),
124      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
125      floatingActionButton: FloatingActionButton(
126        child: Icon(
127          Icons.add,
128        ),
129        onPressed: () => _startAddNewTransaction(context),
130      ),
131    );
132  }
133}

Le Fichier new_transaction.dart

  1/// ./widgets/new_transaction.dart
  2
  3import 'package:flutter/material.dart';
  4import 'package:intl/intl.dart';
  5
  6class NewTransaction extends StatefulWidget {
  7  final Function addNewTransaction;
  8
  9  NewTransaction(this.addNewTransaction);
 10
 11  @override
 12  _NewTransactionState createState() => _NewTransactionState();
 13}
 14
 15class _NewTransactionState extends State<NewTransaction> {
 16  final _titleController = TextEditingController();
 17  final _amountController = TextEditingController();
 18  DateTime _selectedDate;
 19
 20  void submitData() {
 21    if (_amountController.text.isEmpty) {
 22      return;
 23    }
 24    final enteredTitle = _titleController.text;
 25    final enteredAmount = double.parse(_amountController.text);
 26    if (enteredTitle.isEmpty || enteredAmount <= 0 || _selectedDate == null) {
 27      return;
 28    }
 29    widget.addNewTransaction(
 30      enteredTitle,
 31      enteredAmount,
 32      _selectedDate,
 33    );
 34    Navigator.of(context).pop();
 35  }
 36
 37  void _presentDatePicker() {
 38    showDatePicker(
 39      context: context,
 40      initialDate: DateTime.now(),
 41      firstDate: DateTime(DateTime.now().year),
 42      lastDate: DateTime.now(),
 43    ).then((pickedDate) {
 44      if (pickedDate == null) {
 45        return;
 46      }
 47      setState(() {
 48        _selectedDate = pickedDate;
 49      });
 50    });
 51  }
 52
 53  @override
 54  Widget build(BuildContext context) {
 55    return Card(
 56      child: Container(
 57        padding: EdgeInsets.all(10),
 58        child: Column(
 59          crossAxisAlignment: CrossAxisAlignment.end,
 60          children: <Widget>[
 61            TextField(
 62              decoration: InputDecoration(
 63                labelText: 'Titre',
 64              ),
 65              controller: _titleController,
 66              onSubmitted: (_) => submitData(),
 67            ),
 68            TextField(
 69              decoration: InputDecoration(
 70                labelText: 'Montant',
 71              ),
 72              controller: _amountController,
 73              keyboardType: TextInputType.number,
 74              onSubmitted: (_) => submitData(),
 75            ),
 76            Container(
 77              height: 70,
 78              child: Row(
 79                children: <Widget>[
 80                  Text(
 81                    _selectedDate == null
 82                        ? 'Aucune date choisie!'
 83                        : 'Date sélectionnée: ${DateFormat('d.M.y').format(_selectedDate)}',
 84                  ),
 85                  FlatButton(
 86                    textColor: Theme.of(context).primaryColor,
 87                    child: Text(
 88                      'Choisir une date',
 89                      style: TextStyle(
 90                        fontWeight: FontWeight.bold,
 91                      ),
 92                    ),
 93                    onPressed: _presentDatePicker,
 94                  ),
 95                ],
 96              ),
 97            ),
 98            RaisedButton(
 99              child: Text(
100                'Add Transaction',
101              ),
102              color: Theme.of(context).primaryColor,
103              textColor: Theme.of(context).textTheme.button.color,
104              onPressed: submitData,
105            ),
106          ],
107        ),
108      ),
109    );
110  }
111}

Le Fichier transaction_list.dart

 1/// ./widgets/transaction_list.dart
 2
 3import 'package:flutter/material.dart';
 4import 'package:intl/intl.dart';
 5
 6import '../models/transaction.dart';
 7
 8class TransactionList extends StatelessWidget {
 9  final List<Transaction> transactions;
10  final Function deleteTransaction;
11
12  TransactionList(this.transactions, this.deleteTransaction);
13
14  @override
15  Widget build(BuildContext context) {
16    return Container(
17      height: 450,
18      child: ListView.builder(
19        itemBuilder: (context, index) {
20          return Card(
21            elevation: 5,
22            margin: EdgeInsets.symmetric(
23              vertical: 8,
24              horizontal: 5,
25            ),
26            child: ListTile(
27              leading: CircleAvatar(
28                radius: 30,
29                child: Padding(
30                  padding: EdgeInsets.all(6),
31                  child: FittedBox(
32                    child: Text(
33                      '\$${transactions[index].amount.toStringAsFixed(2)}',
34                    ),
35                  ),
36                ),
37              ),
38              title: Text(
39                transactions[index].title,
40                style: Theme.of(context).textTheme.title,
41              ),
42              subtitle: Text(
43                DateFormat('d.M.y').format(transactions[index].date),
44              ),
45              trailing: IconButton(
46                icon: Icon(Icons.delete),
47                color: Theme.of(context).errorColor,
48                onPressed: () => deleteTransaction(transactions[index].id),
49              ),
50            ),
51          );
52        },
53        itemCount: transactions.length,
54      ),
55    );
56  }
57}

Le Fichier char.dart

 1/// ./widgets/char.dart
 2
 3import 'package:flutter/material.dart';
 4import 'package:intl/intl.dart';
 5
 6import '../models/transaction.dart';
 7import './char_bar.dart';
 8
 9class Chart extends StatelessWidget {
10  final List<Transaction> recentTransactions;
11
12  Chart(this.recentTransactions);
13
14  List<Map<String, Object>> get groupedTransactionValues {
15    return List.generate(7, (index) {
16      final weekDay = DateTime.now().subtract(
17        Duration(days: index),
18      );
19
20      var totalSum = 0.0;
21      for (var i = 0; i < recentTransactions.length; i++) {
22        if (recentTransactions[i].date.day == weekDay.day &&
23            recentTransactions[i].date.month == weekDay.month &&
24            recentTransactions[i].date.year == weekDay.year) {
25          totalSum += recentTransactions[i].amount;
26        }
27      }
28
29      return {
30        'day': DateFormat.E().format(weekDay).substring(0, 1),
31        'amount': totalSum
32      };
33    }).reversed.toList();
34  }
35
36  double get totalSpending {
37    return groupedTransactionValues.fold(0.0, (sum, item) {
38      return sum + item['amount'];
39    });
40  }
41
42  @override
43  Widget build(BuildContext context) {
44    print(groupedTransactionValues);
45
46    return Card(
47      elevation: 6,
48      margin: EdgeInsets.all(20),
49      child: Padding(
50        padding: EdgeInsets.all(10),
51        child: Row(
52          children: groupedTransactionValues.map((data) {
53            return Flexible(
54              fit: FlexFit.tight,
55              child: ChartBar(
56                data['day'],
57                data['amount'],
58                (data['amount'] as double) / totalSpending,
59              ),
60            );
61          }).toList(),
62        ),
63      ),
64    );
65  }
66}

Le Fichier char_bar.dart

 1/// ./widgets/char_bar.dart
 2
 3import 'package:flutter/material.dart';
 4
 5class ChartBar extends StatelessWidget {
 6  final String label;
 7  final double spendingAmount;
 8  final double spendingPercentageOfTotal;
 9
10  ChartBar(this.label, this.spendingAmount, this.spendingPercentageOfTotal);
11
12  @override
13  Widget build(BuildContext context) {
14    return Column(
15      children: <Widget>[
16        Container(
17          height: 20,
18          child: FittedBox(
19            child: Text('\$${spendingAmount.toStringAsFixed(0)}'),
20          ),
21        ),
22        SizedBox(
23          height: 4,
24        ),
25        Container(
26          height: 60,
27          width: 10,
28          child: Stack(
29            children: <Widget>[
30              Container(
31                decoration: BoxDecoration(
32                  border: Border.all(color: Colors.grey, width: 1.0),
33                  color: Color.fromRGBO(220, 220, 220, 1),
34                  borderRadius: BorderRadius.circular(10),
35                ),
36              ),
37              Container(
38                alignment: Alignment.bottomLeft,
39                child: FractionallySizedBox(
40                  heightFactor: spendingPercentageOfTotal,
41                  child: Container(
42                    decoration: BoxDecoration(
43                      color: Theme.of(context).primaryColor,
44                      borderRadius: BorderRadius.circular(10),
45                    ),
46                  ),
47                ),
48              ),
49            ],
50          ),
51        ),
52        SizedBox(
53          height: 4,
54        ),
55        Text(label),
56      ],
57    );
58  }
59}