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.

This commit is contained in:
Khafidh Fuadi
2025-03-17 20:44:21 +07:00
parent aa73508108
commit 9eb2c5ac1a
8 changed files with 918 additions and 227 deletions

View File

@ -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  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>

}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\additional_project_files.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2~
}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\additional_project_files.txt  <08><>ס<EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2~
|
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build.json  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build.json  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
<EFBFBD>
D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build_mini.json  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2p
D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\android_gradle_build_mini.json  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2p
n
lD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja  <08><><EFBFBD><EFBFBD><EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2t
lD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja  <08><>ס<EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2t
r
pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2y
pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build.ninja.txt  <08><>ס<EFBFBD>2y
w
uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build_file_index.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2
uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\build_file_index.txt  <08><>ס<EFBFBD>2
K <20><><EFBFBD><EFBFBD><EFBFBD>2z
x
x
vD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json  <08><>ס<EFBFBD>2 ~
|
|
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\compile_commands.json.bin  <08><>ס<EFBFBD>2
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\metadata_generation_command.txt  <08><>ס<EFBFBD>2 <18> <20><><EFBFBD><EFBFBD><EFBFBD>2w
u
u
sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\arm64-v8a\prefab_config.json  <08><>ס<EFBFBD>2
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2|
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2|

View File

@ -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  κ<EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ɠס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
<EFBFBD>
D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\additional_project_files.txt  κ<EFBFBD><EFBFBD><EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\additional_project_files.txt  ɠס<EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
~
|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build.json  κ<EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build.json  ɠס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
<EFBFBD>
<EFBFBD>D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build_mini.json  κ<EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2r
<EFBFBD>D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\android_gradle_build_mini.json  ʠס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2r
p
nD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja  κ<EFBFBD><EFBFBD><EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2v
nD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja  ʠס<EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2v
t
rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja.txt  κ<EFBFBD><EFBFBD><EFBFBD>2{
rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build.ninja.txt  ʠס<EFBFBD>2{
y
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build_file_index.txt  κ<EFBFBD><EFBFBD><EFBFBD>2
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\build_file_index.txt  ʠס<EFBFBD>2
K <20><><EFBFBD><EFBFBD><EFBFBD>2|
z
z
xD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json  ʠס<CAA0>2 <09>
~
~
|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\compile_commands.json.bin  ʠס<CAA0>2
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\metadata_generation_command.txt  ʠס<CAA0>2 <18> <20><><EFBFBD><EFBFBD><EFBFBD>2y
w
w
uD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\armeabi-v7a\prefab_config.json  ʠס<CAA0>2
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2~
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2~

View File

@ -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  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2{
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2{
y
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\additional_project_files.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2x
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\additional_project_files.txt  <08><>ס<EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2x
v
tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build.json  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2}
tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build.json  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2}
{
yD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build_mini.json  <08><><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2j
yD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\android_gradle_build_mini.json  <08><>ס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2j
h
fD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja  <08><><EFBFBD><EFBFBD><EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2n
fD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja  <08><>ס<EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2n
l
jD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2s
jD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build.ninja.txt  <08><>ס<EFBFBD>2s
q
oD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build_file_index.txt  <08><><EFBFBD><EFBFBD><EFBFBD>2
oD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\build_file_index.txt  <08><>ס<EFBFBD>2
K <20><><EFBFBD><EFBFBD><EFBFBD>2t
r
r
pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json  <08><>ס<EFBFBD>2 x
v
v
tD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\compile_commands.json.bin  <08><>ס<EFBFBD>2
~
|
|
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\metadata_generation_command.txt  <08><>ס<EFBFBD>2 <18> <20><><EFBFBD><EFBFBD><EFBFBD>2q
o
o
mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86\prefab_config.json  <08><>ס<EFBFBD>2
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2v
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2v

View File

@ -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  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2~
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Ԣס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2~
|
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\additional_project_files.txt  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2{
zD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\additional_project_files.txt  Ԣס<EFBFBD>2  <20><><EFBFBD><EFBFBD><EFBFBD>2{
y
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build.json  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build.json  Ԣס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>
~
|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build_mini.json  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2m
|D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\android_gradle_build_mini.json  Ԣס<EFBFBD>2<18> <20><><EFBFBD><EFBFBD><EFBFBD>2m
k
iD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2q
iD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja  Ԣס<EFBFBD>2<18><> <20><><EFBFBD><EFBFBD><EFBFBD>2q
o
mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja.txt  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2v
mD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build.ninja.txt  Ԣס<EFBFBD>2v
t
rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build_file_index.txt  <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
rD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\build_file_index.txt  Ԣס<EFBFBD>2
K <20><><EFBFBD><EFBFBD><EFBFBD>2w
u
u
sD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json  Ԣס<D4A2>2 {
y
y
wD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\compile_commands.json.bin  Ԣס<D4A2>2
<EFBFBD>


}D:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\metadata_generation_command.txt  Ԣס<D4A2>2 <18> <20><><EFBFBD><EFBFBD><EFBFBD>2t
r
r
pD:\KULIAH\Matkul\SKRIPSI\penyaluran_app\penyaluran_app\android\app\.cxx\Debug\626b5o2n\x86_64\prefab_config.json  Ԣס<D4A2>2
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2y
 ( <20><><EFBFBD><EFBFBD><EFBFBD>2y

View File

@ -19,6 +19,11 @@ import 'package:penyaluran_app/app/widgets/inputs/text_input.dart';
class DetailPengaduanView extends GetView<PengaduanController> {
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<String, dynamic> args = Get.arguments ?? {};
@ -151,15 +156,15 @@ class DetailPengaduanView extends GetView<PengaduanController> {
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<PengaduanController> {
_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<PengaduanController> {
'PROSES',
'Dalam Proses',
'Tindakan sedang dilakukan',
Colors.blue,
statusTindakanColor,
Icons.sync,
),
const SizedBox(height: 8),
@ -291,7 +296,7 @@ class DetailPengaduanView extends GetView<PengaduanController> {
'SELESAI',
'Selesai',
'Tindakan telah selesai',
Colors.green,
statusSelesaiColor,
Icons.check_circle,
),
],
@ -539,19 +544,24 @@ class DetailPengaduanView extends GetView<PengaduanController> {
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<PengaduanController> {
status == 'MENUNGGU' ||
status == 'TINDAKAN' ||
status == 'SELESAI',
Colors.orange,
statusMenungguColor,
),
),
Expanded(
@ -622,7 +632,7 @@ class DetailPengaduanView extends GetView<PengaduanController> {
'Tindakan',
status == 'TINDAKAN',
status == 'TINDAKAN' || status == 'SELESAI',
Colors.blue,
statusTindakanColor,
),
),
Expanded(
@ -631,7 +641,7 @@ class DetailPengaduanView extends GetView<PengaduanController> {
'Selesai',
status == 'SELESAI',
status == 'SELESAI',
Colors.green,
statusSelesaiColor,
),
),
],
@ -646,7 +656,7 @@ class DetailPengaduanView extends GetView<PengaduanController> {
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<PengaduanController> {
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<PengaduanController> {
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<PengaduanController> {
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<PengaduanController> {
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<PengaduanController> {
// 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<PengaduanController> {
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<PengaduanController> {
: (newStatus == 'TINDAKAN' ? 'Tindakan' : 'Selesai');
Color statusColor = newStatus == 'MENUNGGU'
? Colors.orange
: (newStatus == 'TINDAKAN' ? Colors.blue : Colors.green);
? statusMenungguColor
: (newStatus == 'TINDAKAN' ? statusTindakanColor : statusSelesaiColor);
showDialog(
context: context,

View File

@ -9,7 +9,10 @@ class PengaduanView extends GetView<PengaduanController> {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
return RefreshIndicator(
onRefresh: controller.refreshData,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
@ -23,6 +26,9 @@ class PengaduanView extends GetView<PengaduanController> {
// Filter dan pencarian
_buildFilterSearch(context),
// Informasi terakhir update
_buildLastUpdateInfo(context),
const SizedBox(height: 20),
// Daftar pengaduan
@ -30,6 +36,32 @@ class PengaduanView extends GetView<PengaduanController> {
],
),
),
),
);
}
// 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,
),
),
],
),
);
}
@ -160,72 +192,33 @@ class PengaduanView extends GetView<PengaduanController> {
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
onPressed: () {
// Tampilkan dialog filter
_showFilterDialog(context);
},
child: PopupMenuButton<int>(
icon: const Icon(Icons.filter_list),
tooltip: 'Filter',
),
),
],
);
}
void _showFilterDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Filter Pengaduan'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Obx(() => RadioListTile<int>(
title: const Text('Semua'),
onSelected: (index) {
controller.changeCategory(index);
},
itemBuilder: (context) => [
const PopupMenuItem(
value: 0,
groupValue: controller.selectedCategoryIndex.value,
onChanged: (value) {
controller.changeCategory(value!);
Navigator.pop(context);
},
)),
Obx(() => RadioListTile<int>(
title: const Text('Diproses'),
child: Text('Semua'),
),
const PopupMenuItem(
value: 1,
groupValue: controller.selectedCategoryIndex.value,
onChanged: (value) {
controller.changeCategory(value!);
Navigator.pop(context);
},
)),
Obx(() => RadioListTile<int>(
title: const Text('Tindakan'),
child: Text('Diproses'),
),
const PopupMenuItem(
value: 2,
groupValue: controller.selectedCategoryIndex.value,
onChanged: (value) {
controller.changeCategory(value!);
Navigator.pop(context);
},
)),
Obx(() => RadioListTile<int>(
title: const Text('Selesai'),
child: Text('Tindakan'),
),
const PopupMenuItem(
value: 3,
groupValue: controller.selectedCategoryIndex.value,
onChanged: (value) {
controller.changeCategory(value!);
Navigator.pop(context);
},
)),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Batal'),
child: Text('Selesai'),
),
],
),
),
],
);
}
@ -248,16 +241,16 @@ class PengaduanView extends GetView<PengaduanController> {
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<PengaduanController> {
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<PengaduanController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
@ -352,9 +347,10 @@ class PengaduanView extends GetView<PengaduanController> {
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<PengaduanController> {
),
],
),
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<PengaduanController> {
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<PengaduanController> {
);
}
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<Widget> _buildActionButtons(BuildContext context, dynamic item) {
final status = item.status?.toUpperCase();

View File

@ -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<PengaduanController> {
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<int>(
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<Widget> _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'),
),
],
),
);
}
}

BIN
temp.txt Normal file

Binary file not shown.