From 85be29e7ce6c2eeae4317ad2c8cc4192cce863af Mon Sep 17 00:00:00 2001 From: kicap Date: Thu, 26 Oct 2023 16:05:01 +0800 Subject: [PATCH] finish caleg, area and tim survei page --- android/app/src/main/AndroidManifest.xml | 1 + lib/app/app.dart | 4 + lib/app/app.dialogs.dart | 4 + lib/app/app.locator.dart | 2 + lib/app/core/custom_base_view_model.dart | 2 + lib/model/tim_survei_model.dart | 51 ++++ lib/services/http_services.dart | 39 ++- lib/services/other_function.dart | 10 + .../admin_first_page_view.dart | 151 +++++++--- .../admin_first_page_view_model.dart | 48 +++ .../halaman_area/halaman_area_view.dart | 10 +- .../halaman_area/halaman_area_view_model.dart | 3 + .../halaman_caleg/halaman_caleg_view.dart | 76 +++-- .../halaman_caleg_view_model.dart | 66 ++++- .../tambah_edit_caleg_view.dart | 280 +++++++++++++----- .../tambah_edit_caleg_view_model.dart | 138 +++++---- .../halaman_pengaturan_view.dart | 7 +- .../tambah_detail_tim_survei_view.dart | 154 ++++++++++ .../tambah_detail_tim_survei_view_model.dart | 54 ++++ .../tim_survei/tim_survei_view.dart | 118 +++++++- .../tim_survei/tim_survei_view_model.dart | 89 ++++++ lib/ui/widgets/my_textformfield.dart | 12 + pubspec.lock | 8 + pubspec.yaml | 1 + 24 files changed, 1100 insertions(+), 228 deletions(-) create mode 100644 lib/model/tim_survei_model.dart create mode 100644 lib/services/other_function.dart create mode 100644 lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view.dart create mode 100644 lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view_model.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8a25d97..0866b3a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ + builders = { DialogType.tambahEditCalegView: (context, request, completer) => TambahEditCalegView(request: request, completer: completer), + DialogType.tambahDetailTimSurveiView: (context, request, completer) => + TambahDetailTimSurveiView(request: request, completer: completer), }; dialogService.registerCustomDialogBuilders(builders); diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart index 43a09d1..fa3d25b 100644 --- a/lib/app/app.locator.dart +++ b/lib/app/app.locator.dart @@ -15,6 +15,7 @@ import 'package:stacked_shared/stacked_shared.dart'; import '../services/global_var.dart'; import '../services/http_services.dart'; import '../services/my_easyloading.dart'; +import '../services/other_function.dart'; final locator = StackedLocator.instance; @@ -34,4 +35,5 @@ Future setupLocator({ locator.registerLazySingleton(() => MyEasyLoading()); locator.registerLazySingleton(() => MyHttpServices()); locator.registerLazySingleton(() => GlobalVar()); + locator.registerLazySingleton(() => MyFunction()); } diff --git a/lib/app/core/custom_base_view_model.dart b/lib/app/core/custom_base_view_model.dart index 43c4beb..35c3cc8 100755 --- a/lib/app/core/custom_base_view_model.dart +++ b/lib/app/core/custom_base_view_model.dart @@ -6,6 +6,7 @@ import 'package:stacked_services/stacked_services.dart'; import '../../services/global_var.dart'; import '../../services/http_services.dart'; import '../../services/my_easyloading.dart'; +import '../../services/other_function.dart'; import '../app.locator.dart'; import '../themes/app_colors.dart'; @@ -17,6 +18,7 @@ class CustomBaseViewModel extends BaseViewModel { final easyLoading = locator(); final httpService = locator(); final globalVar = locator(); + final myFunction = locator(); void back() { navigationService.back(); diff --git a/lib/model/tim_survei_model.dart b/lib/model/tim_survei_model.dart new file mode 100644 index 0000000..0582538 --- /dev/null +++ b/lib/model/tim_survei_model.dart @@ -0,0 +1,51 @@ +import '../app/app.locator.dart'; +import '../services/other_function.dart'; + +class TimSurveiListModel { + List? survei; + int? jumlah; + + TimSurveiListModel({this.survei, this.jumlah}); + + TimSurveiListModel.fromJson(Map json) { + if (json['survei'] != null) { + survei = []; + json['survei'].forEach((v) { + survei!.add(TimSurveiModel.fromJson(v)); + }); + } + jumlah = json['jumlah']; + } + + Map toJson() { + final Map data = {}; + if (survei != null) { + data['survei'] = survei!.map((v) => v.toJson()).toList(); + } + data['jumlah'] = jumlah; + return data; + } +} + +class TimSurveiModel { + final myFunction = locator(); + String? nik; + String? nama; + String? createdAt; + + TimSurveiModel({this.nik, this.nama, this.createdAt}); + + TimSurveiModel.fromJson(Map json) { + nik = json['nik']; + nama = json['nama']; + createdAt = myFunction.convertDateTime(json['created_at']); + } + + Map toJson() { + final Map data = {}; + data['nik'] = nik; + data['nama'] = nama; + data['created_at'] = createdAt; + return data; + } +} diff --git a/lib/services/http_services.dart b/lib/services/http_services.dart index 9c77675..44520ab 100644 --- a/lib/services/http_services.dart +++ b/lib/services/http_services.dart @@ -1,7 +1,13 @@ import 'package:dio/dio.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:stacked_services/stacked_services.dart'; + +import '../app/app.locator.dart'; +import '../app/app.logger.dart'; class MyHttpServices { + final _log = getLogger('MyHttpServices'); + final _snackbarService = locator(); final _options = BaseOptions( baseUrl: dotenv.env['api_url']!, connectTimeout: const Duration(milliseconds: 60000), @@ -17,7 +23,16 @@ class MyHttpServices { Future get(String path) async { try { return await _dio.get(path); - } on DioException { + } on DioException catch (e) { + String response = e.response != null + ? e.response!.data['message'].toString() + : e.toString(); + _log.e('ini errornya: $response'); + _snackbarService.showSnackbar( + message: response, + title: 'Error', + duration: const Duration(milliseconds: 1000), + ); rethrow; } } @@ -25,7 +40,16 @@ class MyHttpServices { Future postWithFormData(String path, FormData formData) async { try { return await _dio.post(path, data: formData); - } on DioException { + } on DioException catch (e) { + String response = e.response != null + ? e.response!.data['message'].toString() + : e.toString(); + // _log.e('ini errornya: $response'); + _snackbarService.showSnackbar( + message: response, + title: 'Error', + duration: const Duration(milliseconds: 1000), + ); rethrow; } } @@ -33,7 +57,16 @@ class MyHttpServices { Future delete(String path) async { try { return await _dio.delete(path); - } on DioException { + } on DioException catch (e) { + String response = e.response != null + ? e.response!.data['message'].toString() + : e.toString(); + // _log.e('ini errornya: $response'); + _snackbarService.showSnackbar( + message: response, + title: 'Error', + duration: const Duration(milliseconds: 1000), + ); rethrow; } } diff --git a/lib/services/other_function.dart b/lib/services/other_function.dart new file mode 100644 index 0000000..18afa3a --- /dev/null +++ b/lib/services/other_function.dart @@ -0,0 +1,10 @@ +import 'package:intl/intl.dart'; + +class MyFunction { + String convertDateTime(String input) { + DateTime dateTime = DateTime.parse(input); + String formattedDateTime = + DateFormat('dd-MM-yyyy | hh.mm.ss a').format(dateTime); + return formattedDateTime; + } +} diff --git a/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view.dart b/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view.dart index 5344316..2193567 100644 --- a/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view.dart +++ b/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view.dart @@ -38,20 +38,27 @@ class AdminFirstPageView extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const TopContainer( + TopContainer( title: 'Jumlah Area', - value: '10 Area', + value: '${model.jumlahArea} Area', icon: Icons.place_outlined, background: warningColor, ), const SizedBox(height: 10), - const TopContainer( + TopContainer( title: 'Jumlah Caleg', - value: '10 Caleg', + value: '${model.jumlahCaleg} Caleg', icon: Icons.co_present_outlined, background: greenColor, ), const SizedBox(height: 10), + TopContainer( + title: 'Tim Survei', + value: '${model.jumlahTimSurvei} Tim Survei', + icon: Icons.co_present_outlined, + background: orangeColor, + ), + const SizedBox(height: 10), const TopContainer( title: 'Jumlah Pemilih', value: '10 Pemilih', @@ -61,55 +68,109 @@ class AdminFirstPageView extends StatelessWidget { const SizedBox( height: 20, ), - RichText( - text: TextSpan( - text: 'Selamat Datang, ', - style: regularTextStyle, - children: [ - const TextSpan( - text: 'Admin\n', - style: boldTextStyle, - ), - const TextSpan( - text: 'Silahkan tambahkan data ', - style: regularTextStyle, - ), - TextSpan( - text: 'Area ', - style: boldTextStyle.copyWith( - color: greenColor, - fontStyle: FontStyle.italic, + if (model.isBusy) + const Center(child: CircularProgressIndicator()), + if (!model.isBusy && model.status == true) + RichText( + text: TextSpan( + text: 'Selamat Datang, ', + style: regularTextStyle, + children: [ + const TextSpan( + text: 'Admin\n', + style: boldTextStyle, ), - ), - const TextSpan( - text: 'terlebih dahulu sebelum menambahkan data ', - style: regularTextStyle, - ), - TextSpan( - text: 'Caleg', - style: boldTextStyle.copyWith( - color: greenColor, - fontStyle: FontStyle.italic, + const TextSpan( + text: 'Silahkan tambahkan data ', + style: regularTextStyle, ), - ), - const TextSpan( - text: - '.\n\nData Pemilih akan diambil dari data yang dimasukkan oleh tim survei\n\n', - style: regularTextStyle, - ), - const TextSpan( - text: - 'Jika terjadi kesalahan pada data, silahkan hubungi ', - style: regularTextStyle, - ), - ], + TextSpan( + text: 'Area ', + style: boldTextStyle.copyWith( + color: greenColor, + fontStyle: FontStyle.italic, + ), + ), + const TextSpan( + text: 'terlebih dahulu sebelum menambahkan data ', + style: regularTextStyle, + ), + TextSpan( + text: 'Caleg', + style: boldTextStyle.copyWith( + color: greenColor, + fontStyle: FontStyle.italic, + ), + ), + const TextSpan( + text: + '.\n\nData Pemilih akan diambil dari data yang dimasukkan oleh tim survei\n\n', + style: regularTextStyle, + ), + const TextSpan( + text: + 'Jika terjadi kesalahan pada data, silahkan hubungi ', + style: regularTextStyle, + ), + ], + ), + ), + if (!model.isBusy && model.status == false) + RichText( + text: TextSpan( + text: 'Selamat Datang, ', + style: regularTextStyle, + children: [ + const TextSpan( + text: 'Admin\n', + style: boldTextStyle, + ), + const TextSpan( + text: 'Terjadi ', + style: regularTextStyle, + ), + TextSpan( + text: 'Error ', + style: boldTextStyle.copyWith( + color: redColor, + fontStyle: FontStyle.italic, + ), + ), + const TextSpan( + text: 'pada saat mengambil data\n', + style: regularTextStyle, + ), + const TextSpan( + text: 'Silahkan coba lagi dengan menekan icon', + style: regularTextStyle, + ), + TextSpan( + text: ' Pengaturan\n', + style: boldTextStyle.copyWith( + color: greenColor, + fontStyle: FontStyle.italic, + ), + ), + const TextSpan( + text: 'di pojok kanan bawah\n', + style: regularTextStyle, + ), + ], + ), ), - ), ], ), ), ), ), + // with setting icon + floatingActionButton: FloatingActionButton( + onPressed: () { + // model.gotoSetting(); + }, + child: const Icon(Icons.settings), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.miniEndTop, ); }, ); diff --git a/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view_model.dart b/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view_model.dart index 6d5cb05..3427f6e 100644 --- a/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view_model.dart +++ b/lib/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view_model.dart @@ -1,7 +1,55 @@ +import '../../../../app/app.logger.dart'; import '../../../../app/core/custom_base_view_model.dart'; +import '../../../../model/area_model.dart'; +import '../../../../model/caleg_model.dart'; +import '../../../../model/my_response.model.dart'; +import '../../../../model/tim_survei_model.dart'; class AdminFirstPageViewModel extends CustomBaseViewModel { + final log = getLogger('AdminFirstPageViewModel'); + + // variabel + int jumlahArea = 0; + int jumlahCaleg = 0; + int jumlahTimSurvei = 0; + bool status = false; + Future init() async { globalVar.backPressed = 'exitApp'; + await getDataArea(); + } + + getDataArea() async { + log.i('getData'); + setBusy(true); + globalVar.backPressed = 'cantBack'; + try { + var response = await httpService.get('area'); + log.i(response.data); + MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data); + AreaListModel areaListModel = + AreaListModel.fromJson(myResponseModel.data); + jumlahArea = areaListModel.jumlah!; + + response = await httpService.get('caleg'); + log.i(response.data); + myResponseModel = MyResponseModel.fromJson(response.data); + CalegListModel calegListModel = + CalegListModel.fromJson(myResponseModel.data); + jumlahCaleg = calegListModel.jumlah!; + + response = await httpService.get('survei'); + myResponseModel = MyResponseModel.fromJson(response.data); + TimSurveiListModel timSurveiListModel = + TimSurveiListModel.fromJson(myResponseModel.data); + jumlahTimSurvei = timSurveiListModel.jumlah!; + status = true; + } catch (e) { + status = false; + log.e(e); + } finally { + globalVar.backPressed = 'exitApp'; + setBusy(false); + } } } diff --git a/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view.dart b/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view.dart index 09882bd..a434ca1 100644 --- a/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view.dart +++ b/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view.dart @@ -92,9 +92,13 @@ class HalamanAreaView extends StatelessWidget { child: Column( children: [ if (model.jumlahArea == 0) - const Center( - child: Text( - 'Belum ada area diinput')), + Center( + child: model.status == true + ? const Text( + 'Belum ada area diinput') + : const Text( + 'Gagal mengambil data'), + ), if (model.jumlahArea > 0) for (var i = 0; i < model.jumlahArea; diff --git a/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view_model.dart b/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view_model.dart index e697bee..6b56775 100644 --- a/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view_model.dart +++ b/lib/ui/views/admin_index_tracking/halaman_area/halaman_area_view_model.dart @@ -13,6 +13,7 @@ class HalamanAreaViewModel extends CustomBaseViewModel { // variabel List listAreaModel = []; int jumlahArea = 0; + bool status = false; // add area form final formKey = GlobalKey(); @@ -38,7 +39,9 @@ class HalamanAreaViewModel extends CustomBaseViewModel { log.i('listAreaModel: $listAreaModel'); log.i('jumlahArea: $jumlahArea'); + status = true; } catch (e) { + status = false; log.e(e); } finally { globalVar.backPressed = 'exitApp'; diff --git a/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view.dart b/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view.dart index 88bb063..985223d 100644 --- a/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view.dart +++ b/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view.dart @@ -1,8 +1,8 @@ -import 'package:cek_suara/app/themes/app_text.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import '../../../../app/themes/app_colors.dart'; +import '../../../../app/themes/app_text.dart'; import '../../../widgets/top_container.dart'; import './halaman_caleg_view_model.dart'; @@ -71,40 +71,58 @@ class HalamanCalegView extends StatelessWidget { ), if (!model.isBusy && model.listCalegModel.isNotEmpty) - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - for (var i = 0; - i < model.jumlahCaleg; - i++) - Card( - child: ListTile( - leading: Text('${i + 1}'), - title: Text( - model - .listCalegModel[i].namaCaleg!, - style: boldTextStyle, - ), - subtitle: Text( - 'No. Urut: ${model.listCalegModel[i].nomorUrutCaleg!}', - style: italicTextStyle, - ), - trailing: IconButton( - icon: const Icon(Icons.edit, - color: mainColor), - onPressed: () {}, - ), + SingleChildScrollView( + child: Column( + children: [ + for (var i = 0; i < model.jumlahCaleg; i++) + Card( + child: ListTile( + leading: Text('${i + 1}'), + title: Text( + model.listCalegModel[i].namaCaleg!, + style: boldTextStyle, + ), + subtitle: Text( + 'No. Urut: ${model.listCalegModel[i].nomorUrutCaleg!}', + style: italicTextStyle, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon( + Icons.info_outline, + color: mainColor, + ), + onPressed: () { + model.showDetailCaleg( + model.listCalegModel[i]); + }, + ), + IconButton( + icon: const Icon( + // trash + Icons.delete_outline, + color: dangerColor, + ), + onPressed: () { + model.deleteCaleg( + model.listCalegModel[i]); + }, + ), + ], ), ), - ], - ), + ), + ], ), ), if (!model.isBusy && model.listCalegModel.isEmpty) - const Center( + Center( child: Text( - 'Tidak ada data caleg diinput sebelumnya', + model.status == true + ? 'Tidak ada data caleg diinput sebelumnya' + : 'Gagal mengambil data caleg', style: italicTextStyle, textAlign: TextAlign.center, ), diff --git a/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view_model.dart b/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view_model.dart index 49776cc..b6c3577 100644 --- a/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view_model.dart +++ b/lib/ui/views/admin_index_tracking/halaman_caleg/halaman_caleg_view_model.dart @@ -1,3 +1,5 @@ +import 'package:cek_suara/app/themes/app_colors.dart'; + import '../../../../app/app.dialogs.dart'; import '../../../../app/app.logger.dart'; import '../../../../app/core/custom_base_view_model.dart'; @@ -10,6 +12,7 @@ class HalamanCalegViewModel extends CustomBaseViewModel { // variabel List listCalegModel = []; int jumlahCaleg = 0; + bool status = false; Future init() async { globalVar.backPressed = 'exitApp'; @@ -31,8 +34,10 @@ class HalamanCalegViewModel extends CustomBaseViewModel { log.i('listCalegModel: $listCalegModel'); log.i('jumlahCaleg: $jumlahCaleg'); + status = true; } catch (e) { log.e(e); + status = false; } finally { globalVar.backPressed = 'exitApp'; setBusy(false); @@ -43,11 +48,64 @@ class HalamanCalegViewModel extends CustomBaseViewModel { // log.i('addCaleg'); var res = await dialogService.showCustomDialog( variant: DialogType.tambahEditCalegView, - data: { - 'title': 'Tambah Caleg', - }, + title: 'Tambah Caleg', ); - log.i(res?.confirmed); + if (res!.confirmed) { + snackbarService.showSnackbar( + message: 'Caleg berhasil ditambahkan', + title: 'Berhasil', + duration: const Duration(seconds: 3), + ); + await getData(); + } + } + + deleteCaleg(CalegModel calegModel) { + dialogService + .showDialog( + title: 'Hapus Caleg', + description: + 'Apakah anda yakin ingin menghapus caleg ${calegModel.namaCaleg} ?', + buttonTitle: 'Hapus', + cancelTitle: 'Batal', + buttonTitleColor: dangerColor, + cancelTitleColor: mainColor, + ) + .then((value) async { + if (value!.confirmed) { + setBusy(true); + easyLoading.customLoading('Menghapus Caleg...'); + try { + var response = + await httpService.delete('caleg/${calegModel.idCaleg}'); + log.i(response.data); + await getData(); + snackbarService.showSnackbar( + message: 'Caleg berhasil dihapus', + title: 'Berhasil', + duration: const Duration(seconds: 3), + ); + } catch (e) { + log.e(e); + } finally { + easyLoading.dismissLoading(); + setBusy(false); + } + } + }); + } + + showDetailCaleg(CalegModel calegModel) async { + var res = await dialogService.showCustomDialog( + variant: DialogType.tambahEditCalegView, + title: 'Detail Caleg', + data: calegModel, + ); + + // log.i('res ini: ${res!.confirmed}'); + if (res!.confirmed) { + await deleteCaleg(calegModel); + } } } diff --git a/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view.dart b/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view.dart index 0fba2ce..77a5a26 100644 --- a/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view.dart +++ b/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; import 'package:validatorless/validatorless.dart'; @@ -10,13 +11,13 @@ import '../../../../widgets/my_textformfield.dart'; import './tambah_edit_caleg_view_model.dart'; class TambahEditCalegView extends StatelessWidget { - final DialogRequest? request; - final Function(DialogResponse)? completer; + final DialogRequest request; + final Function(DialogResponse) completer; const TambahEditCalegView({ Key? key, - this.request, - this.completer, + required this.request, + required this.completer, }) : super(key: key); @override @@ -24,7 +25,7 @@ class TambahEditCalegView extends StatelessWidget { return ViewModelBuilder.reactive( viewModelBuilder: () => TambahEditCalegViewModel(), onViewModelReady: (TambahEditCalegViewModel model) async { - await model.init(); + await model.init(request.data); }, builder: ( BuildContext context, @@ -45,73 +46,113 @@ class TambahEditCalegView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text( - request?.data['title'] ?? '', + request.title ?? '', ), const SizedBox(height: 10), - Stack( - children: [ - CircleAvatar( - radius: 50, - backgroundColor: fontParagraphColor, - child: model.imageBytes == null - ? const Icon( - Icons.person, - size: 50, - color: Colors.white, - ) - : ClipRRect( - borderRadius: BorderRadius.circular(50), - child: Image.memory( - model.imageBytes!, - width: 100, - height: 100, - fit: BoxFit.cover, + if (model.calegModel == null) + Stack( + children: [ + CircleAvatar( + radius: 50, + backgroundColor: fontParagraphColor, + child: model.imageBytes == null + ? const Icon( + Icons.person, + size: 50, + color: Colors.white, + ) + : ClipRRect( + borderRadius: BorderRadius.circular(50), + child: Image.memory( + model.imageBytes!, + width: 100, + height: 100, + fit: BoxFit.cover, + ), ), - ), - ), - Positioned( - bottom: 0, - right: 0, - child: CircleAvatar( - radius: 15, - backgroundColor: warningColor, - child: IconButton( - onPressed: () { - model.addImage(); - }, - icon: const Icon( - Icons.add, - color: fontColor, - size: 15, - )), + ), + Positioned( + bottom: 0, + right: 0, + child: CircleAvatar( + radius: 15, + backgroundColor: warningColor, + child: IconButton( + onPressed: () { + model.addImage(); + }, + icon: const Icon( + Icons.add, + color: fontColor, + size: 15, + )), + ), + ), + ], + ), + if (model.calegModel != null) + CircleAvatar( + radius: 50, + backgroundColor: fontParagraphColor, + child: ClipRRect( + borderRadius: BorderRadius.circular(50), + child: Image.network( + '${dotenv.env['api_url']}assets/caleg/${model.calegModel!.idCaleg}/${model.calegModel!.foto}', + width: 100, + height: 100, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return const Icon( + Icons.person, + size: 50, + color: greyBlueColor, + ); + }, ), ), - ], - ), + ), const SizedBox(height: 10), MyTextFormField( hintText: 'Masukan Nama Caleg', labelText: 'Nama Caleg', controller: model.namaController, + readOnly: model.calegModel != null, validator: Validatorless.required( 'Nama Caleg tidak boleh kosong'), ), const SizedBox(height: 10), MyTextFormField( - hintText: 'Area', - labelText: 'Pencarian Area', - controller: model.cariAreaController, - suffixIcon: GestureDetector( - onTap: () { - // remove keyboard focus - FocusScope.of(context).unfocus(); - model.cariArea(); - }, - child: const Icon(Icons.search), + hintText: 'Masukan Nomor Urut', + labelText: 'Nomor Urut', + controller: model.nomorUrutController, + readOnly: model.calegModel != null, + keyboardType: TextInputType.number, + validator: Validatorless.multiple( + // numbers only + [ + Validatorless.required( + 'Nomor Urut tidak boleh kosong'), + Validatorless.number('Nomor Urut harus berupa angka'), + ], ), - - // controller: model.partaiController, ), + if (model.calegModel == null) const SizedBox(height: 10), + if (model.calegModel == null) + MyTextFormField( + hintText: 'Area', + labelText: 'Pencarian Area', + controller: model.cariAreaController, + suffixIcon: GestureDetector( + onTap: () { + // remove keyboard focus + FocusScope.of(context).unfocus(); + model.cariArea(); + }, + child: const Icon(Icons.search), + ), + + // controller: model.partaiController, + ), const SizedBox(height: 10), SizedBox( height: MediaQuery.of(context).size.height * 0.3, @@ -137,6 +178,7 @@ class TambahEditCalegView extends StatelessWidget { value: model.listAreaId.contains( model.listAreaModel[index].idArea!), onChanged: (value) { + if (model.calegModel != null) return; model.tambahHapusArea( model.listAreaModel[index].idArea!, ); @@ -175,35 +217,111 @@ class TambahEditCalegView extends StatelessWidget { ), ), const SizedBox(height: 10), - SizedBox( - width: 250, - child: MyButton( - text: 'Tambah Caleg', - onPressed: () async { - if (model.listAreaId.isEmpty) { - model.snackbarService.showSnackbar( - message: - 'Pilih Area Calon Legislatif terlebih dahulu', - duration: const Duration(seconds: 2), - ); - return; - } + if (model.calegModel == null) + SizedBox( + width: 250, + child: MyButton( + text: 'Tambah Caleg', + onPressed: () async { + if (model.listAreaId.isEmpty) { + model.snackbarService.showSnackbar( + message: + 'Pilih Area Calon Legislatif terlebih dahulu', + duration: const Duration(seconds: 2), + ); + return; + } - if (model.imageBytes == null) { - model.snackbarService.showSnackbar( - message: - 'Pilih Foto Calon Legislatif terlebih dahulu', - duration: const Duration(seconds: 2), - ); - return; - } + if (model.imageBytes == null) { + model.snackbarService.showSnackbar( + message: + 'Pilih Foto Calon Legislatif terlebih dahulu', + duration: const Duration(seconds: 2), + ); + return; + } - if (model.formKey.currentState!.validate()) { - model.addCaleg(); - } - }, + if (model.formKey.currentState!.validate()) { + // remove keyboard focus + FocusScope.of(context).unfocus(); + model.dialogService + .showDialog( + title: 'Tambah Caleg', + description: + 'Apakah anda yakin ingin menambah caleg ${model.namaController.text} ?', + buttonTitle: 'Ya', + cancelTitle: 'Batal', + ) + .then((value) async { + if (value!.confirmed) { + bool res = await model.addCaleg(); + model.log + .i('ini di res bagian dalamnya: $res'); + if (res) { + // ignore: use_build_context_synchronously + // Navigator.of(context).pop(); + completer(DialogResponse(confirmed: true)); + } + // if (res.confirmed) { + // await model.addCaleg(completer!); + // completer!(DialogResponse(confirmed: true)); + } + }); + + // bool res = await model.addCaleg(); + // model.log.i('ini di res bagian dalamnya: $res'); + // if (res) { + // // ignore: use_build_context_synchronously + // Navigator.of(context).pop(); + // completer(DialogResponse(confirmed: true)); + // } + // if (res.confirmed) { + // await model.addCaleg(completer!); + // completer!(DialogResponse(confirmed: true)); + } + }, + ), ), - ), + if (model.calegModel != null) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + // create rounde icon with one is delete and one is info + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: mainColor.withOpacity(0.5), + borderRadius: BorderRadius.circular(50), + ), + child: IconButton( + onPressed: () {}, + icon: const Icon( + Icons.info, + color: Colors.white, + ), + ), + ), + const SizedBox(width: 20), + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: dangerColor, + borderRadius: BorderRadius.circular(50), + ), + child: IconButton( + onPressed: () async { + completer(DialogResponse(confirmed: true)); + }, + icon: const Icon( + Icons.delete, + color: Colors.white, + ), + ), + ), + ], + ) ], ), ), diff --git a/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view_model.dart b/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view_model.dart index 928c9bd..db3229e 100644 --- a/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view_model.dart +++ b/lib/ui/views/admin_index_tracking/halaman_caleg/tambah_edit_caleg/tambah_edit_caleg_view_model.dart @@ -11,6 +11,7 @@ import '../../../../../app/core/custom_base_view_model.dart'; import 'package:image_picker/image_picker.dart'; import '../../../../../model/area_model.dart'; +import '../../../../../model/caleg_model.dart'; import '../../../../../model/my_response.model.dart'; class TambahEditCalegViewModel extends CustomBaseViewModel { @@ -24,6 +25,7 @@ class TambahEditCalegViewModel extends CustomBaseViewModel { final formKey = GlobalKey(); TextEditingController namaController = TextEditingController(); TextEditingController cariAreaController = TextEditingController(); + TextEditingController nomorUrutController = TextEditingController(); List listAreaId = []; // image picker @@ -32,9 +34,49 @@ class TambahEditCalegViewModel extends CustomBaseViewModel { XFile? imageFile; Uint8List? imageBytes; - Future init() async { + CalegModel? calegModel; + + Future init(data) async { globalVar.backPressed = 'exitApp'; await getData(); + calegModel = data; + if (calegModel != null) { + namaController.text = calegModel!.namaCaleg!; + nomorUrutController.text = calegModel!.nomorUrutCaleg!.toString(); + getAreaList(calegModel!.idCaleg!); + // listAreaId = calegModel!.area!.map((e) => e.id!).toList(); + } + log.i(data); + } + + getAreaList(int idCaleg) async { + log.i('getAreaList'); + setBusy(true); + globalVar.backPressed = 'cantBack'; + try { + var response = await httpService.get('caleg/relasi_area/$idCaleg'); + log.i(response.data); + MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data); + var data = myResponseModel.data['area']; + for (var item in data) { + listAreaId.add(item['id_area']); + } + listAreaModel = []; + for (var item in allListAreaModel) { + if (listAreaId.contains(item.idArea)) { + listAreaModel.add(item); + } + } + + log.i('listAreaModel: $listAreaModel'); + + // log.i('jumlahArea: $jumlahArea'); + } catch (e) { + log.e(e); + } finally { + globalVar.backPressed = 'exitApp'; + setBusy(false); + } } getData() async { @@ -105,61 +147,47 @@ class TambahEditCalegViewModel extends CustomBaseViewModel { notifyListeners(); } - addCaleg() async { - dialogService - .showDialog( - title: 'Tambah Caleg', - description: - 'Apakah anda yakin ingin menambahkan Caleg ${namaController.text}?', - buttonTitle: 'Ya', - cancelTitle: 'Tidak', - ) - .then((value) async { - if (value!.confirmed) { - log.i('addCaleg'); - setBusy(true); - globalVar.backPressed = 'cantBack'; - easyLoading.customLoading('Tambah Caleg..'); + Future addCaleg() async { + log.i('addCaleg'); + setBusy(true); + globalVar.backPressed = 'cantBack'; + easyLoading.customLoading('Tambah Caleg..'); - var formData = FormData.fromMap({ - 'nama': namaController.text, - 'area': const JsonEncoder().convert(listAreaId), - 'foto': await MultipartFile.fromFile( - imageFile!.path, - filename: imageFile!.name, - contentType: MediaType('image', 'jpeg'), - ) - }); - - try { - var response = await httpService.postWithFormData('caleg', formData); - log.i(response.data); - await getData(); - - navigationService.back(); - // navigationService.back(); - snackbarService.showSnackbar( - message: 'Berhasil menambahkan Caleg', - duration: const Duration(seconds: 2), - ); - // navigationService.popRepeated(2); - } catch (e) { - log.e(e); - - // navigationService.back(); - snackbarService.showSnackbar( - message: 'Gagal menambahkan Caleg, ${e.toString()}', - duration: const Duration(seconds: 2), - ); - } finally { - easyLoading.dismissLoading(); - globalVar.backPressed = 'exitApp'; - setBusy(false); - // navigationService.back(); - // Navigator.of(context!).pop(); - // remove all dialog - } - } + var formData = FormData.fromMap({ + 'nama': namaController.text, + 'nomor_urut': nomorUrutController.text, + 'area': const JsonEncoder().convert(listAreaId), + 'foto': await MultipartFile.fromFile( + imageFile!.path, + filename: imageFile!.name, + contentType: MediaType('image', 'jpeg'), + ) }); + + try { + var response = await httpService.postWithFormData('caleg', formData); + log.i(response.data); + // await getData(); + + // navigationService.back(); + // navigationService.back(); + // snackbarService.showSnackbar( + // message: 'Berhasil menambahkan Caleg', + // duration: const Duration(seconds: 2), + // ); + // completer(DialogResponse(confirmed: true)); + return true; + // navigationService.popRepeated(2); + } catch (e) { + log.e(e); + return false; + } finally { + easyLoading.dismissLoading(); + globalVar.backPressed = 'exitApp'; + setBusy(false); + // navigationService.back(); + // Navigator.of(context!).pop(); + // remove all dialog + } } } diff --git a/lib/ui/views/admin_index_tracking/halaman_pengaturan/halaman_pengaturan_view.dart b/lib/ui/views/admin_index_tracking/halaman_pengaturan/halaman_pengaturan_view.dart index 1b596cc..99ab1c2 100644 --- a/lib/ui/views/admin_index_tracking/halaman_pengaturan/halaman_pengaturan_view.dart +++ b/lib/ui/views/admin_index_tracking/halaman_pengaturan/halaman_pengaturan_view.dart @@ -1,3 +1,4 @@ +import 'package:cek_suara/ui/views/admin_index_tracking/admin_first_page/admin_first_page_view.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; @@ -28,11 +29,7 @@ class HalamanPengaturanView extends StatelessWidget { } return false; }, - child: const Center( - child: Text( - 'HalamanPengaturanView', - ), - ), + child: const AdminFirstPageView(), ), ); }, diff --git a/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view.dart b/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view.dart new file mode 100644 index 0000000..bd0dcb3 --- /dev/null +++ b/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view.dart @@ -0,0 +1,154 @@ +import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; +import 'package:validatorless/validatorless.dart'; + +import '../../../../../app/themes/app_colors.dart'; +import '../../../../widgets/my_button.dart'; +import '../../../../widgets/my_textformfield.dart'; +import './tambah_detail_tim_survei_view_model.dart'; + +class TambahDetailTimSurveiView extends StatelessWidget { + final DialogRequest request; + final Function(DialogResponse) completer; + + const TambahDetailTimSurveiView({ + Key? key, + required this.request, + required this.completer, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => TambahDetailTimSurveiViewModel(), + onViewModelReady: (TambahDetailTimSurveiViewModel model) async { + await model.init(request.data); + }, + builder: ( + BuildContext context, + TambahDetailTimSurveiViewModel model, + Widget? child, + ) { + return Dialog( + child: Container( + padding: const EdgeInsets.all(15), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: backgroundColor, + ), + child: SingleChildScrollView( + child: Form( + key: model.formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + request.title ?? '', + ), + const SizedBox(height: 15), + MyTextFormField( + hintText: 'NIK Tim Survei', + labelText: 'NIK Tim Survei', + keyboardType: TextInputType.number, + controller: model.nikController, + readOnly: model.timSurveiModel != null, + maxLength: 16, + validator: Validatorless.multiple( + [ + Validatorless.required( + 'NIK Tim Survei tidak boleh kosong'), + Validatorless.min( + 16, 'NIK Tim Survei harus 16 digit'), + Validatorless.number( + 'NIK Tim Survei harus berupa angka') + ], + ), + ), + const SizedBox(height: 15), + MyTextFormField( + hintText: 'Nama Tim Survei', + labelText: 'Nama Tim Survei', + readOnly: model.timSurveiModel != null, + controller: model.namaController, + validator: Validatorless.required( + 'Nama Tim Survei tidak boleh kosong'), + ), + const SizedBox(height: 20), + if (model.timSurveiModel == null) + SizedBox( + width: 200, + child: MyButton( + text: 'Tambah', + onPressed: () { + if (model.formKey.currentState!.validate()) { + model.dialogService + .showConfirmationDialog( + title: 'Tambah Tim Survei', + description: + 'Apakah anda yakin ingin menambahkan Tim Survei ${model.namaController.text} ?', + confirmationTitle: 'Ya', + cancelTitle: 'Tidak', + ) + .then((value) async { + if (value!.confirmed) { + bool res = await model.tambahTimSurvei(); + if (res) { + completer(DialogResponse(confirmed: true)); + } + } + }); + } + }, + ), + ), + if (model.timSurveiModel != null) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + // create rounde icon with one is delete and one is info + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: mainColor.withOpacity(0.5), + borderRadius: BorderRadius.circular(50), + ), + child: IconButton( + onPressed: () {}, + icon: const Icon( + Icons.list_alt_outlined, + color: Colors.white, + ), + ), + ), + const SizedBox(width: 20), + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: dangerColor, + borderRadius: BorderRadius.circular(50), + ), + child: IconButton( + onPressed: () async { + completer(DialogResponse(confirmed: true)); + }, + icon: const Icon( + Icons.delete, + color: Colors.white, + ), + ), + ), + ], + ) + ], + ), + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view_model.dart b/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view_model.dart new file mode 100644 index 0000000..7cb357c --- /dev/null +++ b/lib/ui/views/admin_index_tracking/tim_survei/tambah_detail_tim_survei/tambah_detail_tim_survei_view_model.dart @@ -0,0 +1,54 @@ +import 'package:cek_suara/model/tim_survei_model.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +import '../../../../../app/app.logger.dart'; +import '../../../../../app/core/custom_base_view_model.dart'; + +class TambahDetailTimSurveiViewModel extends CustomBaseViewModel { + final log = getLogger('TambahDetailTimSurveiViewModel'); + + // form variabel + final formKey = GlobalKey(); + TextEditingController nikController = TextEditingController(); + TextEditingController namaController = TextEditingController(); + + TimSurveiModel? timSurveiModel; + + Future init(data) async { + globalVar.backPressed = 'exitApp'; + timSurveiModel = data; + if (timSurveiModel != null) { + nikController.text = timSurveiModel!.nik!; + namaController.text = timSurveiModel!.nama!; + } + } + + Future tambahTimSurvei() async { + globalVar.backPressed = 'cantBack'; + setBusy(true); + easyLoading.customLoading('Menambahkan Tim Survei...'); + + try { + var formData = FormData.fromMap({ + 'nik': nikController.text, + 'nama': namaController.text, + }); + var response = await httpService.postWithFormData('survei', formData); + log.i(response.data); + return true; + } catch (e) { + // log.e(e); + // snackbarService.showSnackbar( + // message: 'Gagal menambahkan Tim Survei\n${e.res}', + // title: 'Error', + // duration: const Duration(seconds: 2), + // ); + return false; + } finally { + globalVar.backPressed = 'exitApp'; + easyLoading.dismissLoading(); + setBusy(false); + } + } +} diff --git a/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view.dart b/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view.dart index 3498b0d..f4a9aea 100644 --- a/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view.dart +++ b/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; +import '../../../../app/themes/app_colors.dart'; +import '../../../widgets/top_container.dart'; import './tim_survei_view_model.dart'; class TimSurveiView extends StatelessWidget { @@ -28,12 +30,122 @@ class TimSurveiView extends StatelessWidget { } return false; }, - child: const Center( - child: Text( - 'TimSurveiView', + child: SafeArea( + child: Container( + height: MediaQuery.of(context).size.height, + padding: const EdgeInsets.all(20), + child: Column( + children: [ + TopContainer( + title: 'Tim\nSurvei', + value: '${model.jumlahTimSurvei} Orang', + icon: Icons.people_alt_outlined, + background: orangeColor, + ), + const SizedBox(height: 15), + Expanded( + child: Container( + alignment: model.isBusy + ? Alignment.center + : (model.listTimSurveiModel.isNotEmpty + ? null + : Alignment.center), + width: double.infinity, + height: double.infinity, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(10), + color: warningColor, + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (model.isBusy) + const Center( + child: LinearProgressIndicator( + minHeight: 5, + color: mainColor, + ), + ), + if (!model.isBusy && + model.listTimSurveiModel.isNotEmpty) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // create 10 list of survei person using card + for (int i = 0; + i < model.jumlahTimSurvei; + i++) + Card( + child: ListTile( + leading: Text('${i + 1}'), + title: Text( + model.listTimSurveiModel[i].nama!, + ), + subtitle: Text( + model.listTimSurveiModel[i].nik!, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + // one info and one delete button + IconButton( + onPressed: () { + model.showDetailTimSurvei( + model.listTimSurveiModel[ + i]); + }, + icon: const Icon( + Icons.info_outline, + color: mainColor, + ), + ), + IconButton( + onPressed: () { + model.deleteTimSurvei(model + .listTimSurveiModel[i]); + }, + icon: const Icon( + Icons.delete_outline, + color: Colors.red, + ), + ), + ], + )), + ), + ], + ), + + // if listTimSurveiModel is empty + if (!model.isBusy && + model.listTimSurveiModel.isEmpty) + Center( + child: Text( + model.status == true + ? 'Data Tim Survei Kosong\n' + 'Silahkan Tambahkan Tim Survei Baru' + : 'Gagal Mengambil Data Tim Survei', + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + ) + ], + ), ), ), ), + floatingActionButton: FloatingActionButton( + onPressed: () { + model.addTimSurvei(); + }, + child: const Icon(Icons.add), + ), ); }, ); diff --git a/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view_model.dart b/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view_model.dart index b4a2275..daa5a32 100644 --- a/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view_model.dart +++ b/lib/ui/views/admin_index_tracking/tim_survei/tim_survei_view_model.dart @@ -1,7 +1,96 @@ +import '../../../../app/app.dialogs.dart'; +import '../../../../app/app.logger.dart'; import '../../../../app/core/custom_base_view_model.dart'; +import '../../../../app/themes/app_colors.dart'; +import '../../../../model/my_response.model.dart'; +import '../../../../model/tim_survei_model.dart'; class TimSurveiViewModel extends CustomBaseViewModel { + final log = getLogger('TimSurveiViewModel'); + + // variabel + List listTimSurveiModel = []; + int jumlahTimSurvei = 0; + bool status = false; + Future init() async { globalVar.backPressed = 'exitApp'; + await getData(); + } + + getData() async { + setBusy(true); + // easyLoading.showLoading(); + // globalVar.backPressed = 'cantBack'; + try { + var response = await httpService.get('survei'); + MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data); + TimSurveiListModel timSurveiListModel = + TimSurveiListModel.fromJson(myResponseModel.data); + listTimSurveiModel = timSurveiListModel.survei!; + jumlahTimSurvei = timSurveiListModel.jumlah!; + log.i('listTimSurveiModel: $listTimSurveiModel'); + log.i('jumlahTimSurvei: $jumlahTimSurvei'); + status = true; + } catch (e) { + log.e(e.toString()); + status = false; + } finally { + setBusy(false); + // globalVar.backPressed = 'exitApp'; + // easyLoading.dismissLoading(); + } + } + + addTimSurvei() async { + var res = await dialogService.showCustomDialog( + variant: DialogType.tambahDetailTimSurveiView, + title: 'Tambah Tim Survei', + ); + + if (res!.confirmed) { + await getData(); + snackbarService.showSnackbar( + message: 'Berhasil menambahkan Tim Survei\nPassword default: 12345678', + title: 'Sukses', + duration: const Duration(seconds: 2), + ); + } + } + + deleteTimSurvei(TimSurveiModel listTimSurveiModel) async { + dialogService + .showDialog( + title: 'Hapus Tim Survei', + description: + 'Apakah anda yakin ingin menghapus ${listTimSurveiModel.nama} ?', + buttonTitle: 'Hapus', + cancelTitle: 'Batal', + buttonTitleColor: dangerColor, + cancelTitleColor: mainColor, + ) + .then((value) async { + if (value!.confirmed) { + await httpService.delete('survei/${listTimSurveiModel.nik}'); + await getData(); + snackbarService.showSnackbar( + message: 'Berhasil menghapus ${listTimSurveiModel.nama}', + title: 'Sukses', + duration: const Duration(seconds: 2), + ); + } + }); + } + + showDetailTimSurvei(TimSurveiModel listTimSurveiModel) async { + var res = await dialogService.showCustomDialog( + variant: DialogType.tambahDetailTimSurveiView, + title: 'Detail Tim Survei', + data: listTimSurveiModel, + ); + + if (res!.confirmed) { + deleteTimSurvei(listTimSurveiModel); + } } } diff --git a/lib/ui/widgets/my_textformfield.dart b/lib/ui/widgets/my_textformfield.dart index 000380d..a4ef356 100644 --- a/lib/ui/widgets/my_textformfield.dart +++ b/lib/ui/widgets/my_textformfield.dart @@ -15,6 +15,10 @@ class MyTextFormField extends StatelessWidget { this.controller, this.maxLines = 1, this.onEditingComplete, + this.keyboardType = TextInputType.text, + this.initialValue, + this.readOnly = false, + this.maxLength, }) : super(key: key); final String? labelText; @@ -27,15 +31,23 @@ class MyTextFormField extends StatelessWidget { final TextEditingController? controller; final int maxLines; final VoidCallback? onEditingComplete; + final TextInputType keyboardType; + final String? initialValue; + final bool readOnly; + final int? maxLength; @override Widget build(BuildContext context) { return TextFormField( + maxLength: maxLength, + readOnly: readOnly, + initialValue: initialValue, onEditingComplete: onEditingComplete, maxLines: maxLines, controller: controller, focusNode: focusNode, obscureText: obscureText ?? false, + keyboardType: keyboardType, decoration: InputDecoration( prefixIcon: prefixIcon, suffixIcon: suffixIcon, diff --git a/pubspec.lock b/pubspec.lock index 8846671..9a2c82e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -456,6 +456,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.1+1" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" io: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1371dd0..9a9236e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: stylish_bottom_bar: validatorless: ^1.2.3 http_parser: + intl: dev_dependencies: