Fakultas Ilmu Komputer UI

add_informasi.dart 23.3 KB
Newer Older
1
import 'dart:async';
2
3
import 'dart:io';
import 'package:bisaGo/bloc/komentar_bloc.dart';
4
import 'package:bisaGo/component/disabilitas_button_grid.dart';
5
import 'package:bisaGo/component/image_preview_holder.dart';
6
7
8
9

import 'package:bisaGo/config/strings.dart';
import 'package:bisaGo/config/styles.dart';
import 'package:bisaGo/page/login/login.dart';
10
import 'package:bisaGo/utils/custom_button.dart';
11
12
13
14
15
import 'package:bisaGo/utils/custom_alert_dialog.dart';
import 'package:bisaGo/utils/custom_dropdown.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
16
import 'package:bisaGo/utils/custom_deskripsi_field.dart';
17
import 'package:bisaGo/utils/validator.dart';
18
import 'package:flutter/services.dart';
19
20
21
22
23
24
25
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:image_picker/image_picker.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class AddInformasi extends StatefulWidget {
  final String nama;
26
  final String placeId;
27
28
29
  @override
  AddInformasiState createState() => AddInformasiState();

30
31
32
33
34
  const AddInformasi({
    this.nama,
    Key key,
    @required this.placeId,
  }) : super(key: key);
35
36
37
38
39
40
41
42
43
44
45
}

class AddInformasiState extends State<AddInformasi> {
  Map<String, dynamic> newKomentarData = {};
  KomentarBloc _bloc;
  TextEditingController deskripsiController = TextEditingController();
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final picker = ImagePicker();
  File _image;

  Future _getImage() async {
46
    final image = await picker.getImage(source: ImageSource.gallery);
47
48
49
    return File(image.path);
  }

50
  Future _getCameraImage() async {
51
52
    final image =
        await picker.getImage(source: ImageSource.camera, imageQuality: 50);
53
54
55
    return File(image.path);
  }

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  Future _clearImage() async {
    setState(() {
      _image = null;
    });
  }

