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:
@ -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();
|
||||
|
||||
|
Reference in New Issue
Block a user