From 9eb2c5ac1a3c8e937ddd45decb0da4c94518de5f Mon Sep 17 00:00:00 2001 From: Khafidh Fuadi Date: Mon, 17 Mar 2025 20:44:21 +0700 Subject: [PATCH] Perbarui tampilan DetailPengaduanView dan PengaduanView untuk meningkatkan konsistensi dan pengalaman pengguna. Tambahkan konstanta warna untuk status pengaduan dan modifikasi penggunaan warna di seluruh tampilan. Ganti metode filter dengan PopupMenuButton untuk kemudahan akses dan tambahkan informasi waktu terakhir update pada PengaduanView. --- .../arm64-v8a/configure_fingerprint.bin | 24 +- .../armeabi-v7a/configure_fingerprint.bin | 24 +- .../626b5o2n/x86/configure_fingerprint.bin | 24 +- .../626b5o2n/x86_64/configure_fingerprint.bin | 24 +- .../views/detail_pengaduan_view.dart | 65 +- .../petugas_desa/views/pengaduan_view.dart | 327 +++++---- .../views/pengaduan_view_backup.dart | 657 ++++++++++++++++++ temp.txt | Bin 0 -> 42032 bytes 8 files changed, 918 insertions(+), 227 deletions(-) create mode 100644 lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart create mode 100644 temp.txt diff --git a/android/app/.cxx/Debug/626b5o2n/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/626b5o2n/arm64-v8a/configure_fingerprint.bin index e4b0d5a..3902c56 100644 --- a/android/app/.cxx/Debug/626b5o2n/arm64-v8a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/626b5o2n/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured LogO M KC:\dev\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2 2 +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ס2 2  -}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\additional_project_files.txt  2  2~ +}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\additional_project_files.txt  ס2  2~ | -zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build.json  2 2 +zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build.json  ס2 2  -D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build_mini.json  2 2p +D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build_mini.json  ס2 2p n -lD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja  2 2t +lD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja  ס2 2t r -pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja.txt  2y +pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja.txt  ס2y w -uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build_file_index.txt  2 K 2z +uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build_file_index.txt  ס2 K 2z x -vD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json  2 ~ +vD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json  ס2 ~ | -zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json.bin  2 +zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json.bin  ס2   -D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\metadata_generation_command.txt  2  2w +D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\metadata_generation_command.txt  ס2  2w u -sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\prefab_config.json  2  ( 2| +sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\prefab_config.json  ס2  ( 2| z -xD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\symbol_folder_index.txt  2  o 2 \ No newline at end of file +xD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\symbol_folder_index.txt  ס2  o 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/626b5o2n/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/626b5o2n/armeabi-v7a/configure_fingerprint.bin index bf80186..de14102 100644 --- a/android/app/.cxx/Debug/626b5o2n/armeabi-v7a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/626b5o2n/armeabi-v7a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured LogO M KC:\dev\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  κ2 2 +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ɠס2 2  -D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\additional_project_files.txt  κ2  2 +D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\additional_project_files.txt  ɠס2  2 ~ -|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build.json  κ2 2 +|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build.json  ɠס2 2  -D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build_mini.json  κ2 2r +D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build_mini.json  ʠס2 2r p -nD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja  κ2 2v +nD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja  ʠס2 2v t -rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja.txt  κ2{ +rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja.txt  ʠס2{ y -wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build_file_index.txt  κ2 K 2| +wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build_file_index.txt  ʠס2 K 2| z -xD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json  κ2  +xD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json  ʠס2  ~ -|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json.bin  κ2 +|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json.bin  ʠס2   -D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\metadata_generation_command.txt  κ2  2y +D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\metadata_generation_command.txt  ʠס2  2y w -uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\prefab_config.json  κ2  ( 2~ +uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\prefab_config.json  ʠס2  ( 2~ | -zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\symbol_folder_index.txt  κ2  q 2 \ No newline at end of file +zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\symbol_folder_index.txt  ʠס2  q 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/626b5o2n/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/626b5o2n/x86/configure_fingerprint.bin index 1cd8fd0..d20ab28 100644 --- a/android/app/.cxx/Debug/626b5o2n/x86/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/626b5o2n/x86/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured LogO M KC:\dev\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2 2{ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ס2 2{ y -wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\additional_project_files.txt  2  2x +wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\additional_project_files.txt  ס2  2x v -tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build.json  2 2} +tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build.json  ס2 2} { -yD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build_mini.json  2 2j +yD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build_mini.json  ס2 2j h -fD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja  2 2n +fD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja  ס2 2n l -jD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja.txt  2s +jD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja.txt  ס2s q -oD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build_file_index.txt  2 K 2t +oD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build_file_index.txt  ס2 K 2t r -pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json  2 x +pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json  ס2 x v -tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json.bin  2 +tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json.bin  ס2 ~ | -zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\metadata_generation_command.txt  2  2q +zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\metadata_generation_command.txt  ס2  2q o -mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\prefab_config.json  2  ( 2v +mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\prefab_config.json  ס2  ( 2v t -rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\symbol_folder_index.txt  2  i 2 \ No newline at end of file +rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\symbol_folder_index.txt  ס2  i 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/626b5o2n/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/626b5o2n/x86_64/configure_fingerprint.bin index 783eec6..bb50cf4 100644 --- a/android/app/.cxx/Debug/626b5o2n/x86_64/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/626b5o2n/x86_64/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured LogO M KC:\dev\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2 2~ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Ԣס2 2~ | -zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\additional_project_files.txt  2  2{ +zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\additional_project_files.txt  Ԣס2  2{ y -wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build.json  2 2 +wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build.json  Ԣס2 2 ~ -|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build_mini.json  2 2m +|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build_mini.json  Ԣס2 2m k -iD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja  2 2q +iD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja  Ԣס2 2q o -mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja.txt  2v +mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja.txt  Ԣס2v t -rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build_file_index.txt  2 K 2w +rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build_file_index.txt  Ԣס2 K 2w u -sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json  2 { +sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json  Ԣס2 { y -wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json.bin  2 +wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json.bin  Ԣס2   -}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\metadata_generation_command.txt  2  2t +}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\metadata_generation_command.txt  Ԣס2  2t r -pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\prefab_config.json  2  ( 2y +pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\prefab_config.json  Ԣס2  ( 2y w -uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\symbol_folder_index.txt  2  l 2 \ No newline at end of file +uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\symbol_folder_index.txt  Ԣס2  l 2 \ No newline at end of file diff --git a/lib/app/modules/petugas_desa/views/detail_pengaduan_view.dart b/lib/app/modules/petugas_desa/views/detail_pengaduan_view.dart index efc55a6..6e275f9 100644 --- a/lib/app/modules/petugas_desa/views/detail_pengaduan_view.dart +++ b/lib/app/modules/petugas_desa/views/detail_pengaduan_view.dart @@ -19,6 +19,11 @@ import 'package:penyaluran_app/app/widgets/inputs/text_input.dart'; class DetailPengaduanView extends GetView { const DetailPengaduanView({Key? key}) : super(key: key); + // Definisi konstanta warna status untuk konsistensi + static const Color statusMenungguColor = Colors.orange; + static const Color statusTindakanColor = Colors.blue; + static const Color statusSelesaiColor = Colors.green; + @override Widget build(BuildContext context) { final Map args = Get.arguments ?? {}; @@ -151,15 +156,15 @@ class DetailPengaduanView extends GetView { switch (pengaduan.status?.toUpperCase()) { case 'MENUNGGU': - statusColor = Colors.orange; + statusColor = statusMenungguColor; statusText = 'Menunggu'; break; case 'TINDAKAN': - statusColor = Colors.blue; + statusColor = statusTindakanColor; statusText = 'Tindakan'; break; case 'SELESAI': - statusColor = Colors.green; + statusColor = statusSelesaiColor; statusText = 'Selesai'; break; default: @@ -236,21 +241,21 @@ class DetailPengaduanView extends GetView { _buildStatusGuideItem( 'MENUNGGU', 'Pengaduan baru yang belum ditindaklanjuti', - Colors.orange, + statusMenungguColor, Icons.hourglass_empty, ), const SizedBox(height: 8), _buildStatusGuideItem( 'TINDAKAN', 'Pengaduan sedang dalam proses penanganan', - Colors.blue, + statusTindakanColor, Icons.engineering, ), const SizedBox(height: 8), _buildStatusGuideItem( 'SELESAI', 'Pengaduan telah selesai ditangani', - Colors.green, + statusSelesaiColor, Icons.check_circle, ), ], @@ -283,7 +288,7 @@ class DetailPengaduanView extends GetView { 'PROSES', 'Dalam Proses', 'Tindakan sedang dilakukan', - Colors.blue, + statusTindakanColor, Icons.sync, ), const SizedBox(height: 8), @@ -291,7 +296,7 @@ class DetailPengaduanView extends GetView { 'SELESAI', 'Selesai', 'Tindakan telah selesai', - Colors.green, + statusSelesaiColor, Icons.check_circle, ), ], @@ -539,19 +544,24 @@ class DetailPengaduanView extends GetView { case 'MENUNGGU': return StatusPill( status: 'Menunggu', - backgroundColor: Colors.orange, + backgroundColor: statusMenungguColor, textColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), ); case 'TINDAKAN': return StatusPill( status: 'Tindakan', - backgroundColor: Colors.blue, + backgroundColor: statusTindakanColor, textColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), ); case 'SELESAI': - return StatusPill.completed(status: 'Selesai'); + return StatusPill( + status: 'Selesai', + backgroundColor: statusSelesaiColor, + textColor: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + ); default: return StatusPill( status: status ?? 'Tidak Diketahui', @@ -613,7 +623,7 @@ class DetailPengaduanView extends GetView { status == 'MENUNGGU' || status == 'TINDAKAN' || status == 'SELESAI', - Colors.orange, + statusMenungguColor, ), ), Expanded( @@ -622,7 +632,7 @@ class DetailPengaduanView extends GetView { 'Tindakan', status == 'TINDAKAN', status == 'TINDAKAN' || status == 'SELESAI', - Colors.blue, + statusTindakanColor, ), ), Expanded( @@ -631,7 +641,7 @@ class DetailPengaduanView extends GetView { 'Selesai', status == 'SELESAI', status == 'SELESAI', - Colors.green, + statusSelesaiColor, ), ), ], @@ -646,7 +656,7 @@ class DetailPengaduanView extends GetView { icon: const Icon(Icons.engineering), label: const Text('Tambah Tindakan'), style: ElevatedButton.styleFrom( - backgroundColor: Colors.blue, + backgroundColor: statusTindakanColor, foregroundColor: Colors.white, minimumSize: const Size(double.infinity, 40), ), @@ -662,7 +672,7 @@ class DetailPengaduanView extends GetView { icon: const Icon(Icons.add), label: const Text('Tambah Tindakan'), style: ElevatedButton.styleFrom( - backgroundColor: Colors.blue, + backgroundColor: statusTindakanColor, foregroundColor: Colors.white, ), ), @@ -676,7 +686,7 @@ class DetailPengaduanView extends GetView { icon: const Icon(Icons.check_circle), label: const Text('Selesaikan'), style: ElevatedButton.styleFrom( - backgroundColor: Colors.green, + backgroundColor: statusSelesaiColor, foregroundColor: Colors.white, ), ), @@ -687,15 +697,15 @@ class DetailPengaduanView extends GetView { Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.green.shade50, + color: statusSelesaiColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.green.shade200), + border: Border.all(color: statusSelesaiColor.withOpacity(0.3)), ), child: Row( children: [ Icon( Icons.check_circle, - color: Colors.green, + color: statusSelesaiColor, size: 20, ), const SizedBox(width: 8), @@ -703,7 +713,7 @@ class DetailPengaduanView extends GetView { child: Text( 'Pengaduan telah selesai ditangani', style: TextStyle( - color: Colors.green.shade800, + color: statusSelesaiColor, fontWeight: FontWeight.w500, ), ), @@ -921,8 +931,9 @@ class DetailPengaduanView extends GetView { // Informasi penyaluran _buildInfoRow('Nama Penyaluran', pengaduan.namaPenyaluran), - _buildInfoRow('Jenis Bantuan', pengaduan.jenisBantuan), - _buildInfoRow('Jumlah Bantuan', pengaduan.jumlahBantuan), + _buildInfoRow('Stok Bantuan', pengaduan.stokBantuan!['nama']), + _buildInfoRow('Jumlah Bantuan', + '${pengaduan.jumlahBantuan} ${pengaduan.stokBantuan!['satuan']}'), _buildInfoRow('Deskripsi', pengaduan.deskripsiPenyaluran), ], ), @@ -1022,10 +1033,10 @@ class DetailPengaduanView extends GetView { Color dotColor; switch (tindakan.statusTindakan) { case 'SELESAI': - dotColor = Colors.green; + dotColor = statusSelesaiColor; break; case 'PROSES': - dotColor = Colors.blue; + dotColor = statusTindakanColor; break; default: dotColor = Colors.grey; @@ -1989,8 +2000,8 @@ class DetailPengaduanView extends GetView { : (newStatus == 'TINDAKAN' ? 'Tindakan' : 'Selesai'); Color statusColor = newStatus == 'MENUNGGU' - ? Colors.orange - : (newStatus == 'TINDAKAN' ? Colors.blue : Colors.green); + ? statusMenungguColor + : (newStatus == 'TINDAKAN' ? statusTindakanColor : statusSelesaiColor); showDialog( context: context, diff --git a/lib/app/modules/petugas_desa/views/pengaduan_view.dart b/lib/app/modules/petugas_desa/views/pengaduan_view.dart index 879a5b1..2d68969 100644 --- a/lib/app/modules/petugas_desa/views/pengaduan_view.dart +++ b/lib/app/modules/petugas_desa/views/pengaduan_view.dart @@ -9,30 +9,62 @@ class PengaduanView extends GetView { @override Widget build(BuildContext context) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Ringkasan pengaduan - _buildPengaduanSummary(context), + return RefreshIndicator( + onRefresh: controller.refreshData, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ringkasan pengaduan + _buildPengaduanSummary(context), - const SizedBox(height: 24), + const SizedBox(height: 24), - // Filter dan pencarian - _buildFilterSearch(context), + // Filter dan pencarian + _buildFilterSearch(context), - const SizedBox(height: 20), + // Informasi terakhir update + _buildLastUpdateInfo(context), - // Daftar pengaduan - _buildPengaduanList(context), - ], + const SizedBox(height: 20), + + // Daftar pengaduan + _buildPengaduanList(context), + ], + ), ), ), ); } + // Tambahkan widget untuk menampilkan waktu terakhir update + Widget _buildLastUpdateInfo(BuildContext context) { + final lastUpdate = DateTime + .now(); // Gunakan waktu saat ini atau dari controller jika tersedia + final formattedDate = DateTimeHelper.formatDateTimeWithHour(lastUpdate); + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + Icon(Icons.update, size: 16, color: Colors.grey[600]), + const SizedBox(width: 4), + Text( + 'Data terupdate: $formattedDate', + style: TextStyle( + fontSize: 12, + color: Colors.grey[600], + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ); + } + Widget _buildPengaduanSummary(BuildContext context) { return Obx(() { return Container( @@ -160,75 +192,36 @@ class PengaduanView extends GetView { color: Colors.grey.shade100, borderRadius: BorderRadius.circular(12), ), - child: IconButton( - onPressed: () { - // Tampilkan dialog filter - _showFilterDialog(context); - }, + child: PopupMenuButton( icon: const Icon(Icons.filter_list), tooltip: 'Filter', + onSelected: (index) { + controller.changeCategory(index); + }, + itemBuilder: (context) => [ + const PopupMenuItem( + value: 0, + child: Text('Semua'), + ), + const PopupMenuItem( + value: 1, + child: Text('Diproses'), + ), + const PopupMenuItem( + value: 2, + child: Text('Tindakan'), + ), + const PopupMenuItem( + value: 3, + child: Text('Selesai'), + ), + ], ), ), ], ); } - void _showFilterDialog(BuildContext context) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Filter Pengaduan'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Obx(() => RadioListTile( - title: const Text('Semua'), - value: 0, - groupValue: controller.selectedCategoryIndex.value, - onChanged: (value) { - controller.changeCategory(value!); - Navigator.pop(context); - }, - )), - Obx(() => RadioListTile( - title: const Text('Diproses'), - value: 1, - groupValue: controller.selectedCategoryIndex.value, - onChanged: (value) { - controller.changeCategory(value!); - Navigator.pop(context); - }, - )), - Obx(() => RadioListTile( - title: const Text('Tindakan'), - value: 2, - groupValue: controller.selectedCategoryIndex.value, - onChanged: (value) { - controller.changeCategory(value!); - Navigator.pop(context); - }, - )), - Obx(() => RadioListTile( - title: const Text('Selesai'), - value: 3, - groupValue: controller.selectedCategoryIndex.value, - onChanged: (value) { - controller.changeCategory(value!); - Navigator.pop(context); - }, - )), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Batal'), - ), - ], - ), - ); - } - Widget _buildPengaduanList(BuildContext context) { return Obx(() { if (controller.isLoading.value) { @@ -248,16 +241,16 @@ class PengaduanView extends GetView { padding: const EdgeInsets.all(20.0), child: Column( children: [ - const Icon( + Icon( Icons.inbox_outlined, size: 80, - color: Colors.grey, + color: Colors.grey.shade400, ), const SizedBox(height: 16), Text( 'Belum ada pengaduan', style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: Colors.grey, + color: Colors.grey.shade600, ), ), ], @@ -278,10 +271,11 @@ class PengaduanView extends GetView { fontWeight: FontWeight.bold, ), ), - IconButton( - icon: const Icon(Icons.refresh), - onPressed: () => controller.refreshData(), - tooltip: 'Refresh', + Text( + '${DateTimeHelper.formatNumber(filteredPengaduan.length)} item', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Colors.grey, + ), ), ], ), @@ -344,6 +338,7 @@ class PengaduanView extends GetView { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( @@ -352,9 +347,10 @@ class PengaduanView extends GetView { style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), - overflow: TextOverflow.ellipsis, + // overflow: TextOverflow.ellipsis, ), ), + const SizedBox(width: 12), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), @@ -383,63 +379,6 @@ class PengaduanView extends GetView { ), ], ), - const SizedBox(height: 4), - Text( - 'NIK: ${item.warga?['nik'] ?? ''}', - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Colors.grey, - ), - ), - const SizedBox(height: 12), - if (item.penerimaPenyaluran != null) ...[ - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade100, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - 'Penyaluran: ${item.namaPenyaluran}', - style: Theme.of(context).textTheme.bodySmall?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.blue.shade50, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - 'Jenis: ${item.jenisBantuan}', - style: Theme.of(context).textTheme.bodySmall, - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.green.shade50, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - 'Jumlah: ${item.jumlahBantuan}', - style: Theme.of(context).textTheme.bodySmall, - ), - ), - ), - ], - ), - ], const SizedBox(height: 8), Text( item.deskripsi ?? '', @@ -447,24 +386,72 @@ class PengaduanView extends GetView { maxLines: 2, overflow: TextOverflow.ellipsis, ), - const SizedBox(height: 8), + const SizedBox(height: 12), Row( children: [ - Icon( - Icons.calendar_today, - size: 14, - color: Colors.grey, + Expanded( + child: _buildItemDetail( + context, + icon: Icons.person, + label: 'Pelapor', + value: item.warga?['nama_lengkap'] ?? '', + ), ), - const SizedBox(width: 4), - Text( - formattedDate, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Colors.grey, - ), + Expanded( + child: _buildItemDetail( + context, + icon: Icons.numbers, + label: 'NIK', + value: item.warga?['nik'] ?? '', + ), ), ], ), const SizedBox(height: 12), + if (item.penerimaPenyaluran != null) ...[ + Row( + children: [ + Expanded( + child: _buildItemDetail( + context, + icon: Icons.shopping_bag, + label: 'Jumlah', + value: + '${item.jumlahBantuan} ${item.stokBantuan['satuan']}', + )), + Expanded( + child: _buildItemDetail( + context, + icon: Icons.inventory, + label: 'Stok Bantuan', + value: item.stokBantuan['nama'] ?? '', + ), + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: _buildItemDetail( + context, + icon: Icons.category, + label: 'Nama Penyaluran', + value: item.namaPenyaluran ?? '', + ), + ), + Expanded( + child: _buildItemDetail( + context, + icon: Icons.calendar_today, + label: 'Tanggal', + value: formattedDate, + ), + ), + ], + ), + ], + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.end, children: _buildActionButtons(context, item), @@ -475,6 +462,42 @@ class PengaduanView extends GetView { ); } + Widget _buildItemDetail( + BuildContext context, { + required IconData icon, + required String label, + required String value, + }) { + return Row( + children: [ + Icon( + icon, + size: 16, + color: Colors.grey, + ), + const SizedBox(width: 4), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.grey, + ), + ), + Text( + value, + style: Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ); + } + List _buildActionButtons(BuildContext context, dynamic item) { final status = item.status?.toUpperCase(); diff --git a/lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart b/lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart new file mode 100644 index 0000000..f0f95c3 --- /dev/null +++ b/lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart @@ -0,0 +1,657 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:penyaluran_app/app/modules/petugas_desa/controllers/pengaduan_controller.dart'; +import 'package:penyaluran_app/app/theme/app_theme.dart'; +import 'package:penyaluran_app/app/utils/date_time_helper.dart'; + +class PengaduanView extends GetView { + const PengaduanView({super.key}); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ringkasan pengaduan + _buildPengaduanSummary(context), + + const SizedBox(height: 24), + + // Filter dan pencarian + _buildFilterSearch(context), + + // Informasi terakhir update + _buildLastUpdateInfo(context), + + const SizedBox(height: 20), + + // Daftar pengaduan + _buildPengaduanList(context), + ], + ), + ), + ); + } + + // Tambahkan widget untuk menampilkan waktu terakhir update + Widget _buildLastUpdateInfo(BuildContext context) { + return Obx(() { + final lastUpdate = DateTime + .now(); // Gunakan waktu saat ini atau dari controller jika tersedia + final formattedDate = DateTimeHelper.formatDateTimeWithHour(lastUpdate); + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + Icon(Icons.update, size: 16, color: Colors.grey[600]), + const SizedBox(width: 4), + Text( + 'Data terupdate: $formattedDate', + style: TextStyle( + fontSize: 12, + color: Colors.grey[600], + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ); + }); + } + + Widget _buildPengaduanSummary(BuildContext context) { + return Obx(() { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: AppTheme.primaryGradient, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Ringkasan Pengaduan', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.pending_actions, + title: 'Diproses', + value: controller.jumlahDiproses.toString(), + color: Colors.orange, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.engineering, + title: 'Tindakan', + value: controller.jumlahTindakan.toString(), + color: Colors.blue, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.check_circle, + title: 'Selesai', + value: controller.jumlahSelesai.toString(), + color: Colors.green, + ), + ), + ], + ), + ], + ), + ); + }); + } + + Widget _buildSummaryItem( + BuildContext context, { + required IconData icon, + required String title, + required String value, + required Color color, + }) { + return Column( + children: [ + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.2), + shape: BoxShape.circle, + ), + child: Icon( + icon, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(height: 8), + Text( + value, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 4), + Text( + title, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ], + ); + } + + Widget _buildFilterSearch(BuildContext context) { + return Row( + children: [ + Expanded( + child: TextField( + controller: controller.searchController, + decoration: InputDecoration( + hintText: 'Cari pengaduan...', + prefixIcon: const Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide.none, + ), + filled: true, + fillColor: Colors.grey.shade100, + contentPadding: const EdgeInsets.symmetric(vertical: 0), + ), + onChanged: (value) { + // Implementasi pencarian + controller.refreshData(); + }, + ), + ), + const SizedBox(width: 12), + Container( + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(12), + ), + child: PopupMenuButton( + icon: const Icon(Icons.filter_list), + tooltip: 'Filter', + onSelected: (index) { + controller.changeCategory(index); + }, + itemBuilder: (context) => [ + const PopupMenuItem( + value: 0, + child: Text('Semua'), + ), + const PopupMenuItem( + value: 1, + child: Text('Diproses'), + ), + const PopupMenuItem( + value: 2, + child: Text('Tindakan'), + ), + const PopupMenuItem( + value: 3, + child: Text('Selesai'), + ), + ], + ), + ), + ], + ); + } + + Widget _buildPengaduanList(BuildContext context) { + return Obx(() { + if (controller.isLoading.value) { + return const Center( + child: Padding( + padding: EdgeInsets.all(20.0), + child: CircularProgressIndicator(), + ), + ); + } + + final filteredPengaduan = controller.getFilteredPengaduan(); + + if (filteredPengaduan.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Icon( + Icons.inbox_outlined, + size: 80, + color: Colors.grey.shade400, + ), + const SizedBox(height: 16), + Text( + 'Belum ada pengaduan', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + color: Colors.grey.shade600, + ), + ), + ], + ), + ), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Daftar Pengaduan', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Row( + children: [ + Text( + '${DateTimeHelper.formatNumber(filteredPengaduan.length)} item', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Colors.grey, + ), + ), + IconButton( + icon: const Icon(Icons.refresh), + onPressed: () => controller.refreshData(), + tooltip: 'Refresh', + ), + ], + ), + ], + ), + const SizedBox(height: 12), + ...filteredPengaduan + .map((item) => _buildPengaduanItem(context, item)), + ], + ); + }); + } + + Widget _buildPengaduanItem(BuildContext context, dynamic item) { + Color statusColor; + IconData statusIcon; + + switch (item.status?.toUpperCase()) { + case 'MENUNGGU': + statusColor = AppTheme.warningColor; + statusIcon = Icons.pending; + break; + case 'TINDAKAN': + statusColor = AppTheme.infoColor; + statusIcon = Icons.sync; + break; + case 'SELESAI': + statusColor = AppTheme.successColor; + statusIcon = Icons.check_circle; + break; + default: + statusColor = Colors.grey; + statusIcon = Icons.help_outline; + } + + // Format tanggal menggunakan DateTimeHelper + String formattedDate = ''; + if (item.tanggalPengaduan != null) { + formattedDate = DateTimeHelper.formatDate(item.tanggalPengaduan); + } else if (item.createdAt != null) { + formattedDate = DateTimeHelper.formatDate(item.createdAt); + } + + return Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.grey.withAlpha(26), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 1), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + item.warga?['nama'] ?? item.judul ?? '', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: statusColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + statusIcon, + size: 16, + color: statusColor, + ), + const SizedBox(width: 4), + Text( + item.status ?? '', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: statusColor, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 4), + _buildItemDetail( + context, + icon: Icons.person, + label: 'NIK', + value: item.warga?['nik'] ?? '', + ), + const SizedBox(height: 12), + if (item.penerimaPenyaluran != null) ...[ + Row( + children: [ + Expanded( + child: _buildItemDetail( + context, + icon: Icons.category, + label: 'Penyaluran', + value: item.namaPenyaluran ?? '', + ), + ), + Expanded( + child: _buildItemDetail( + context, + icon: Icons.inventory, + label: 'Jenis', + value: item.jenisBantuan ?? '', + ), + ), + ], + ), + const SizedBox(height: 8), + _buildItemDetail( + context, + icon: Icons.shopping_bag, + label: 'Jumlah', + value: item.jumlahBantuan ?? '', + ), + ], + const SizedBox(height: 8), + Text( + item.deskripsi ?? '', + style: Theme.of(context).textTheme.bodyMedium, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 8), + _buildItemDetail( + context, + icon: Icons.calendar_today, + label: 'Tanggal', + value: formattedDate, + ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _buildActionButtons(context, item), + ), + ], + ), + ), + ); + } + + Widget _buildItemDetail( + BuildContext context, { + required IconData icon, + required String label, + required String value, + }) { + return Row( + children: [ + Icon( + icon, + size: 16, + color: Colors.grey, + ), + const SizedBox(width: 4), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.grey, + ), + ), + Text( + value, + style: Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ); + } + + List _buildActionButtons(BuildContext context, dynamic item) { + final status = item.status?.toUpperCase(); + + if (status == 'MENUNGGU') { + return [ + TextButton.icon( + onPressed: () { + // Implementasi untuk memproses pengaduan + _showTindakanDialog(context, item); + }, + icon: const Icon(Icons.engineering, size: 18), + label: const Text('Tindakan'), + style: TextButton.styleFrom( + foregroundColor: Colors.blue, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + TextButton.icon( + onPressed: () { + // Navigasi ke halaman detail pengaduan + Get.toNamed('/detail-pengaduan', arguments: {'id': item.id}); + }, + icon: const Icon(Icons.info_outline, size: 18), + label: const Text('Detail'), + style: TextButton.styleFrom( + foregroundColor: Colors.grey, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + ]; + } else if (status == 'TINDAKAN') { + return [ + TextButton.icon( + onPressed: () { + // Implementasi untuk menyelesaikan pengaduan + _showSelesaikanDialog(context, item); + }, + icon: const Icon(Icons.check_circle, size: 18), + label: const Text('Selesaikan'), + style: TextButton.styleFrom( + foregroundColor: Colors.green, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + TextButton.icon( + onPressed: () { + // Navigasi ke halaman detail pengaduan + Get.toNamed('/detail-pengaduan', arguments: {'id': item.id}); + }, + icon: const Icon(Icons.info_outline, size: 18), + label: const Text('Detail'), + style: TextButton.styleFrom( + foregroundColor: Colors.grey, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + ]; + } else { + return [ + TextButton.icon( + onPressed: () { + // Navigasi ke halaman detail pengaduan + Get.toNamed('/detail-pengaduan', arguments: {'id': item.id}); + }, + icon: const Icon(Icons.info_outline, size: 18), + label: const Text('Detail'), + style: TextButton.styleFrom( + foregroundColor: Colors.grey, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + ]; + } + } + + void _showTindakanDialog(BuildContext context, dynamic item) { + controller.tindakanController.clear(); + controller.catatanController.clear(); + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Tindakan Pengaduan'), + content: Form( + key: controller.tindakanFormKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Pengaduan dari: ${item.warga?['nama'] ?? ''}'), + const SizedBox(height: 16), + TextFormField( + controller: controller.tindakanController, + decoration: const InputDecoration( + labelText: 'Tindakan yang dilakukan', + border: OutlineInputBorder(), + ), + maxLines: 3, + validator: controller.validateTindakan, + ), + const SizedBox(height: 12), + TextFormField( + controller: controller.catatanController, + decoration: const InputDecoration( + labelText: 'Catatan (opsional)', + border: OutlineInputBorder(), + ), + maxLines: 2, + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Batal'), + ), + ElevatedButton( + onPressed: () { + if (controller.tindakanFormKey.currentState!.validate()) { + Navigator.pop(context); + controller.tambahTindakanPengaduan( + pengaduanId: item.id!, + tindakan: controller.tindakanController.text, + kategoriTindakan: 'VERIFIKASI_DATA', + statusTindakan: 'PROSES', + prioritas: 'SEDANG', + catatan: controller.catatanController.text.isEmpty + ? null + : controller.catatanController.text, + buktiTindakanPaths: [], + ); + } + }, + child: const Text('Simpan'), + ), + ], + ), + ); + } + + void _showSelesaikanDialog(BuildContext context, dynamic item) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Selesaikan Pengaduan'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Pengaduan dari: ${item.warga?['nama'] ?? ''}'), + const SizedBox(height: 16), + const Text( + 'Apakah Anda yakin ingin menyelesaikan pengaduan ini?', + textAlign: TextAlign.center, + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Batal'), + ), + ElevatedButton( + onPressed: () { + Navigator.pop(context); + controller.selesaikanPengaduan(item.id!); + }, + child: const Text('Selesaikan'), + ), + ], + ), + ); + } +} diff --git a/temp.txt b/temp.txt new file mode 100644 index 0000000000000000000000000000000000000000..584bc5d4e54146b39f046019ee994d0a9d8b2caf GIT binary patch literal 42032 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 Zn&VZhydSk*^nHf0UQXBFq*Yhj{{In0Dp3Fc literal 0 HcmV?d00001