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:
@ -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|
|
@ -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~
|
@ -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
|
@ -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
|
@ -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,
|
||||
|
@ -9,30 +9,62 @@ class PengaduanView extends GetView<PengaduanController> {
|
||||
|
||||
@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<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',
|
||||
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<int>(
|
||||
title: const Text('Semua'),
|
||||
value: 0,
|
||||
groupValue: controller.selectedCategoryIndex.value,
|
||||
onChanged: (value) {
|
||||
controller.changeCategory(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)),
|
||||
Obx(() => RadioListTile<int>(
|
||||
title: const Text('Diproses'),
|
||||
value: 1,
|
||||
groupValue: controller.selectedCategoryIndex.value,
|
||||
onChanged: (value) {
|
||||
controller.changeCategory(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)),
|
||||
Obx(() => RadioListTile<int>(
|
||||
title: const Text('Tindakan'),
|
||||
value: 2,
|
||||
groupValue: controller.selectedCategoryIndex.value,
|
||||
onChanged: (value) {
|
||||
controller.changeCategory(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)),
|
||||
Obx(() => RadioListTile<int>(
|
||||
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<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();
|
||||
|
||||
|
657
lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart
Normal file
657
lib/app/modules/petugas_desa/views/pengaduan_view_backup.dart
Normal 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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user