· 5 years ago · Nov 25, 2020, 07:38 PM
1import 'package:flutter/material.dart';
2import 'package:flutter/widgets.dart';
3import 'controls/apiClient.dart';
4import 'controls/databaseClient.dart';
5import 'models/dog.dart';
6
7void main() => runApp(MyApp());
8
9class MyApp extends StatelessWidget {
10 @override
11 Widget build(BuildContext context) {
12 return MaterialApp(
13 theme: ThemeData(
14 primarySwatch: Colors.cyan,
15 ),
16 home: DogPage(),
17 );
18 }
19}
20
21class DogPage extends StatefulWidget {
22 @override
23 _DogPageState createState() => _DogPageState();
24}
25
26class _DogPageState extends State<DogPage> {
27 final GlobalKey<FormState> _formStateKey = GlobalKey<FormState>();
28
29 final _scaffoldKey = GlobalKey<ScaffoldState>();
30
31 Future<List<Dog>> dogs;
32
33 List<Dog> dogsFromApi;
34 List<Dog> dogsFromDb;
35
36 String _dogId;
37 String _dogName;
38 int _dogAge;
39
40 bool isUpdate = false;
41
42 String dogIdForUpdate;
43
44 DatabaseClient db;
45
46 ApiClient api;
47
48 final _dogIdController = TextEditingController();
49 final _dogNameController = TextEditingController();
50 final _dogAgeController = TextEditingController();
51
52 @override
53 void initState() {
54 super.initState();
55 db = DatabaseClient();
56 api = ApiClient();
57 openDatabase();
58 }
59
60 openDatabase() async {
61 await db.open();
62 await refreshDogList();
63 }
64
65 refreshDogList() {
66 setState(() {
67 dogs = db.getDogs();
68 });
69 }
70
71 Future<Dog> uploadOnApi(dog) async {
72 try {
73 Dog newDog = await api.insertDog(dog);
74
75 final snackBar = SnackBar(
76 content: Text('Dados enviados com sucesso para a API!'),
77 duration: Duration(milliseconds: 500),
78 backgroundColor: Colors.green,
79 );
80
81 _scaffoldKey.currentState.showSnackBar(snackBar);
82
83 return newDog;
84 }
85 catch (error) {
86 final snackBar = SnackBar(
87 content: Text('Erro ao enviar dado para a API!'),
88 duration: Duration(milliseconds: 500),
89 backgroundColor: Colors.red,
90 );
91 _scaffoldKey.currentState.showSnackBar(snackBar);
92
93 return null;
94 }
95 }
96
97 uploadOnDb(dog) async {
98 try {
99 await db.insertDog(dog);
100 final snackBar = SnackBar(
101 content: Text('Dados enviados com sucesso para a BD!'),
102 duration: Duration(milliseconds: 500),
103 backgroundColor: Colors.green,
104 );
105 _scaffoldKey.currentState.showSnackBar(snackBar);
106 }
107 catch (error) {
108 final snackBar = SnackBar(
109 content: Text('Erro ao enviar dado para o BD!'),
110 duration: Duration(milliseconds: 500),
111 backgroundColor: Colors.red,
112 );
113 _scaffoldKey.currentState.showSnackBar(snackBar);
114 }
115 }
116
117 deleteOnApi(Dog dog) async {
118 try {
119 await api.deleteDog(dog.id);
120 final snackBar = SnackBar(
121 content: Text('Dado removido com sucesso da API!'),
122 duration: Duration(milliseconds: 500),
123 backgroundColor: Colors.green,
124 );
125 _scaffoldKey.currentState.showSnackBar(snackBar);
126 }
127 catch (error) {
128 final snackBar = SnackBar(
129 content: Text('Erro ao remover dado da API!'),
130 duration: Duration(milliseconds: 500),
131 backgroundColor: Colors.red,
132 );
133 _scaffoldKey.currentState.showSnackBar(snackBar);
134 }
135 }
136
137 deleteOnDb(Dog dog) async {
138 try {
139 await db.deleteDog(dog.id);
140 final snackBar = SnackBar(
141 content: Text('Dado removido com sucesso do BD!'),
142 duration: Duration(milliseconds: 500),
143 backgroundColor: Colors.green,
144 );
145 _scaffoldKey.currentState.showSnackBar(snackBar);
146 }
147 catch (error) {
148 final snackBar = SnackBar(
149 content: Text('Erro ao remover dado do BD!'),
150 duration: Duration(milliseconds: 500),
151 backgroundColor: Colors.red,
152 );
153 _scaffoldKey.currentState.showSnackBar(snackBar);
154 }
155 }
156
157 Future<Dog> updateOnApi(Dog dog) async {
158 try {
159 Dog newDog = await api.updateDog(dog);
160
161 final snackBar = SnackBar(
162 content: Text('Dado atualizado com sucesso da API!'),
163 duration: Duration(milliseconds: 500),
164 backgroundColor: Colors.green,
165 );
166 _scaffoldKey.currentState.showSnackBar(snackBar);
167
168 return newDog;
169 }
170 catch (error) {
171 final snackBar = SnackBar(
172 content: Text('Erro ao atualizar dado na API!'),
173 duration: Duration(milliseconds: 500),
174 backgroundColor: Colors.red,
175 );
176 _scaffoldKey.currentState.showSnackBar(snackBar);
177
178 return null;
179 }
180 }
181
182 updateOnDb(Dog dog) async {
183 try {
184 await db.updateDog(dog);
185 final snackBar = SnackBar(
186 content: Text('Dado atualizado com sucesso do BD!'),
187 duration: Duration(milliseconds: 500),
188 backgroundColor: Colors.green,
189 );
190 _scaffoldKey.currentState.showSnackBar(snackBar);
191 }
192 catch (error) {
193 final snackBar = SnackBar(
194 content: Text('Erro ao atualizar dado no BD!'),
195 duration: Duration(milliseconds: 500),
196 backgroundColor: Colors.red,
197 );
198 _scaffoldKey.currentState.showSnackBar(snackBar);
199 }
200 }
201
202 downloadFromApi() async {
203 var errorDownload = false;
204
205 try {
206 dogsFromApi = await api.getDogs();
207
208 final snackBar = SnackBar(
209 content: Text('Dados lidos com sucesso na API!'),
210 duration: Duration(milliseconds: 500),
211 backgroundColor: Colors.green,
212 );
213 _scaffoldKey.currentState.showSnackBar(snackBar);
214 }
215 catch (erro) {
216 errorDownload = true;
217
218 final snackBar = SnackBar(
219 content: Text('Erro ao comunicar com a API!'),
220 duration: Duration(milliseconds: 500),
221 backgroundColor: Colors.red,
222 );
223 _scaffoldKey.currentState.showSnackBar(snackBar);
224 }
225
226 if (errorDownload == false) {
227 await db.deleteAllDogs();
228 await db.insertDogs(dogsFromApi);
229 refreshDogList();
230
231 final snackBar = SnackBar(
232 content: Text('Dados armazenados com sucesso no BD!'),
233 duration: Duration(milliseconds: 500),
234 backgroundColor: Colors.green,
235 );
236 _scaffoldKey.currentState.showSnackBar(snackBar);
237 }
238 }
239
240 @override
241 Widget build(BuildContext context) {
242 return Scaffold(
243 key: _scaffoldKey,
244 appBar: AppBar(title: Text('App Dog'), actions: <Widget>[
245 Padding(
246 padding: EdgeInsets.only(right: 20.0),
247 child: GestureDetector(
248 onTap: () {
249 downloadFromApi();
250 },
251 child: Icon(Icons.cloud_download),
252 )),
253 ]),
254
255 body: Column(
256 children: <Widget>[
257 Form(
258 key: _formStateKey,
259 autovalidate: true,
260 child: Column(
261 children: <Widget>[
262 Padding(
263 padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
264 child: TextFormField(
265 enabled: false,
266 onSaved: (value) {
267 _dogId = value;
268 },
269 controller: _dogIdController,
270 keyboardType: TextInputType.number,
271 decoration: InputDecoration(
272 disabledBorder: new UnderlineInputBorder(
273 borderSide: new BorderSide(
274 color: Colors.grey,
275 width: 2,
276 style: BorderStyle.solid)),
277 labelText: "Id do cachorro",
278 icon: Icon(
279 Icons.vpn_key,
280 color: Colors.grey,
281 ),
282 fillColor: Colors.white,
283 labelStyle: TextStyle(
284 color: Colors.grey,
285 )),
286 ),
287 ),
288
289 Padding(
290 padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
291 child: TextFormField(
292 validator: (value) {
293 if (value.isEmpty) {
294 return 'Por favor insira o nome do cachorro';
295 }
296 if (value.trim() == "")
297 return "Somente espaço não é válido!";
298 return null;
299 },
300 onSaved: (value) {
301 _dogName = value;
302 },
303 controller: _dogNameController,
304 decoration: InputDecoration(
305 focusedBorder: new UnderlineInputBorder(
306 borderSide: new BorderSide(
307 color: Colors.cyan,
308 width: 2,
309 style: BorderStyle.solid)),
310 labelText: "Nome do cachorro",
311 icon: Icon(
312 Icons.pets,
313 color: Colors.cyan,
314 ),
315 fillColor: Colors.white,
316 labelStyle: TextStyle(
317 color: Colors.cyan,
318 )),
319 ),
320 ),
321
322 Padding(
323 padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
324 child: TextFormField(
325 validator: (value) {
326 if (value.isEmpty) {
327 return 'Por favor insira a idade do cachorro';
328 }
329 if (value.trim() == "")
330 return "Somente espaço não é válido!";
331 return null;
332 },
333 onSaved: (value) {
334 _dogAge = int.parse(value);
335 },
336 controller: _dogAgeController,
337 keyboardType: TextInputType.number,
338 decoration: InputDecoration(
339 focusedBorder: new UnderlineInputBorder(
340 borderSide: new BorderSide(
341 color: Colors.cyan,
342 width: 2,
343 style: BorderStyle.solid)),
344 labelText: "Idade do cachorro",
345 icon: Icon(
346 Icons.calendar_today,
347 color: Colors.cyan,
348 ),
349 fillColor: Colors.white,
350 labelStyle: TextStyle(
351 color: Colors.cyan,
352 )),
353 ),
354 ),
355 ],
356 ),
357 ),
358
359 Row(
360 mainAxisAlignment: MainAxisAlignment.center,
361 children: <Widget>[
362 RaisedButton(
363 color: Colors.cyan,
364 child: Text(
365 (isUpdate ? 'ATUALIZAR' : 'ADICIONAR'),
366 style: TextStyle(color: Colors.white),
367 ),
368 onPressed: () async {
369 FocusScope.of(context).requestFocus(new FocusNode());
370
371 if (isUpdate) {
372 if (_formStateKey.currentState.validate()) {
373 _formStateKey.currentState.save();
374 try {
375 Dog dog = Dog(
376 id: dogIdForUpdate, name: _dogName, age: _dogAge);
377
378 await updateOnDb(await updateOnApi(dog));
379 refreshDogList();
380 setState(() {
381 isUpdate = false;
382 });
383 }
384 catch (error) {
385 print(error);
386 final snackBar = SnackBar(
387 content: Text('Erro ao comunicar com a API!'),
388 duration: Duration(milliseconds: 500),
389 backgroundColor: Colors.red,
390 );
391 _scaffoldKey.currentState.showSnackBar(snackBar);
392 }
393 }
394 }
395 else {
396 if (_formStateKey.currentState.validate()) {
397 _formStateKey.currentState.save();
398 try {
399 Dog dog = Dog(id: _dogId, name: _dogName, age: _dogAge);
400 await uploadOnDb(await uploadOnApi(dog));
401
402 refreshDogList();
403 }
404 catch (error) {
405 final snackBar = SnackBar(
406 content: Text('Erro ao comunicar com a API!'),
407 duration: Duration(milliseconds: 500),
408 backgroundColor: Colors.red,
409 );
410 _scaffoldKey.currentState.showSnackBar(snackBar);
411 }
412 }
413 }
414 _dogIdController.text = '';
415 _dogNameController.text = '';
416 _dogAgeController.text = '';
417 },
418 ),
419 Padding(
420 padding: EdgeInsets.all(10),
421 ),
422 RaisedButton(
423 color: Colors.red,
424 child: Text(
425 (isUpdate ? 'CANCELAR ATUALIZAÇÃO' : 'LIMPAR'),
426 style: TextStyle(color: Colors.white),
427 ),
428 onPressed: () {
429 _dogIdController.text = '';
430 _dogNameController.text = '';
431 _dogAgeController.text = '';
432
433 setState(() {
434 isUpdate = false;
435 dogIdForUpdate = null;
436 });
437 },
438 ),
439 ],
440 ),
441 const Divider(
442 height: 20.0,
443 ),
444 Expanded(
445 child: FutureBuilder(
446 future: dogs,
447 builder: (context, snapshot) {
448 print(snapshot.connectionState);
449 if (snapshot.data == null || snapshot.data.length == 0) {
450 return Text('Sem dados para exibir');
451 }
452 else if (snapshot.hasData) {
453 return generateList(snapshot.data);
454 }
455 return CircularProgressIndicator();
456 },
457 ),
458 ),
459 ],
460 ),
461 );
462 }
463
464 SingleChildScrollView generateList(List<Dog> dogs) {
465 return SingleChildScrollView(
466 scrollDirection: Axis.vertical,
467 child: SingleChildScrollView(
468 scrollDirection: Axis.horizontal,
469 child: DataTable(
470 columns: [
471 DataColumn(
472 label: Text('ID', style: TextStyle(fontStyle: FontStyle.italic)),
473 ),
474 DataColumn(
475 label:
476 Text('NOME', style: TextStyle(fontStyle: FontStyle.italic)),
477 ),
478 DataColumn(
479 label:
480 Text('IDADE', style: TextStyle(fontStyle: FontStyle.italic)),
481 ),
482 DataColumn(
483 label: Text('DELETAR',
484 style: TextStyle(fontStyle: FontStyle.italic)),
485 )
486 ],
487 rows: dogs
488 .map(
489 (dog) => DataRow(
490 cells: [
491 DataCell(
492 Text(dog.id.toString()),
493 onTap: () {
494 setState(() {
495 isUpdate = true;
496 dogIdForUpdate = dog.id;
497 });
498 _dogIdController.text = dog.id.toString();
499 _dogNameController.text = dog.name;
500 _dogAgeController.text = dog.age.toString();
501 },
502 ),
503 DataCell(
504 Text(dog.name),
505 onTap: () {
506 setState(() {
507 isUpdate = true;
508 dogIdForUpdate = dog.id;
509 });
510 _dogIdController.text = dog.id.toString();
511 _dogNameController.text = dog.name;
512 _dogAgeController.text = dog.age.toString();
513 },
514 ),
515 DataCell(
516 Text(dog.age.toString()),
517 onTap: () {
518 setState(() {
519 isUpdate = true;
520 dogIdForUpdate = dog.id;
521 });
522 _dogIdController.text = dog.id.toString();
523 _dogNameController.text = dog.name;
524 _dogAgeController.text = dog.age.toString();
525 },
526 ),
527 DataCell(
528 IconButton(
529 icon: Icon(Icons.delete),
530 onPressed: () {
531 try {
532 deleteOnApi(dog);
533 deleteOnDb(dog);
534 refreshDogList();
535 }
536 catch (error) {
537 final snackBar = SnackBar(
538 content: Text('Erro ao comunicar com a API!'),
539 duration: Duration(milliseconds: 500),
540 backgroundColor: Colors.red,
541 );
542 _scaffoldKey.currentState.showSnackBar(snackBar);
543 }
544 },
545 ),
546 ),
547 ],
548 ),
549 )
550 .toList(),
551 ),
552 ),
553 );
554 }
555}
556