  @override
  void initState() {
    super.initState();
    _jumlahFasilitas = 0;
    _fisikClicked = false;
    _intelektualClicked = false;
    _mentalClicked = false;
    _sensorikClicked = false;
    _isCounterValid = true;
    _isDisabilitasValid = true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
78
          title: const Text('Tambah Informasi'),
79
          centerTitle: true,
80
          backgroundColor: const Color(0xff3A903A),
81
82
83
84
85
        ),
        body: SingleChildScrollView(
            child: Form(
          key: _formKey,
          child: Container(
86
            margin: const EdgeInsets.symmetric(horizontal: 25.0),
87
88
89
90
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
91
                const SizedBox(height: doubleSpace),
92
93
                Text(
                  widget.nama,
94
95
                  key: const Key('Text Location Name'),
                  style: const TextStyle(
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
                    fontSize: 28,
                    fontWeight: FontWeight.w800,
                    color: Colors.black,
                    fontFamily: 'Comfortaa',
                  ),
                ),
                // GridView.count(
                //   key: Key('Input Gambar'),
                //   shrinkWrap: true,
                //   primary: false,
                //   padding: const EdgeInsets.all(10),
                //   crossAxisSpacing: 10,
                //   crossAxisCount: 2,
                //   children: <Widget>[
                //     GestureDetector(
                //       onTap: () async {
                //         var imageSelected = await _getImage();
                //         setState(() {
                //           _image = imageSelected;
                //         });
                //         },
                //       child: Container(
                //         padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0),
                //         decoration: BoxDecoration(
                //           borderRadius: BorderRadius.only(
                //             topLeft: Radius.circular(20.0),
                //             topRight: Radius.circular(20.0),
                //             bottomLeft: Radius.circular(20.0),
                //             bottomRight: Radius.circular(20.0),
                //           ),
                //           color: Colors.black12,
                //         ),
                //         child: _image == null ? Icon(FontAwesomeIcons.plus) : Image.file(_image),
                //       ),
                //     )
                //   ],
                // ),
133
                const SizedBox(height: doubleSpace),
134
135
                CustomDropdown(
                    title: 'Fasilitas / Layanan',
136
                    key: const Key('Dropdown Fasilitas Layanan'),
137
                    dropdownList: fasilitas,
138
139
140
141
142
143
144
                    validator: FieldValidator.validateDropdown,
                    hint: 'Pilih fasilitas / layanan',
                    onChanged: (value) {
                      setState(() {
                        _jenisFasilitas = value;
                      });
                    }),
145
                const SizedBox(height: 10),
146
                const Text(
147
148
149
150
                  'Jumlah fasilitas / layanan',
                  style: TextStyle(fontSize: 18),
                  textAlign: TextAlign.left,
                ),
151
                const SizedBox(height: 10),
152
153
154
                Row(
                  children: [
                    iconButton(
155
156
157
                        const Key('Button Decrement'),
                        const Icon(MdiIcons.minus,
                            color: Colors.black, size: 18),
158
159
160
                        _decrementCount,
                        30,
                        30),
161
                    const SizedBox(width: regularSpace),
162
                    Container(
163
                      key: const Key('Counter Fasilitas Layanan'),
164
165
166
167
168
169
170
171
172
173
174
175
                      alignment: Alignment.center,
                      decoration: BoxDecoration(
                          color: Colors.white,
                          boxShadow: regularShadow,
                          borderRadius: BorderRadius.circular(5.0),
                          border: Border.all(
                              color:
                                  _isCounterValid ? greenPrimary : Colors.red)),
                      height: 30,
                      width: 45,
                      child: Text(
                        _jumlahFasilitas.toString(),
176
                        style: const TextStyle(fontSize: 18.0),
177
178
                      ),
                    ),
179
                    const SizedBox(width: regularSpace),
180
                    iconButton(
181
182
183
                        const Key('Button Increment'),
                        const Icon(MdiIcons.plus,
                            color: Colors.black, size: 18),
184
185
186
187
188
189
190
                        _incrementCount,
                        30,
                        30),
                  ],
                ),
                SizedBox(height: _isCounterValid == true ? 0 : regularSpace),
                FieldValidator.validateCustomFieldAlert(_isCounterValid),
191
                const SizedBox(height: 10),
192
193
                CustomDeskripsiField(
                  title: 'Cara menggunakan',
194
                  key: const Key('Text Field Informasi'),
195
196
197
198
199
                  hint: 'Masukkan cara menggunakan',
                  onSaved: (input) {},
                  validator: FieldValidator.validateInfo,
                  controller: deskripsiController,
                ),
200
                const SizedBox(height: 10),
201
202
203
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
204
                    const Text(
205
206
207
208
                      'Foto',
                      style: TextStyle(fontSize: 18),
                      textAlign: TextAlign.left,
                    ),
209
                    TextButton(
210
                      key: const Key('Button Input Foto Gallery'),
211
                      style: TextButton.styleFrom(padding: EdgeInsets.zero),
212
                      onPressed: () async {
213
                        final imageSelected = await _getImage();
214
215
216
217
218
                        setState(() {
                          _image = imageSelected;
                        });
                      },
                      child: Container(
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
                        width: MediaQuery.of(context).size.width * 0.35,
                        padding: const EdgeInsets.all(9.0),
                        alignment: Alignment.centerLeft,
                        decoration: BoxDecoration(
                            boxShadow: regularShadow,
                            borderRadius: BorderRadius.circular(10.0),
                            color: greenPrimary),
                        child: Row(
                          children: [
                            const Icon(
                              MdiIcons.imagePlus,
                              color: Colors.white,
                              size: 14.0,
                            ),
                            const SizedBox(width: regularSpace),
                            const Text(
                              'Dari Gallery',
                              style: TextStyle(
                                  color: Colors.white, fontSize: 14.0),
                            ),
                          ],
                        ),
                      ),
                    ),
243
                    TextButton(
244
                      key: const Key('Button Input Foto Camera'),
245
                      style: TextButton.styleFrom(padding: EdgeInsets.zero),
246
247
248
249
250
251
252
253
                      onPressed: () async {
                        final imageSelected = await _getCameraImage();
                        setState(() {
                          _image = imageSelected;
                        });
                      },
                      child: Container(
                        width: MediaQuery.of(context).size.width * 0.35,
254
                        padding: const EdgeInsets.all(9.0),
255
256
257
                        alignment: Alignment.centerLeft,
                        decoration: BoxDecoration(
                            boxShadow: regularShadow,
258
                            borderRadius: BorderRadius.circular(10.0),
259
260
261
                            color: greenPrimary),
                        child: Row(
                          children: [
262
                            const Icon(
263
264
                              MdiIcons.imagePlus,
                              color: Colors.white,
265
                              size: 14.0,
266
                            ),
267
268
                            const SizedBox(width: regularSpace),
                            const Text(
269
                              'Dari Kamera',
270
                              style: TextStyle(
271
                                  color: Colors.white, fontSize: 14.0),
272
273
274
275
276
277
278
                            ),
                          ],
                        ),
                      ),
                    )
                  ],
                ),
wilson's avatar
wilson committed
279
                _showImagePreview(),
280
                const SizedBox(height: 10),
281
                const Text(
282
283
284
285
286
                  'Jenis Disabilitas',
                  style: TextStyle(fontSize: 18),
                  textAlign: TextAlign.left,
                ),
                FieldValidator.validateCustomFieldAlert(_isDisabilitasValid),
287
                const SizedBox(height: 10),
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
                DisabilitasButtonGrid(
                  boolFisik: _fisikClicked,
                  boolIntelektual: _intelektualClicked,
                  boolMental: _mentalClicked,
                  boolSensorik: _sensorikClicked,
                  onPressedFisik: () {
                    setState(() {
                      _fisikClicked = !_fisikClicked;
                    });
                  },
                  onPressedIntelektual: () {
                    setState(() {
                      _intelektualClicked = !_intelektualClicked;
                    });
                  },
                  onPressedMental: () {
                    setState(() {
                      _mentalClicked = !_mentalClicked;
                    });
                  },
                  onPressedSensorik: () {
                    setState(() {
                      _sensorikClicked = !_sensorikClicked;
                    });
                  },
                ),
314
                Container(
315
316
                    key: const Key('Button Simpan'),
                    margin: const EdgeInsets.fromLTRB(0, 30, 0, 10),
317
318
319
320
                    alignment: Alignment.center,
                    decoration: BoxDecoration(boxShadow: regularShadow),
                    child: ButtonTheme(
                      height: 55.0,
321
322
323
324
325
326
327
                      child: TextButton(
                        style: TextButton.styleFrom(
                          backgroundColor: greenPrimary,
                          shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10.0)),
                          padding: const EdgeInsets.symmetric(vertical: 10.0)
                        ),
328
                        onPressed: _validateInformationInput,
329
330
331
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
332
                            const Icon(MdiIcons.check,
333
                                color: Colors.white, size: 30.0),
334
335
                            const SizedBox(width: 5.0),
                            const Text('Simpan',
336
337
338
339
340
341
                                style: TextStyle(
                                    color: Colors.white, fontSize: 20.0)),
                          ],
                        ),
                      ),
                    )),
342
                const SizedBox(
343
344
345
346
347
348
349
350
351
                  height: doubleSpace,
                )
              ],
            ),
          ),
        )));
  }

  String _jenisFasilitas;
352
  int _jumlahFasilitas;
353
354
355
356
357
358
359
360
361
362
363
364
365
  bool _fisikClicked;
  bool _intelektualClicked;
  bool _mentalClicked;
  bool _sensorikClicked;
  bool _isCounterValid;
  bool _isDisabilitasValid;
  String _disabilitas = '';

  void _showConfirmationPopUp() {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return CustomAlertDialog(
366
            key: const Key('Pop Up Konfirmasi'),
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
            title:
                'Apakah kamu sudah yakin informasi yang diberikan sudah benar?',
            leftText: 'Tidak',
            leftIcon: MdiIcons.close,
            leftFunction: () {
              Navigator.of(context).pop(true);
              _resetInput();
            },
            rightText: 'Ya',
            rightIcon: MdiIcons.check,
            rightFunction: () async {
              Navigator.of(context).pop(true);
              await submitKomentar();
            },
          );
        });
  }

385
386
  Future<void> submitKomentar() async {
    final sharedPreferences = await SharedPreferences.getInstance();
387
    if (sharedPreferences.getString('token') == null) {
388
389
      await Navigator.push(
          context, MaterialPageRoute(builder: (_) => const Login()));
390
    } else {
391
      final _namaLokasi = widget.placeId;
392
393
      _bloc = KomentarBloc(_namaLokasi);
      final response = await _bloc.addNewKomentar(newKomentarData, _namaLokasi);
wilson's avatar
wilson committed
394
395
      if (response.containsKey('id')) {
        successDialog(context);
396
        Timer(const Duration(seconds: 2), () {
wilson's avatar
wilson committed
397
398
399
          Navigator.pop(context);
          Navigator.pop(context);
        });
wilson's avatar
wilson committed
400
401
      } else if (response['response'] == 'fasilitas already exist') {
        failedDialog(context, 'Fasilitas/Layanan sudah ditambahkan sebelumnya');
wilson's avatar
wilson committed
402
      } else {
wilson's avatar
wilson committed
403
        failedDialog(context, 'default');
404
405
406
407
      }
    }
  }

