Skip to content

Instantly share code, notes, and snippets.

@ulyanovn
Last active December 6, 2018 08:41
Show Gist options
  • Save ulyanovn/54be5939875a84be2e3c895324bc2215 to your computer and use it in GitHub Desktop.
Save ulyanovn/54be5939875a84be2e3c895324bc2215 to your computer and use it in GitHub Desktop.
Flutter Finance Workshop
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class CategoryListPage extends StatelessWidget {
@override
Widget build(BuildContext context) =>
Scaffold(
appBar: AppBar(
title: Text("Category List"),
),
body: StreamBuilder(
stream: Firestore.instance.collection('categories').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) =>
(!snapshot.hasData) ? Text('Loading...') :
(snapshot.data == null) ? Text('No categories') :
ListView(
addRepaintBoundaries: true,
children: snapshot.data.documents.map((document) =>
ListTile(
title: Text(document.data['name']),
)
).toList(),
),
),
);
}
import 'package:flutter/material.dart';
import 'spent_widget.dart';
import 'spent_list_widget.dart';
import 'category_list_widget.dart';
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<HomePage> {
int _currentIndex = 0;
final List<Widget> _children = [
SpentPage(),
SpentListPage(),
CategoryListPage()
];
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
@override
Widget build(BuildContext context) =>
Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.plus_one),
title: Text("Add spend"),
),
BottomNavigationBarItem(
icon: Icon(Icons.donut_large),
title: Text("Spendings"),
),
BottomNavigationBarItem(
icon: Icon(Icons.donut_large),
title: Text("Graph"),
),
],
onTap: onTabTapped,
currentIndex: _currentIndex,
),
);
}
import 'package:flutter/material.dart';
import 'home_widget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class SpentListPage extends StatelessWidget {
final activityIcons = [
Icons.fastfood,
Icons.gamepad,
Icons.airplanemode_active,
];
@override
Widget build(BuildContext context) =>
Scaffold(
appBar: AppBar(
title: Text("Spending List"),
),
body: StreamBuilder(
stream: Firestore.instance.collection('transactions')
.orderBy("time", descending: true)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) =>
(!snapshot.hasData) ? Text('Loading...') :
ListView(
addRepaintBoundaries: true,
children: snapshot.data.documents.map((document) =>
ListTile(
leading: Icon(activityIcons[document['type']]),
title: Text(document['sum'].toString()),
subtitle: Text(document['comment']),
),
).toList(),
),
),
);
}
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'Transactions.dart';
class SpentPage extends StatefulWidget {
SpentPage({Key key}) : super(key: key);
@override
_SpentPageState createState() => _SpentPageState();
}
class _SpentPageState extends State<SpentPage> {
final _formKey = GlobalKey<FormState>();
final myController = TextEditingController();
final commentController = TextEditingController();
final List _cities = [
"Fun",
"Dining Out",
"Travel"
];
List<DropdownMenuItem<String>> _dropDownMenuItems;
String _currentCat;
@override
void initState() {
_dropDownMenuItems = [DropdownMenuItem(value: "Loading...", child: Text( "Loading..."))];
_currentCat = _dropDownMenuItems[0].value;
getDropDownMenuItems().then((val) {
setState(() {
_dropDownMenuItems = val;
_currentCat = val[0].value;
});
});
super.initState();
}
@override
void dispose() {
// Clean up the controller when the Widget is disposed
myController.dispose();
super.dispose();
}
// here we are creating the list needed for the DropDownButton
Future<List<DropdownMenuItem<String>>> getDropDownMenuItems() async {
List<DropdownMenuItem<String>> items = List();
QuerySnapshot docs = await Firestore.instance.collection('categories').orderBy("name").getDocuments();
docs.documents.forEach((document) {
items.add(DropdownMenuItem(value: document['name'], child: Text(document['name'])));
});
return items;
}
void changedDropDownItem(String selectedCat) {
setState(() {
_currentCat = selectedCat;
});
}
void _onSubmit() {
if (_formKey.currentState.validate()) {
CollectionReference dbReplies = Firestore.instance.collection('transactions');
Transactions _transactionObj = new Transactions(
comment: commentController.text,
sum: double.tryParse(myController.text),
type: _cities.indexOf(_currentCat),
time: DateTime
.now()
.millisecondsSinceEpoch,
);
Firestore.instance.runTransaction((Transaction tx) async {
await dbReplies.add(_transactionObj.toJson());
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Spent added!")));
});
}
}
@override
Widget build(BuildContext context) =>
Scaffold(
appBar: AppBar(
title: Text("Spending"),
),
body: Center(
child: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextFormField(
controller: myController,
decoration: InputDecoration(labelText: "Spending sum:"),
validator: (value) {
if (value.isEmpty) {
return "You must spend something :)";
} else if (int.tryParse(value) == null) {
return "Spending must be a number.";
}
},
keyboardType: TextInputType.number,
),
Container(
width: MediaQuery.of(context).size.width,
child: DropdownButton(
isExpanded: true,
value: _currentCat,
items: _dropDownMenuItems,
onChanged: changedDropDownItem,
),
),
TextFormField(
controller: commentController,
decoration: InputDecoration(labelText: "Comment:"),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 30),
child: RaisedButton(
child: Icon(Icons.plus_one),
onPressed: _onSubmit
),
),
],
),
),
),
),
);
}
import 'package:meta/meta.dart';
class Transactions {
final String comment;
final int type;
final double sum;
final int time;
Transactions({
@required this.comment,
@required this.type,
@required this.sum,
@required this.time,
});
Map<String, dynamic> toJson() =>
{
'comment': comment,
'type': type,
'sum': sum,
'time': time,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment