Perbarui dependensi dan konfigurasi lokal untuk mendukung fitur baru
- Tambahkan dependensi baru: syncfusion_flutter_calendar, syncfusion_localizations, dan flutter_localizations di pubspec.yaml - Perbarui konfigurasi lokal di main.dart untuk mendukung bahasa Indonesia dan menambahkan delegasi lokal - Modifikasi model PenyaluranBantuan untuk memastikan format tanggal menggunakan UTC - Perbarui tampilan dan logika di beberapa widget untuk meningkatkan pengalaman pengguna dan konsistensi data - Ganti posisi snack bar dari bawah ke atas untuk notifikasi yang lebih baik
This commit is contained in:
@ -6,6 +6,8 @@ import 'package:penyaluran_app/app/data/models/kategori_bantuan_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/user_model.dart';
|
||||
import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart';
|
||||
import 'package:penyaluran_app/app/services/supabase_service.dart';
|
||||
import 'package:penyaluran_app/app/utils/date_time_helper.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class JadwalPenyaluranController extends GetxController {
|
||||
final AuthController _authController = Get.find<AuthController>();
|
||||
@ -47,14 +49,99 @@ class JadwalPenyaluranController extends GetxController {
|
||||
loadPermintaanPenjadwalanData();
|
||||
loadLokasiPenyaluranData();
|
||||
loadKategoriBantuanData();
|
||||
|
||||
// Jalankan timer untuk memeriksa jadwal secara berkala
|
||||
_startJadwalCheckTimer();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
searchController.dispose();
|
||||
// Hentikan timer jika ada
|
||||
_stopJadwalCheckTimer();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
// Timer untuk memeriksa jadwal secara berkala
|
||||
Timer? _jadwalCheckTimer;
|
||||
|
||||
void _startJadwalCheckTimer() {
|
||||
// Periksa jadwal setiap 1 menit
|
||||
_jadwalCheckTimer = Timer.periodic(const Duration(minutes: 1), (_) {
|
||||
checkAndUpdateJadwalStatus();
|
||||
});
|
||||
|
||||
// Periksa jadwal segera saat aplikasi dimulai
|
||||
checkAndUpdateJadwalStatus();
|
||||
}
|
||||
|
||||
void _stopJadwalCheckTimer() {
|
||||
_jadwalCheckTimer?.cancel();
|
||||
_jadwalCheckTimer = null;
|
||||
}
|
||||
|
||||
// Memeriksa dan memperbarui status jadwal
|
||||
Future<void> checkAndUpdateJadwalStatus() async {
|
||||
try {
|
||||
// Dapatkan tanggal dan waktu saat ini dalam timezone lokal
|
||||
final now = DateTime.now();
|
||||
final today = DateTime(now.year, now.month, now.day);
|
||||
|
||||
// Periksa jadwal mendatang yang tanggalnya hari ini
|
||||
List<PenyaluranBantuanModel> jadwalToUpdate = [];
|
||||
|
||||
for (var jadwal in jadwalMendatang) {
|
||||
if (jadwal.tanggalPenyaluran != null) {
|
||||
// Konversi tanggal jadwal ke timezone lokal
|
||||
final jadwalDateTime =
|
||||
DateTimeHelper.toLocalDateTime(jadwal.tanggalPenyaluran!);
|
||||
final jadwalDate = DateTime(
|
||||
jadwalDateTime.year,
|
||||
jadwalDateTime.month,
|
||||
jadwalDateTime.day,
|
||||
);
|
||||
|
||||
// Jika tanggal jadwal adalah hari ini
|
||||
if (isSameDay(jadwalDate, today)) {
|
||||
jadwalToUpdate.add(jadwal);
|
||||
|
||||
// Jika waktu jadwal sudah tiba atau lewat
|
||||
if (now.isAfter(jadwalDateTime) ||
|
||||
now.isAtSameMomentAs(jadwalDateTime)) {
|
||||
// Ubah status menjadi BERLANGSUNG (aktif)
|
||||
await _supabaseService.updateJadwalStatus(
|
||||
jadwal.id!, 'BERLANGSUNG');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh data setelah pembaruan
|
||||
if (jadwalToUpdate.isNotEmpty) {
|
||||
await loadJadwalData();
|
||||
|
||||
// Tampilkan notifikasi jika ada jadwal yang dipindahkan
|
||||
Get.snackbar(
|
||||
'Jadwal Diperbarui',
|
||||
'${jadwalToUpdate.length} jadwal dipindahkan ke section Hari Ini',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error checking and updating jadwal status: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method untuk memeriksa apakah dua tanggal adalah hari yang sama
|
||||
bool isSameDay(DateTime date1, DateTime date2) {
|
||||
return date1.year == date2.year &&
|
||||
date1.month == date2.month &&
|
||||
date1.day == date2.day;
|
||||
}
|
||||
|
||||
Future<void> loadJadwalData() async {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
@ -155,7 +242,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Jadwal berhasil disetujui',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -164,7 +251,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menyetujui jadwal: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -181,7 +268,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Jadwal berhasil ditolak',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -190,7 +277,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menolak jadwal: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -207,7 +294,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Jadwal berhasil diselesaikan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -216,7 +303,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menyelesaikan jadwal: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -78,7 +78,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Laporan berhasil dibuat',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -88,7 +88,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal membuat laporan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -106,7 +106,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Laporan berhasil diunduh',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -116,7 +116,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengunduh laporan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -133,7 +133,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Laporan berhasil dihapus',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -142,7 +142,7 @@ class LaporanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menghapus laporan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -102,7 +102,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penerima bantuan berhasil ditambahkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -111,7 +111,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menambahkan penerima bantuan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -147,7 +147,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penerima bantuan berhasil diperbarui',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -156,7 +156,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal memperbarui penerima bantuan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -173,7 +173,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penerima bantuan berhasil dinonaktifkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -182,7 +182,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menonaktifkan penerima bantuan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -199,7 +199,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penerima bantuan berhasil diaktifkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -208,7 +208,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengaktifkan penerima bantuan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -76,7 +76,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Pengaduan berhasil diproses',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -85,7 +85,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal memproses pengaduan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -120,7 +120,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Tindakan berhasil ditambahkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -129,7 +129,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menambahkan tindakan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -146,7 +146,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Pengaduan berhasil diselesaikan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -155,7 +155,7 @@ class PengaduanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menyelesaikan pengaduan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -214,7 +214,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengambil gambar: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -237,7 +237,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengambil gambar: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -261,7 +261,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Foto bantuan harus diupload',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -291,7 +291,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penitipan bantuan berhasil ditambahkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -300,7 +300,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menambahkan penitipan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -315,7 +315,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Bukti serah terima harus diupload',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -339,7 +339,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penitipan berhasil diverifikasi',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -348,7 +348,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal memverifikasi penitipan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -369,7 +369,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Penitipan berhasil ditolak',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -378,7 +378,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menolak penitipan: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -666,7 +666,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menambahkan donatur: ${e.toString()}',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -19,6 +19,10 @@ class PetugasDesaController extends GetxController {
|
||||
// Controller untuk pencarian
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
// Controller untuk pencarian penerima
|
||||
final TextEditingController searchPenerimaController =
|
||||
TextEditingController();
|
||||
|
||||
// Data profil pengguna dari cache
|
||||
final RxMap<String, dynamic> userProfile = RxMap<String, dynamic>({});
|
||||
|
||||
@ -28,6 +32,23 @@ class PetugasDesaController extends GetxController {
|
||||
// Data jadwal hari ini
|
||||
final RxList<dynamic> jadwalHariIni = <dynamic>[].obs;
|
||||
|
||||
// Data penerima penyaluran
|
||||
final RxList<Map<String, dynamic>> penerimaPenyaluran =
|
||||
<Map<String, dynamic>>[].obs;
|
||||
final RxList<Map<String, dynamic>> filteredPenerima =
|
||||
<Map<String, dynamic>>[].obs;
|
||||
final RxInt jumlahPenerima = 0.obs;
|
||||
final RxString filterStatus = 'SEMUA'.obs;
|
||||
|
||||
// Tambahkan variabel isLoading
|
||||
final isLoading = false.obs;
|
||||
|
||||
// Tambahkan instance supabaseService yang sudah diinisialisasi
|
||||
final supabaseService = SupabaseService.to;
|
||||
|
||||
// Variabel untuk pencarian dan filter
|
||||
final searchQuery = ''.obs;
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
String get role => user?.role ?? 'PETUGASDESA';
|
||||
String get nama => user?.name ?? 'Petugas Desa';
|
||||
@ -81,6 +102,7 @@ class PetugasDesaController extends GetxController {
|
||||
@override
|
||||
void onClose() {
|
||||
searchController.dispose();
|
||||
searchPenerimaController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@ -216,6 +238,258 @@ class PetugasDesaController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
// Metode untuk memastikan format UUID yang benar
|
||||
String ensureValidUUID(String id) {
|
||||
// Jika ID sudah dalam format UUID yang benar, kembalikan apa adanya
|
||||
if (id.contains('-') && id.length == 36) {
|
||||
return id;
|
||||
}
|
||||
|
||||
// Jika ID adalah string UUID tanpa tanda hubung, tambahkan tanda hubung
|
||||
if (id.length == 32) {
|
||||
return '${id.substring(0, 8)}-${id.substring(8, 12)}-${id.substring(12, 16)}-${id.substring(16, 20)}-${id.substring(20)}';
|
||||
}
|
||||
|
||||
// Jika format tidak dikenali, kembalikan apa adanya
|
||||
return id;
|
||||
}
|
||||
|
||||
// Metode untuk memuat ulang data penerima
|
||||
Future<void> reloadPenerimaPenyaluran() async {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
// Gunakan data dummy sementara
|
||||
final dummyData = _createDummyPenerimaPenyaluran();
|
||||
penerimaPenyaluran.value = dummyData;
|
||||
jumlahPenerima.value = dummyData.length;
|
||||
print(
|
||||
'Data dummy penerima berhasil dimuat: ${penerimaPenyaluran.length} data');
|
||||
} catch (e) {
|
||||
print('Error saat memuat data dummy penerima: $e');
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Membuat data dummy penerima penyaluran
|
||||
List<Map<String, dynamic>> _createDummyPenerimaPenyaluran() {
|
||||
return [
|
||||
{
|
||||
'id': 1,
|
||||
'penyaluran_bantuan_id': 'a2dabc5a-761f-4f11-9fbe-a376768880c3',
|
||||
'warga_id': 'warga-001',
|
||||
'status_penerimaan': 'SUDAHMENERIMA',
|
||||
'jumlah_bantuan': 1,
|
||||
'created_at': '2023-01-01',
|
||||
'warga': {
|
||||
'id': 'warga-001',
|
||||
'nama_lengkap': 'Budi Santoso',
|
||||
'nik': '3201234567890001',
|
||||
'alamat': 'Jl. Merdeka No. 123, RT 01/RW 02',
|
||||
'jenis_kelamin': 'L',
|
||||
'tanggal_lahir': '1980-01-01',
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'penyaluran_bantuan_id': 'a2dabc5a-761f-4f11-9fbe-a376768880c3',
|
||||
'warga_id': 'warga-002',
|
||||
'status_penerimaan': 'BELUMMENERIMA',
|
||||
'jumlah_bantuan': 1,
|
||||
'created_at': '2023-01-01',
|
||||
'warga': {
|
||||
'id': 'warga-002',
|
||||
'nama_lengkap': 'Siti Aminah',
|
||||
'nik': '3201234567890002',
|
||||
'alamat': 'Jl. Pahlawan No. 45, RT 03/RW 04',
|
||||
'jenis_kelamin': 'P',
|
||||
'tanggal_lahir': '1985-05-15',
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
'penyaluran_bantuan_id': 'a2dabc5a-761f-4f11-9fbe-a376768880c3',
|
||||
'warga_id': 'warga-003',
|
||||
'status_penerimaan': 'SUDAHMENERIMA',
|
||||
'jumlah_bantuan': 1,
|
||||
'created_at': '2023-01-01',
|
||||
'warga': {
|
||||
'id': 'warga-003',
|
||||
'nama_lengkap': 'Ahmad Hidayat',
|
||||
'nik': '3201234567890003',
|
||||
'alamat': 'Jl. Cendrawasih No. 78, RT 05/RW 06',
|
||||
'jenis_kelamin': 'L',
|
||||
'tanggal_lahir': '1975-12-10',
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
'penyaluran_bantuan_id': 'a2dabc5a-761f-4f11-9fbe-a376768880c3',
|
||||
'warga_id': 'warga-004',
|
||||
'status_penerimaan': 'BELUMMENERIMA',
|
||||
'jumlah_bantuan': 1,
|
||||
'created_at': '2023-01-01',
|
||||
'warga': {
|
||||
'id': 'warga-004',
|
||||
'nama_lengkap': 'Dewi Lestari',
|
||||
'nik': '3201234567890004',
|
||||
'alamat': 'Jl. Mawar No. 12, RT 07/RW 08',
|
||||
'jenis_kelamin': 'P',
|
||||
'tanggal_lahir': '1990-08-22',
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 5,
|
||||
'penyaluran_bantuan_id': 'a2dabc5a-761f-4f11-9fbe-a376768880c3',
|
||||
'warga_id': 'warga-005',
|
||||
'status_penerimaan': 'SUDAHMENERIMA',
|
||||
'jumlah_bantuan': 1,
|
||||
'created_at': '2023-01-01',
|
||||
'warga': {
|
||||
'id': 'warga-005',
|
||||
'nama_lengkap': 'Joko Widodo',
|
||||
'nik': '3201234567890005',
|
||||
'alamat': 'Jl. Kenanga No. 56, RT 09/RW 10',
|
||||
'jenis_kelamin': 'L',
|
||||
'tanggal_lahir': '1965-06-30',
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// Metode untuk menginisialisasi data penerima penyaluran
|
||||
void initPenerimaPenyaluran(List<Map<String, dynamic>> data) {
|
||||
print(
|
||||
'DEBUG CONTROLLER: Inisialisasi penerima penyaluran dengan ${data.length} item');
|
||||
|
||||
// Periksa struktur data
|
||||
if (data.isNotEmpty) {
|
||||
final firstItem = data.first;
|
||||
print(
|
||||
'DEBUG CONTROLLER: Struktur data penerima: ${firstItem.keys.join(', ')}');
|
||||
|
||||
if (firstItem.containsKey('warga')) {
|
||||
final warga = firstItem['warga'];
|
||||
print(
|
||||
'DEBUG CONTROLLER: Struktur data warga: ${warga != null ? (warga is Map ? warga.keys.join(', ') : 'bukan Map') : 'null'}');
|
||||
} else {
|
||||
print(
|
||||
'DEBUG CONTROLLER: Data warga tidak ditemukan dalam item penerima');
|
||||
}
|
||||
}
|
||||
|
||||
penerimaPenyaluran.value = data;
|
||||
filteredPenerima.value = data;
|
||||
jumlahPenerima.value = data.length;
|
||||
|
||||
print(
|
||||
'DEBUG CONTROLLER: Selesai inisialisasi, jumlah penerima: ${jumlahPenerima.value}');
|
||||
}
|
||||
|
||||
// Metode untuk memfilter penerima berdasarkan kata kunci
|
||||
void filterPenerima(String keyword) {
|
||||
print('DEBUG CONTROLLER: Memfilter penerima dengan keyword: "$keyword"');
|
||||
|
||||
if (keyword.isEmpty) {
|
||||
print('DEBUG CONTROLLER: Keyword kosong, menerapkan filter status saja');
|
||||
applyFilters();
|
||||
return;
|
||||
}
|
||||
|
||||
final lowercaseKeyword = keyword.toLowerCase();
|
||||
final filtered = penerimaPenyaluran.where((penerima) {
|
||||
final warga = penerima['warga'] as Map<String, dynamic>?;
|
||||
if (warga == null) {
|
||||
print(
|
||||
'DEBUG CONTROLLER: Data warga null untuk penerima: ${penerima['id']}');
|
||||
return false;
|
||||
}
|
||||
|
||||
final namaLengkap =
|
||||
(warga['nama_lengkap'] ?? '').toString().toLowerCase();
|
||||
final nik = (warga['nik'] ?? '').toString().toLowerCase();
|
||||
final alamat = (warga['alamat'] ?? '').toString().toLowerCase();
|
||||
|
||||
final matches = namaLengkap.contains(lowercaseKeyword) ||
|
||||
nik.contains(lowercaseKeyword) ||
|
||||
alamat.contains(lowercaseKeyword);
|
||||
|
||||
return matches;
|
||||
}).toList();
|
||||
|
||||
print(
|
||||
'DEBUG CONTROLLER: Hasil filter: ${filtered.length} dari ${penerimaPenyaluran.length} item');
|
||||
filteredPenerima.value = filtered;
|
||||
}
|
||||
|
||||
// Metode untuk menerapkan filter status
|
||||
void applyFilters() {
|
||||
final keyword = searchPenerimaController.text.toLowerCase();
|
||||
print(
|
||||
'DEBUG CONTROLLER: Menerapkan filter dengan status: ${filterStatus.value}, keyword: "$keyword"');
|
||||
|
||||
if (filterStatus.value == 'SEMUA' && keyword.isEmpty) {
|
||||
print('DEBUG CONTROLLER: Tidak ada filter, menampilkan semua data');
|
||||
filteredPenerima.value = penerimaPenyaluran;
|
||||
return;
|
||||
}
|
||||
|
||||
final filtered = penerimaPenyaluran.where((penerima) {
|
||||
bool statusMatch = true;
|
||||
if (filterStatus.value != 'SEMUA') {
|
||||
statusMatch = penerima['status_penerimaan'] == filterStatus.value;
|
||||
}
|
||||
|
||||
if (keyword.isEmpty) return statusMatch;
|
||||
|
||||
final warga = penerima['warga'] as Map<String, dynamic>?;
|
||||
if (warga == null) return false;
|
||||
|
||||
final namaLengkap =
|
||||
(warga['nama_lengkap'] ?? '').toString().toLowerCase();
|
||||
final nik = (warga['nik'] ?? '').toString().toLowerCase();
|
||||
final alamat = (warga['alamat'] ?? '').toString().toLowerCase();
|
||||
|
||||
final keywordMatch = namaLengkap.contains(keyword) ||
|
||||
nik.contains(keyword) ||
|
||||
alamat.contains(keyword);
|
||||
|
||||
return statusMatch && keywordMatch;
|
||||
}).toList();
|
||||
|
||||
print(
|
||||
'DEBUG CONTROLLER: Hasil filter gabungan: ${filtered.length} dari ${penerimaPenyaluran.length} item');
|
||||
filteredPenerima.value = filtered;
|
||||
}
|
||||
|
||||
// Metode untuk memperbarui status penerimaan bantuan
|
||||
Future<bool> updateStatusPenerimaan(int penerimaId, String status,
|
||||
{DateTime? tanggalPenerimaan,
|
||||
String? buktiPenerimaan,
|
||||
String? keterangan}) async {
|
||||
try {
|
||||
final result = await _supabaseService.updateStatusPenerimaan(
|
||||
penerimaId, status,
|
||||
tanggalPenerimaan: tanggalPenerimaan,
|
||||
buktiPenerimaan: buktiPenerimaan,
|
||||
keterangan: keterangan);
|
||||
return result;
|
||||
} catch (e) {
|
||||
print('Error updating status penerimaan: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Metode untuk menyelesaikan jadwal penyaluran
|
||||
Future<void> completeJadwal(String jadwalId) async {
|
||||
try {
|
||||
await _supabaseService.completeJadwal(jadwalId);
|
||||
} catch (e) {
|
||||
print('Error completing jadwal: $e');
|
||||
throw e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Metode untuk mengubah tab aktif
|
||||
void changeTab(int index) {
|
||||
activeTabIndex.value = index;
|
||||
@ -251,4 +525,76 @@ class PetugasDesaController extends GetxController {
|
||||
Future<void> logout() async {
|
||||
await _authController.logout();
|
||||
}
|
||||
|
||||
// Metode untuk debugging struktur data jadwal
|
||||
void debugJadwalData(Map<String, dynamic> jadwal) {
|
||||
print('DEBUG CONTROLLER: ===== DEBUGGING JADWAL DATA =====');
|
||||
print('DEBUG CONTROLLER: Keys dalam jadwal: ${jadwal.keys.join(', ')}');
|
||||
|
||||
// Periksa ID
|
||||
final id = jadwal['id'];
|
||||
print('DEBUG CONTROLLER: ID jadwal: $id (${id.runtimeType})');
|
||||
|
||||
// Periksa data lain yang penting
|
||||
print('DEBUG CONTROLLER: Nama: ${jadwal['nama']}');
|
||||
print('DEBUG CONTROLLER: Status: ${jadwal['status']}');
|
||||
print('DEBUG CONTROLLER: Jumlah penerima: ${jadwal['jumlah_penerima']}');
|
||||
|
||||
// Periksa apakah ada data yang null
|
||||
jadwal.forEach((key, value) {
|
||||
if (value == null) {
|
||||
print('DEBUG CONTROLLER: Field "$key" bernilai null');
|
||||
}
|
||||
});
|
||||
|
||||
print('DEBUG CONTROLLER: ===== END DEBUGGING JADWAL DATA =====');
|
||||
}
|
||||
|
||||
// Metode untuk mendapatkan daftar penerima penyaluran
|
||||
Future<List<Map<String, dynamic>>?> getPenerimaPenyaluran(
|
||||
String penyaluranId) async {
|
||||
print(
|
||||
'DEBUG CONTROLLER: Mengambil data penerima untuk penyaluran ID: $penyaluranId');
|
||||
// Gunakan data dummy sementara
|
||||
final dummyData = _createDummyPenerimaPenyaluran();
|
||||
print(
|
||||
'DEBUG CONTROLLER: Mengembalikan ${dummyData.length} data dummy penerima');
|
||||
return dummyData;
|
||||
}
|
||||
|
||||
// Metode untuk memfilter data penerima berdasarkan status dan pencarian
|
||||
List<Map<String, dynamic>> get filteredPenerimaPenyaluran {
|
||||
if (penerimaPenyaluran.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> filtered =
|
||||
List<Map<String, dynamic>>.from(penerimaPenyaluran);
|
||||
|
||||
// Filter berdasarkan status
|
||||
if (filterStatus.value != 'SEMUA') {
|
||||
filtered = filtered.where((penerima) {
|
||||
return penerima['status_penerimaan'] == filterStatus.value;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
// Filter berdasarkan pencarian
|
||||
if (searchQuery.value.isNotEmpty) {
|
||||
final query = searchQuery.value.toLowerCase();
|
||||
filtered = filtered.where((penerima) {
|
||||
final warga = penerima['warga'] as Map<String, dynamic>?;
|
||||
if (warga == null) return false;
|
||||
|
||||
final nama = (warga['nama_lengkap'] ?? '').toString().toLowerCase();
|
||||
final nik = (warga['nik'] ?? '').toString().toLowerCase();
|
||||
final alamat = (warga['alamat'] ?? '').toString().toLowerCase();
|
||||
|
||||
return nama.contains(query) ||
|
||||
nik.contains(query) ||
|
||||
alamat.contains(query);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Stok bantuan berhasil ditambahkan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -132,7 +132,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menambahkan stok bantuan: $e',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -155,7 +155,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Stok bantuan berhasil diperbarui',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -164,7 +164,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal memperbarui stok bantuan: $e',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -178,7 +178,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Sukses',
|
||||
'Stok bantuan berhasil dihapus',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -187,7 +187,7 @@ class StokBantuanController extends GetxController {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal menghapus stok bantuan: $e',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
Reference in New Issue
Block a user