408
  Future<void> setKomentarData() async {
409
410
411
412
413
    newKomentarData['deskripsi'] = deskripsiController.text.toString();
    newKomentarData['tag'] = _jenisFasilitas;
    _setJenisDisabilitas();
    newKomentarData['disabilitas'] = _disabilitas;
    newKomentarData['rating'] = 5; //temporary
wilson's avatar
wilson committed
414
    newKomentarData['jumlah'] = _jumlahFasilitas;
415
    newKomentarData['image'] = '';
416
417

    if (_image == null) {
418
419
420
421
422
423
      switch (_jenisFasilitas) {
        case 'KR':
          var bytes = (await rootBundle.load('assets/images/kursiroda.jpg'))
              .buffer
              .asUint8List();
          newKomentarData['image'] =
424
              MultipartFile.fromBytes(bytes, filename: 'kursiroda.jpg');
425
426
427
428
429
430
431
          print('Fasilitas null dalem addinfo adalah: ' + _jenisFasilitas);
          break;
        case 'LF':
          var bytes =
              (await rootBundle.load('assets/images/liftdisabilitas.jpg'))
                  .buffer
                  .asUint8List();
432
433
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'liftdisabilitas.jpg');
434
435
436
437
438
439
          break;
        case 'TD':
          var bytes =
              (await rootBundle.load('assets/images/toiletdisabilitas.jpg'))
                  .buffer
                  .asUint8List();
440
441
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'toiletdisabilitas.jpg');
442
443
444
445
446
          break;
        case 'MM':
          var bytes = (await rootBundle.load('assets/images/masjidmushola.jpg'))
              .buffer
              .asUint8List();
447
448
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'masjidmushola.jpg');
449
450
451
452
453
          break;
        case 'GB':
          var bytes = (await rootBundle.load('assets/images/guidingblock.jpg'))
              .buffer
              .asUint8List();
454
455
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'guidingblock.jpg');
456
457
458
459
460
          break;
        case 'BM':
          var bytes = (await rootBundle.load('assets/images/bidangmiring.jpg'))
              .buffer
              .asUint8List();
461
462
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'bidangmiring.jpg');
463
464
465
466
467
468
          break;
        case 'CP':
          var bytes =
              (await rootBundle.load('assets/images/temandisabilitas.jpg'))
                  .buffer
                  .asUint8List();
469
470
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'temandisabilitas.jpg');
471
472
473
474
475
476
          break;
        case 'JI':
          var bytes = (await rootBundle.load('assets/images/juruisyarat.jpg'))
              .buffer
              .asUint8List();
          newKomentarData['image'] =
477
              MultipartFile.fromBytes(bytes, filename: 'juruisyarat.jpg');
478
479
480
481
482
          break;
        case 'TN':
          var bytes = (await rootBundle.load('assets/images/tongkatnetra.jpg'))
              .buffer
              .asUint8List();
483
484
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'tongkatnetra.jpg');
485
486
487
488
489
490
          break;
        case 'KD':
          var bytes =
              (await rootBundle.load('assets/images/kursidisabilitas.jpg'))
                  .buffer
                  .asUint8List();
491
492
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'kursidisabilitas.jpg');
493
494
495
496
497
498
          break;
        case 'PK':
          var bytes =
              (await rootBundle.load('assets/images/parkirdisabilitas.jpg'))
                  .buffer
                  .asUint8List();
499
500
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'parkirdisabilitas.jpg');
501
502
503
504
505
506
          break;
        case 'RT':
          var bytes = (await rootBundle.load('assets/images/runningtext.jpg'))
              .buffer
              .asUint8List();
          newKomentarData['image'] =
507
              MultipartFile.fromBytes(bytes, filename: 'runningtext.jpg');
