diff --git a/lib/database/app_database.dart b/lib/database/app_database.dart index 638dd6e..e66ea6f 100644 --- a/lib/database/app_database.dart +++ b/lib/database/app_database.dart @@ -1,49 +1,18 @@ -import 'package:byte_banck/models/contact.dart'; +import 'package:byte_banck/database/dao/contact_dao.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; -Future createDatabase() { +Future getDatabase() { return getDatabasesPath().then((dbPath) { final String path = join(dbPath, 'bytebanck.db'); return openDatabase( path, onCreate: (database, version) { - database.execute('CREATE TABLE contacts( ' - 'id INTEGER PRIMARY KEY, ' - 'full_name TEXT, ' - 'account_number INTEGER)'); + database.execute(ContactDao.tableSql); }, version: 1, - onDowngrade: onDatabaseDowngradeDelete, ); }); } -Future save(Contact contact) { - return createDatabase().then((database) { - Map contactMap = {}; - contactMap['full_name'] = contact.fullName; - contactMap['account_number'] = contact.accountNumber; - return database.insert('contacts', contactMap); - }); -} -Future> findAll() { - return createDatabase().then((database) { - return database.query('contacts').then((maps) { - { - List contacts = []; - for (Map map in maps) { - contacts.add( - Contact( - map['id'], - map['full_name'], - map['account_number'], - ), - ); - } - return contacts; - } - }); - }); -} diff --git a/lib/database/dao/contact_dao.dart b/lib/database/dao/contact_dao.dart new file mode 100644 index 0000000..79faede --- /dev/null +++ b/lib/database/dao/contact_dao.dart @@ -0,0 +1,48 @@ +import 'package:byte_banck/models/contact.dart'; + +import '../app_database.dart'; +import 'package:sqflite_common/sqlite_api.dart'; + +class ContactDao { + static const String _tableName = 'contacts'; + static const String _id = 'id'; + static const String _fullName = 'full_name'; + static const String _accountNumber = 'account_number'; + + static const String tableSql = 'CREATE TABLE $_tableName( ' + '$_id INTEGER PRIMARY KEY, ' + '$_fullName TEXT, ' + '$_accountNumber INTEGER)'; + + Future save(Contact contact) async { + final Database database = await getDatabase(); + return database.insert(_tableName, _toMap(contact)); + } + + Future> findAll() async { + final Database database = await getDatabase(); + return _toList(await database.query(_tableName)); + } + + Map _toMap(Contact contact) { + Map contactMap = { + _fullName: contact.fullName, + _accountNumber: contact.accountNumber, + }; + return contactMap; + } + + List _toList(List> maps) { + List contacts = []; + for (Map map in maps) { + contacts.add( + Contact( + id: map[_id], + fullName: map[_fullName], + accountNumber: map[_accountNumber], + ), + ); + } + return contacts; + } +} diff --git a/lib/models/contact.dart b/lib/models/contact.dart index c043ce0..7d489ec 100644 --- a/lib/models/contact.dart +++ b/lib/models/contact.dart @@ -1,13 +1,13 @@ class Contact { - final int id; + final int? id; final String fullName; final int accountNumber; - Contact( + Contact({ this.id, - this.fullName, - this.accountNumber, - ); + required this.fullName, + required this.accountNumber, + }); @override String toString() { diff --git a/lib/screans/contact_form.dart b/lib/screans/contact_form.dart index 3f4bcd9..d501351 100644 --- a/lib/screans/contact_form.dart +++ b/lib/screans/contact_form.dart @@ -1,4 +1,4 @@ -import 'package:byte_banck/database/app_database.dart'; +import 'package:byte_banck/database/dao/contact_dao.dart'; import 'package:flutter/material.dart'; import '../models/contact.dart'; @@ -13,11 +13,13 @@ class ContactForm extends StatefulWidget { class _ContactFormState extends State { final TextEditingController _fullName = TextEditingController(); - final TextEditingController _acountNumber = TextEditingController(); + final TextEditingController _accountNumber = TextEditingController(); + + final ContactDao _contactDao = ContactDao(); @override void initState() { - super.initState(); + super.initState(); } @override @@ -30,43 +32,19 @@ class _ContactFormState extends State { padding: const EdgeInsets.all(8.0), child: Column( children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: TextField( - controller: _fullName, - decoration: const InputDecoration( - labelText: 'Full name', - ), - style: const TextStyle(fontSize: 24.0), - ), + _TextField( + controller: _fullName, + labelText: 'Full name', ), - Padding( - padding: const EdgeInsets.all(8.0), - child: TextField( - keyboardType: TextInputType.number, - controller: _acountNumber, - decoration: const InputDecoration( - labelText: 'Acount number', - ), - style: const TextStyle(fontSize: 24.0), - ), + _TextField( + controller: _accountNumber, + labelText: 'Acount number', + keyboardType: TextInputType.number, ), - Padding( - padding: const EdgeInsets.all(8.0), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - textStyle: const TextStyle(fontSize: 20), - fixedSize: const Size.fromWidth( - double.maxFinite, - ), - primary: Theme.of(context).colorScheme.secondary), - onPressed: () { - final String fullName = _fullName.text; - final int acountNumbe = int.parse(_acountNumber.text); - save(Contact(0,fullName,acountNumbe)).then((id) => Navigator.pop(context)); - }, - child: const Text('Create'), - ), + _Button( + contactDao: _contactDao, + accountNumberController: _accountNumber, + fullNameController: _fullName, ) ], ), @@ -74,3 +52,77 @@ class _ContactFormState extends State { ); } } + +class _Button extends StatelessWidget { + const _Button( + {Key? key, + required this.fullNameController, + required this.accountNumberController, + required this.contactDao}) + : super(key: key); + final TextEditingController fullNameController; + + final TextEditingController accountNumberController; + + final ContactDao contactDao; + + final String _textButton = 'Create'; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20), + fixedSize: const Size.fromWidth( + double.maxFinite, + ), + primary: Theme.of(context).colorScheme.secondary), + onPressed: () => createContact(context), + child: Text(_textButton), + ), + ); + } + + void createContact(BuildContext context) { + final String fullName = fullNameController.text; + final int accountNumbe = int.parse(accountNumberController.text); + contactDao + .save(Contact( + fullName: fullName, + accountNumber: accountNumbe, + )) + .then((id) => Navigator.pop(context)); + } +} + +class _TextField extends StatelessWidget { + const _TextField({ + Key? key, + required this.controller, + this.keyboardType, + this.labelText, + this.fontSize = 24.0, + }) : super(key: key); + final TextEditingController controller; + final String? labelText; + final double fontSize; + + final TextInputType? keyboardType; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: controller, + decoration: InputDecoration( + labelText: labelText, + ), + keyboardType: keyboardType, + style: TextStyle(fontSize: fontSize), + ), + ); + } +} diff --git a/lib/screans/contact_list.dart b/lib/screans/contact_list.dart index 5726ea2..8a59203 100644 --- a/lib/screans/contact_list.dart +++ b/lib/screans/contact_list.dart @@ -1,4 +1,4 @@ -import 'package:byte_banck/database/app_database.dart'; +import 'package:byte_banck/database/dao/contact_dao.dart'; import 'package:byte_banck/models/contact.dart'; import 'package:flutter/material.dart'; @@ -12,6 +12,8 @@ class ContactsList extends StatefulWidget { } class _ContactsListState extends State { + final ContactDao _contactDao = ContactDao(); + @override Widget build(BuildContext context) { return Scaffold( @@ -19,25 +21,14 @@ class _ContactsListState extends State { title: const Text("Contacts"), ), body: FutureBuilder>( - future: findAll(), + future: _contactDao.findAll(), initialData: const [], builder: (BuildContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: break; case ConnectionState.waiting: - return Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircularProgressIndicator( - color: Theme.of(context).colorScheme.secondary, - ), - const Text('Loading'), - ], - ), - ); + return const _LoadItens(); case ConnectionState.active: break; case ConnectionState.done: @@ -55,14 +46,36 @@ class _ContactsListState extends State { }, ), floatingActionButton: FloatingActionButton( - child: const Icon(Icons.add), - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const ContactForm(), - ), - ).then((value) => setState((){})); - } + child: const Icon(Icons.add), + onPressed: () { + Navigator.of(context) + .push( + MaterialPageRoute( + builder: (context) => const ContactForm(), + ), + ) + .then((value) => setState(() {})); + }), + ); + } +} + +class _LoadItens extends StatelessWidget { + const _LoadItens({Key? key}) : super(key: key); + final String loadMessage = 'Loading'; + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator( + color: Theme.of(context).colorScheme.secondary, + ), + Text(loadMessage), + ], ), ); } diff --git a/lib/screans/dashboard.dart b/lib/screans/dashboard.dart index 7a639a3..685702b 100644 --- a/lib/screans/dashboard.dart +++ b/lib/screans/dashboard.dart @@ -5,6 +5,7 @@ import 'contact_list.dart'; class Dashboard extends StatelessWidget { const Dashboard({Key? key, required this.title}) : super(key: key); final String title; + final String _bytebanckLogo = 'images/bytebank_logo.png'; @override Widget build(BuildContext context) { @@ -18,38 +19,47 @@ class Dashboard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Image.asset('images/bytebank_logo.png'), - Material( - color: Theme.of(context).colorScheme.primary, - child: InkWell( - onTap: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const ContactsList(), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: SizedBox( - width: 150, - height: 100, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Icon(Icons.people, size: 25, color: Colors.white), - Text( - 'Contatos', - style: TextStyle(color: Colors.white), - ) - ], - ), - ), - ), - ), - ) + Image.asset(_bytebanckLogo), + const _Button(), ], ), ), ); } -} \ No newline at end of file +} + +class _Button extends StatelessWidget { + const _Button({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).colorScheme.primary, + child: InkWell( + onTap: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const ContactsList(), + ), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SizedBox( + width: 150, + height: 100, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Icon(Icons.people, size: 25, color: Colors.white), + Text( + 'Contatos', + style: TextStyle(color: Colors.white), + ) + ], + ), + ), + ), + ), + ); + } +}