508
509
510
511
512
513
          break;
        case 'TB':
          var bytes = (await rootBundle.load('assets/images/parkirbiasa.jpg'))
              .buffer
              .asUint8List();
          newKomentarData['image'] =
514
              MultipartFile.fromBytes(bytes, filename: 'parkirbiasa.jpg');
515
516
517
518
519
520
          break;
        default:
          var bytes =
              (await rootBundle.load('assets/images/defaultDisable.png'))
                  .buffer
                  .asUint8List();
521
522
          newKomentarData['image'] =
              MultipartFile.fromBytes(bytes, filename: 'defaultDisable.png');
523
524
525
          print('Fasilitas null default addinfo adalah: ' + _jenisFasilitas);
          break;
      }
526
    } else {
527
      final fileName = _image.path.split('/').last;
528
      newKomentarData['image'] = MultipartFile.fromFile(
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
        _image.path,
        filename: fileName,
      );
    }
  }

  void _setJenisDisabilitas() {
    _disabilitas = '';
    if (_fisikClicked == true && !_disabilitas.contains('DF')) {
      _disabilitas += 'DF ';
    }
    if (_intelektualClicked == true && !_disabilitas.contains('DI')) {
      _disabilitas += 'DI ';
    }
    if (_mentalClicked == true && !_disabilitas.contains('DM')) {
      _disabilitas += 'DM ';
    }
    if (_sensorikClicked == true && !_disabilitas.contains('DS')) {
      _disabilitas += 'DS ';
    }
  }

  void successDialog(BuildContext context) {
552
553
    const alertDialog = AlertDialog(
      title: Text('Tambah informasi berhasil'),
554
555
556
557
558
559
560
561
562
      content: Icon(FontAwesomeIcons.checkCircle),
    );
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return alertDialog;
        });
  }

wilson's avatar
wilson committed
563
  void failedDialog(BuildContext context, String message) {
564
    var newMessage = message;
wilson's avatar
wilson committed
565
    if (message == 'default') {
566
      newMessage = 'Gagal menambahkan informasi';
wilson's avatar
wilson committed
567
    }
568
    final alertDialog = AlertDialog(
569
      title: Text(newMessage),
570
      content: const Icon(FontAwesomeIcons.exclamationCircle),
571
572
573
574
575
576
577
578
    );
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return alertDialog;
        });
  }

wilson's avatar
wilson committed
579
580
  Widget _showImagePreview() {
    return _image == null
581
        ? const SizedBox(height: 0)
582
583
584
585
586
587
588
        : ImagePreviewHolder(
            image: Image.file(_image),
            onPressed: () async {
              setState(() {
                _image = null;
              });
            },
wilson's avatar
wilson committed
589
590
591
          );
  }

592
  Future<void> _validateInformationInput() async {
593
594
595
    final form = _formKey.currentState;
    if (_validateCustomFields() && _formKey.currentState.validate()) {
      form.save();
596
      await setKomentarData();
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
      _showConfirmationPopUp();
    }
  }

  bool _validateCustomFields() {
    return _validateJumlahFasilitas() && _validatePilihDisabilitas();
  }

  bool _validateJumlahFasilitas() {
    if (_jumlahFasilitas >= 1) {
      setState(() {
        _isCounterValid = true;
      });
      return true;
    } else {
      setState(() {
        _isCounterValid = false;
      });
      return false;
    }
  }

  bool _validatePilihDisabilitas() {
    if (_fisikClicked ||
        _intelektualClicked ||
        _mentalClicked ||
        _sensorikClicked) {
      setState(() {
        _isDisabilitasValid = true;
      });
      return true;
    } else {
      setState(() {
        _isDisabilitasValid = false;
      });
      return false;
    }
  }

636
  Future<void> _resetInput() async {
637
638
    deskripsiController.clear();
    await _clearImage();
wilson's avatar
wilson committed
639
640
641
642
643
644
645
    setState(() {
      _fisikClicked = false;
      _intelektualClicked = false;
      _mentalClicked = false;
      _sensorikClicked = false;
      _jumlahFasilitas = 0;
    });
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  }

  void _incrementCount() {
    setState(() {
      _jumlahFasilitas = _jumlahFasilitas + 1;
    });
  }

  void _decrementCount() {
    if (_jumlahFasilitas > 0) {
      setState(() {
        _jumlahFasilitas = _jumlahFasilitas - 1;
      });
    }
  }
}