Perbarui status dan model penyaluran untuk konsistensi dan fungsionalitas
- Ganti enum StatusKelayakan dari 'pending', 'disetujui', 'ditolak' menjadi 'MENUNGGU', 'TERVERIFIKASI', 'DITOLAK' - Ubah referensi 'jadwalSelesai' menjadi 'jadwalTerlaksana' di beberapa komponen - Perbarui ikon dan warna status di JadwalSectionWidget - Tambahkan logika baru untuk menangani status 'BATALTERLAKSANA' dan 'TERLAKSANA' di JadwalPenyaluranController - Modifikasi tampilan untuk menampilkan 'Terlaksana' dan 'Jumlah Penerima' secara otomatis di TambahPenyaluranView - Tambahkan fungsi untuk memuat data skema bantuan dan pengajuan kelayakan yang disetujui
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
enum StatusKelayakan { pending, disetujui, ditolak }
|
enum StatusKelayakan { MENUNGGU, TERVERIFIKASI, DITOLAK }
|
||||||
|
|
||||||
class PengajuanKelayakanBantuanModel {
|
class PengajuanKelayakanBantuanModel {
|
||||||
final String? id;
|
final String? id;
|
||||||
|
@ -245,7 +245,7 @@ class CalendarViewWidget extends StatelessWidget {
|
|||||||
List<PenyaluranBantuanModel> allJadwal = [
|
List<PenyaluranBantuanModel> allJadwal = [
|
||||||
...controller.jadwalHariIni,
|
...controller.jadwalHariIni,
|
||||||
...controller.jadwalMendatang,
|
...controller.jadwalMendatang,
|
||||||
...controller.jadwalSelesai,
|
...controller.jadwalTerlaksana,
|
||||||
];
|
];
|
||||||
|
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
|
@ -92,8 +92,10 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
return Icons.event_note;
|
return Icons.event_note;
|
||||||
case 'Terjadwal':
|
case 'Terjadwal':
|
||||||
return Icons.pending_actions;
|
return Icons.pending_actions;
|
||||||
case 'Selesai':
|
case 'Terlaksana':
|
||||||
return Icons.event_available;
|
return Icons.event_available;
|
||||||
|
case 'Tidak Terlaksana':
|
||||||
|
return Icons.event_busy;
|
||||||
default:
|
default:
|
||||||
return Icons.event_note;
|
return Icons.event_note;
|
||||||
}
|
}
|
||||||
@ -105,8 +107,9 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
return Icons.calendar_today;
|
return Icons.calendar_today;
|
||||||
case 'Terjadwal':
|
case 'Terjadwal':
|
||||||
return Icons.schedule;
|
return Icons.schedule;
|
||||||
case 'Selesai':
|
case 'Terlaksana':
|
||||||
return Icons.task_alt;
|
return Icons.task_alt;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Icons.event_note;
|
return Icons.event_note;
|
||||||
}
|
}
|
||||||
@ -118,7 +121,7 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
return Colors.green;
|
return Colors.green;
|
||||||
case 'Terjadwal':
|
case 'Terjadwal':
|
||||||
return Colors.blue;
|
return Colors.blue;
|
||||||
case 'Selesai':
|
case 'Terlaksana':
|
||||||
return Colors.grey;
|
return Colors.grey;
|
||||||
default:
|
default:
|
||||||
return Colors.orange;
|
return Colors.orange;
|
||||||
@ -127,16 +130,18 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
|
|
||||||
String _getStatusText(PenyaluranBantuanModel jadwal) {
|
String _getStatusText(PenyaluranBantuanModel jadwal) {
|
||||||
// Jika status jadwal adalah BERLANGSUNG, tampilkan sebagai "Aktif"
|
// Jika status jadwal adalah BERLANGSUNG, tampilkan sebagai "Aktif"
|
||||||
if (jadwal.status == 'BERLANGSUNG') {
|
if (jadwal.status == 'AKTIF') {
|
||||||
return 'Aktif';
|
return 'Aktif';
|
||||||
}
|
}
|
||||||
// Jika status jadwal adalah DIJADWALKAN, tampilkan sebagai "Terjadwal"
|
// Jika status jadwal adalah DIJADWALKAN, tampilkan sebagai "Terjadwal"
|
||||||
else if (jadwal.status == 'DIJADWALKAN' || jadwal.status == 'DISETUJUI') {
|
else if (jadwal.status == 'DIJADWALKAN') {
|
||||||
return 'Terjadwal';
|
return 'Terjadwal';
|
||||||
}
|
}
|
||||||
// Jika status jadwal adalah SELESAI, tampilkan sebagai "Selesai"
|
// Jika status jadwal adalah terlaksana, tampilkan sebagai "Terlaksana"
|
||||||
else if (jadwal.status == 'SELESAI') {
|
else if (jadwal.status == 'TERLAKSANA') {
|
||||||
return 'Selesai';
|
return 'Terlaksana';
|
||||||
|
} else if (jadwal.status == 'BATALTERLAKSANA') {
|
||||||
|
return 'Batal Terlaksana';
|
||||||
}
|
}
|
||||||
// Default status
|
// Default status
|
||||||
return status;
|
return status;
|
||||||
@ -144,16 +149,16 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
|
|
||||||
Color _getStatusColorByJadwal(PenyaluranBantuanModel jadwal) {
|
Color _getStatusColorByJadwal(PenyaluranBantuanModel jadwal) {
|
||||||
// Jika status jadwal adalah BERLANGSUNG, gunakan warna hijau
|
// Jika status jadwal adalah BERLANGSUNG, gunakan warna hijau
|
||||||
if (jadwal.status == 'BERLANGSUNG') {
|
if (jadwal.status == 'AKTIF') {
|
||||||
return Colors.green;
|
return Colors.green;
|
||||||
}
|
}
|
||||||
// Jika status jadwal adalah DIJADWALKAN, gunakan warna biru
|
// Jika status jadwal adalah DIJADWALKAN, gunakan warna biru
|
||||||
else if (jadwal.status == 'DIJADWALKAN' || jadwal.status == 'DISETUJUI') {
|
else if (jadwal.status == 'DIJADWALKAN') {
|
||||||
return Colors.blue;
|
return Colors.blue;
|
||||||
}
|
} else if (jadwal.status == 'TERLAKSANA') {
|
||||||
// Jika status jadwal adalah SELESAI, gunakan warna abu-abu
|
|
||||||
else if (jadwal.status == 'SELESAI') {
|
|
||||||
return Colors.grey;
|
return Colors.grey;
|
||||||
|
} else if (jadwal.status == 'BATALTERLAKSANA') {
|
||||||
|
return Colors.red;
|
||||||
}
|
}
|
||||||
// Default warna
|
// Default warna
|
||||||
return _getStatusColor();
|
return _getStatusColor();
|
||||||
@ -165,8 +170,8 @@ class JadwalSectionWidget extends StatelessWidget {
|
|||||||
return controller.jadwalHariIni.toList();
|
return controller.jadwalHariIni.toList();
|
||||||
case 'Mendatang':
|
case 'Mendatang':
|
||||||
return controller.jadwalMendatang.toList();
|
return controller.jadwalMendatang.toList();
|
||||||
case 'Selesai':
|
case 'Terlaksana':
|
||||||
return controller.jadwalSelesai.toList();
|
return controller.jadwalTerlaksana.toList();
|
||||||
default:
|
default:
|
||||||
return jadwalList;
|
return jadwalList;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import 'package:penyaluran_app/app/data/models/penyaluran_bantuan_model.dart';
|
|||||||
import 'package:penyaluran_app/app/data/models/lokasi_penyaluran_model.dart';
|
import 'package:penyaluran_app/app/data/models/lokasi_penyaluran_model.dart';
|
||||||
import 'package:penyaluran_app/app/data/models/kategori_bantuan_model.dart';
|
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/data/models/user_model.dart';
|
||||||
|
import 'package:penyaluran_app/app/data/models/skema_bantuan_model.dart';
|
||||||
import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.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/services/supabase_service.dart';
|
||||||
import 'package:penyaluran_app/app/utils/date_time_helper.dart';
|
import 'package:penyaluran_app/app/utils/date_time_helper.dart';
|
||||||
@ -13,6 +14,8 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
final AuthController _authController = Get.find<AuthController>();
|
final AuthController _authController = Get.find<AuthController>();
|
||||||
final SupabaseService _supabaseService = SupabaseService.to;
|
final SupabaseService _supabaseService = SupabaseService.to;
|
||||||
|
|
||||||
|
SupabaseService get supabaseService => _supabaseService;
|
||||||
|
|
||||||
final RxBool isLoading = false.obs;
|
final RxBool isLoading = false.obs;
|
||||||
|
|
||||||
// Indeks kategori yang dipilih untuk filter
|
// Indeks kategori yang dipilih untuk filter
|
||||||
@ -23,7 +26,7 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
<PenyaluranBantuanModel>[].obs;
|
<PenyaluranBantuanModel>[].obs;
|
||||||
final RxList<PenyaluranBantuanModel> jadwalMendatang =
|
final RxList<PenyaluranBantuanModel> jadwalMendatang =
|
||||||
<PenyaluranBantuanModel>[].obs;
|
<PenyaluranBantuanModel>[].obs;
|
||||||
final RxList<PenyaluranBantuanModel> jadwalSelesai =
|
final RxList<PenyaluranBantuanModel> jadwalTerlaksana =
|
||||||
<PenyaluranBantuanModel>[].obs;
|
<PenyaluranBantuanModel>[].obs;
|
||||||
|
|
||||||
// Data untuk permintaan penjadwalan
|
// Data untuk permintaan penjadwalan
|
||||||
@ -36,6 +39,8 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
<String, LokasiPenyaluranModel>{}.obs;
|
<String, LokasiPenyaluranModel>{}.obs;
|
||||||
final RxMap<String, KategoriBantuanModel> kategoriBantuanCache =
|
final RxMap<String, KategoriBantuanModel> kategoriBantuanCache =
|
||||||
<String, KategoriBantuanModel>{}.obs;
|
<String, KategoriBantuanModel>{}.obs;
|
||||||
|
final RxMap<String, SkemaBantuanModel> skemaBantuanCache =
|
||||||
|
<String, SkemaBantuanModel>{}.obs;
|
||||||
|
|
||||||
// Controller untuk pencarian
|
// Controller untuk pencarian
|
||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
@ -49,6 +54,7 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
loadPermintaanPenjadwalanData();
|
loadPermintaanPenjadwalanData();
|
||||||
loadLokasiPenyaluranData();
|
loadLokasiPenyaluranData();
|
||||||
loadKategoriBantuanData();
|
loadKategoriBantuanData();
|
||||||
|
loadSkemaBantuanData();
|
||||||
|
|
||||||
// Jalankan timer untuk memeriksa jadwal secara berkala
|
// Jalankan timer untuk memeriksa jadwal secara berkala
|
||||||
_startJadwalCheckTimer();
|
_startJadwalCheckTimer();
|
||||||
@ -89,8 +95,9 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
|
|
||||||
// Periksa jadwal mendatang yang tanggalnya hari ini
|
// Periksa jadwal mendatang yang tanggalnya hari ini
|
||||||
List<PenyaluranBantuanModel> jadwalToUpdate = [];
|
List<PenyaluranBantuanModel> jadwalToUpdate = [];
|
||||||
|
List<PenyaluranBantuanModel> jadwalTerlewat = [];
|
||||||
|
|
||||||
for (var jadwal in jadwalMendatang) {
|
for (var jadwal in jadwalHariIni) {
|
||||||
if (jadwal.tanggalPenyaluran != null) {
|
if (jadwal.tanggalPenyaluran != null) {
|
||||||
// Konversi tanggal jadwal ke timezone lokal
|
// Konversi tanggal jadwal ke timezone lokal
|
||||||
final jadwalDateTime =
|
final jadwalDateTime =
|
||||||
@ -103,24 +110,29 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
|
|
||||||
// Jika tanggal jadwal adalah hari ini
|
// Jika tanggal jadwal adalah hari ini
|
||||||
if (isSameDay(jadwalDate, today)) {
|
if (isSameDay(jadwalDate, today)) {
|
||||||
jadwalToUpdate.add(jadwal);
|
|
||||||
|
|
||||||
// Jika waktu jadwal sudah tiba atau lewat
|
// Jika waktu jadwal sudah tiba atau lewat
|
||||||
if (now.isAfter(jadwalDateTime) ||
|
if (now.isAfter(jadwalDateTime) ||
|
||||||
now.isAtSameMomentAs(jadwalDateTime)) {
|
now.isAtSameMomentAs(jadwalDateTime)) {
|
||||||
// Ubah status menjadi BERLANGSUNG (aktif)
|
if (jadwal.status == 'DIJADWALKAN') {
|
||||||
|
// Jika status masih DIJADWALKAN, ubah menjadi BATALTERLAKSANA
|
||||||
await _supabaseService.updateJadwalStatus(
|
await _supabaseService.updateJadwalStatus(
|
||||||
jadwal.id!, 'BERLANGSUNG');
|
jadwal.id!, 'BATALTERLAKSANA');
|
||||||
|
jadwalTerlewat.add(jadwal);
|
||||||
|
} else if (jadwal.status == 'AKTIF') {
|
||||||
|
// Jika status BERLANGSUNG, tambahkan ke daftar update
|
||||||
|
jadwalToUpdate.add(jadwal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh data setelah pembaruan
|
// Refresh data setelah pembaruan
|
||||||
if (jadwalToUpdate.isNotEmpty) {
|
if (jadwalToUpdate.isNotEmpty || jadwalTerlewat.isNotEmpty) {
|
||||||
await loadJadwalData();
|
await loadJadwalData();
|
||||||
|
|
||||||
// Tampilkan notifikasi jika ada jadwal yang dipindahkan
|
// Tampilkan notifikasi jika ada jadwal yang dipindahkan
|
||||||
|
if (jadwalToUpdate.isNotEmpty) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
'Jadwal Diperbarui',
|
'Jadwal Diperbarui',
|
||||||
'${jadwalToUpdate.length} jadwal dipindahkan ke section Hari Ini',
|
'${jadwalToUpdate.length} jadwal dipindahkan ke section Hari Ini',
|
||||||
@ -130,6 +142,19 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
duration: const Duration(seconds: 3),
|
duration: const Duration(seconds: 3),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tampilkan notifikasi jika ada jadwal yang terlewat
|
||||||
|
if (jadwalTerlewat.isNotEmpty) {
|
||||||
|
Get.snackbar(
|
||||||
|
'Jadwal Terlewat',
|
||||||
|
'${jadwalTerlewat.length} jadwal diubah menjadi BATALTERLAKSANA',
|
||||||
|
snackPosition: SnackPosition.TOP,
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
colorText: Colors.white,
|
||||||
|
duration: const Duration(seconds: 3),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error checking and updating jadwal status: $e');
|
print('Error checking and updating jadwal status: $e');
|
||||||
}
|
}
|
||||||
@ -162,9 +187,9 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mengambil data jadwal selesai
|
// Mengambil data jadwal selesai
|
||||||
final jadwalSelesaiData = await _supabaseService.getJadwalSelesai();
|
final jadwalTerlaksanaData = await _supabaseService.getJadwalTerlaksana();
|
||||||
if (jadwalSelesaiData != null) {
|
if (jadwalTerlaksanaData != null) {
|
||||||
jadwalSelesai.value = jadwalSelesaiData
|
jadwalTerlaksana.value = jadwalTerlaksanaData
|
||||||
.map((data) => PenyaluranBantuanModel.fromJson(data))
|
.map((data) => PenyaluranBantuanModel.fromJson(data))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
@ -219,6 +244,22 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> loadSkemaBantuanData() async {
|
||||||
|
try {
|
||||||
|
final skemaData = await _supabaseService.getAllSkemaBantuan();
|
||||||
|
if (skemaData != null) {
|
||||||
|
for (var skema in skemaData) {
|
||||||
|
final skemaModel = SkemaBantuanModel.fromJson(skema);
|
||||||
|
if (skemaModel.id != null) {
|
||||||
|
skemaBantuanCache[skemaModel.id!] = skemaModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error loading skema bantuan data: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mendapatkan nama lokasi penyaluran berdasarkan ID
|
// Mendapatkan nama lokasi penyaluran berdasarkan ID
|
||||||
String getLokasiPenyaluranName(String? lokasiId) {
|
String getLokasiPenyaluranName(String? lokasiId) {
|
||||||
if (lokasiId == null) return 'Lokasi tidak diketahui';
|
if (lokasiId == null) return 'Lokasi tidak diketahui';
|
||||||
@ -333,7 +374,7 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
Future<void> tambahPenyaluran({
|
Future<void> tambahPenyaluran({
|
||||||
required String nama,
|
required String nama,
|
||||||
required String deskripsi,
|
required String deskripsi,
|
||||||
required String kategoriBantuanId,
|
required String skemaId,
|
||||||
required String lokasiPenyaluranId,
|
required String lokasiPenyaluranId,
|
||||||
required int jumlahPenerima,
|
required int jumlahPenerima,
|
||||||
required DateTime? tanggalPenyaluran,
|
required DateTime? tanggalPenyaluran,
|
||||||
@ -349,7 +390,7 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
final penyaluran = {
|
final penyaluran = {
|
||||||
'nama': nama,
|
'nama': nama,
|
||||||
'deskripsi': deskripsi,
|
'deskripsi': deskripsi,
|
||||||
'kategori_bantuan_id': kategoriBantuanId,
|
'skema_id': skemaId,
|
||||||
'lokasi_penyaluran_id': lokasiPenyaluranId,
|
'lokasi_penyaluran_id': lokasiPenyaluranId,
|
||||||
'petugas_id': user!.id,
|
'petugas_id': user!.id,
|
||||||
'jumlah_penerima': jumlahPenerima,
|
'jumlah_penerima': jumlahPenerima,
|
||||||
@ -357,8 +398,30 @@ class JadwalPenyaluranController extends GetxController {
|
|||||||
'status': 'DIJADWALKAN', // Status awal adalah terjadwal
|
'status': 'DIJADWALKAN', // Status awal adalah terjadwal
|
||||||
};
|
};
|
||||||
|
|
||||||
// Simpan ke database
|
// Simpan ke database dan dapatkan ID penyaluran
|
||||||
await _supabaseService.tambahPenyaluran(penyaluran);
|
final response = await _supabaseService.tambahPenyaluran(penyaluran);
|
||||||
|
final penyaluranId = response['id'];
|
||||||
|
|
||||||
|
// Ambil data pengajuan kelayakan bantuan yang disetujui
|
||||||
|
final pengajuanData = await _supabaseService.client
|
||||||
|
.from('xx02_pengajuan_kelayakan_bantuan')
|
||||||
|
.select('*')
|
||||||
|
.eq('skema_bantuan_id', skemaId)
|
||||||
|
.eq('status', 'TERVERIFIKASI');
|
||||||
|
|
||||||
|
// Buat data penerima penyaluran untuk setiap pengajuan yang disetujui
|
||||||
|
for (var pengajuan in pengajuanData) {
|
||||||
|
final penerimaPenyaluran = {
|
||||||
|
'penyaluran_bantuan_id': penyaluranId,
|
||||||
|
'warga_id': pengajuan['warga_id'],
|
||||||
|
'stok_bantuan_id': skemaBantuanCache[skemaId]?.stokBantuanId,
|
||||||
|
'status_penerimaan': 'MENUNGGU',
|
||||||
|
};
|
||||||
|
|
||||||
|
await _supabaseService.client
|
||||||
|
.from('penerima_penyaluran')
|
||||||
|
.insert(penerimaPenyaluran);
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh data
|
// Refresh data
|
||||||
await loadJadwalData();
|
await loadJadwalData();
|
||||||
|
@ -101,9 +101,9 @@ class PenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
// Jadwal selesai
|
// Jadwal selesai
|
||||||
JadwalSectionWidget(
|
JadwalSectionWidget(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
title: 'Selesai',
|
title: 'Terlaksana',
|
||||||
jadwalList: controller.jadwalSelesai,
|
jadwalList: controller.jadwalTerlaksana,
|
||||||
status: 'Selesai',
|
status: 'Terlaksana',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -190,9 +190,9 @@ class PenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Obx(() => _buildSummaryItem(
|
child: Obx(() => _buildSummaryItem(
|
||||||
context,
|
context,
|
||||||
icon: Icons.event_busy,
|
icon: Icons.event_note,
|
||||||
title: 'Selesai',
|
title: 'Terlaksana',
|
||||||
value: '${controller.jadwalSelesai.length}',
|
value: '${controller.jadwalTerlaksana.length}',
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
|
@ -3,6 +3,8 @@ import 'package:get/get.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/jadwal_penyaluran_controller.dart';
|
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/jadwal_penyaluran_controller.dart';
|
||||||
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
||||||
|
import 'package:penyaluran_app/app/data/models/skema_bantuan_model.dart';
|
||||||
|
import 'package:penyaluran_app/app/data/models/pengajuan_kelayakan_bantuan_model.dart';
|
||||||
|
|
||||||
class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
||||||
const TambahPenyaluranView({super.key});
|
const TambahPenyaluranView({super.key});
|
||||||
@ -23,21 +25,38 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
final formKey = GlobalKey<FormState>();
|
final formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController namaController = TextEditingController();
|
final TextEditingController namaController = TextEditingController();
|
||||||
final TextEditingController deskripsiController = TextEditingController();
|
final TextEditingController deskripsiController = TextEditingController();
|
||||||
final TextEditingController jumlahPenerimaController =
|
|
||||||
TextEditingController();
|
|
||||||
final TextEditingController tanggalPenyaluranController =
|
final TextEditingController tanggalPenyaluranController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
final TextEditingController waktuPenyaluranController =
|
final TextEditingController waktuPenyaluranController =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
|
|
||||||
// Variabel untuk menyimpan nilai yang dipilih
|
// Variabel untuk menyimpan nilai yang dipilih
|
||||||
final Rx<String?> selectedKategoriBantuanId = Rx<String?>(null);
|
final Rx<String?> selectedSkemaBantuanId = Rx<String?>(null);
|
||||||
final Rx<String?> selectedLokasiPenyaluranId = Rx<String?>(null);
|
final Rx<String?> selectedLokasiPenyaluranId = Rx<String?>(null);
|
||||||
|
final Rx<SkemaBantuanModel?> selectedSkemaBantuan =
|
||||||
|
Rx<SkemaBantuanModel?>(null);
|
||||||
|
final RxInt jumlahPenerima = 0.obs;
|
||||||
|
|
||||||
// Tanggal dan waktu penyaluran
|
// Tanggal dan waktu penyaluran
|
||||||
final Rx<DateTime?> selectedDate = Rx<DateTime?>(null);
|
final Rx<DateTime?> selectedDate = Rx<DateTime?>(null);
|
||||||
final Rx<TimeOfDay?> selectedTime = Rx<TimeOfDay?>(null);
|
final Rx<TimeOfDay?> selectedTime = Rx<TimeOfDay?>(null);
|
||||||
|
|
||||||
|
// Fungsi untuk memuat data pengajuan kelayakan bantuan
|
||||||
|
Future<void> loadPengajuanKelayakan(String skemaId) async {
|
||||||
|
try {
|
||||||
|
final pengajuanData = await controller.supabaseService.client
|
||||||
|
.from('xx02_pengajuan_kelayakan_bantuan')
|
||||||
|
.select('*')
|
||||||
|
.eq('skema_bantuan_id', skemaId)
|
||||||
|
.eq('status', 'TERVERIFIKASI');
|
||||||
|
print('pengajuan $pengajuanData');
|
||||||
|
|
||||||
|
jumlahPenerima.value = pengajuanData.length;
|
||||||
|
} catch (e) {
|
||||||
|
print('Error loading pengajuan kelayakan: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Form(
|
child: Form(
|
||||||
@ -82,9 +101,9 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Kategori Bantuan
|
// Skema Bantuan
|
||||||
Text(
|
Text(
|
||||||
'Kategori Bantuan',
|
'Skema Bantuan',
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -98,20 +117,25 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
vertical: 8,
|
vertical: 8,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
hint: const Text('Pilih kategori bantuan'),
|
hint: const Text('Pilih skema bantuan'),
|
||||||
value: selectedKategoriBantuanId.value,
|
value: selectedSkemaBantuanId.value,
|
||||||
items: controller.kategoriBantuanCache.entries
|
items: controller.skemaBantuanCache.entries
|
||||||
.map((entry) => DropdownMenuItem<String>(
|
.map((entry) => DropdownMenuItem<String>(
|
||||||
value: entry.key,
|
value: entry.key,
|
||||||
child: Text(entry.value.nama ?? 'Tidak ada nama'),
|
child: Text(entry.value.nama ?? 'Tidak ada nama'),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
onChanged: (value) {
|
onChanged: (value) async {
|
||||||
selectedKategoriBantuanId.value = value;
|
selectedSkemaBantuanId.value = value;
|
||||||
|
if (value != null) {
|
||||||
|
selectedSkemaBantuan.value =
|
||||||
|
controller.skemaBantuanCache[value];
|
||||||
|
await loadPengajuanKelayakan(value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Kategori bantuan harus dipilih';
|
return 'Skema bantuan harus dipilih';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@ -154,17 +178,18 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
)),
|
)),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Jumlah Penerima
|
// Jumlah Penerima (Otomatis)
|
||||||
Text(
|
Text(
|
||||||
'Jumlah Penerima',
|
'Jumlah Penerima',
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
TextFormField(
|
Obx(() => TextFormField(
|
||||||
controller: jumlahPenerimaController,
|
readOnly: true,
|
||||||
keyboardType: TextInputType.number,
|
controller: TextEditingController(
|
||||||
|
text: jumlahPenerima.value.toString()),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Masukkan jumlah penerima',
|
hintText: 'Jumlah penerima akan diambil otomatis',
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
@ -173,19 +198,97 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
vertical: 8,
|
vertical: 8,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
validator: (value) {
|
)),
|
||||||
if (value == null || value.isEmpty) {
|
const SizedBox(height: 8),
|
||||||
return 'Jumlah penerima tidak boleh kosong';
|
Obx(() => jumlahPenerima.value > 0
|
||||||
}
|
? TextButton.icon(
|
||||||
if (int.tryParse(value) == null) {
|
onPressed: () async {
|
||||||
return 'Jumlah penerima harus berupa angka';
|
final pengajuanData = await controller
|
||||||
}
|
.supabaseService.client
|
||||||
if (int.parse(value) <= 0) {
|
.from('xx02_pengajuan_kelayakan_bantuan')
|
||||||
return 'Jumlah penerima harus lebih dari 0';
|
.select('*, warga:warga_id(*)')
|
||||||
}
|
.eq('skema_bantuan_id',
|
||||||
return null;
|
selectedSkemaBantuanId.value ?? '')
|
||||||
},
|
.eq('status', 'TERVERIFIKASI');
|
||||||
|
|
||||||
|
if (pengajuanData != null) {
|
||||||
|
Get.dialog(
|
||||||
|
Dialog(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.of(context).size.width * 0.9,
|
||||||
|
height:
|
||||||
|
MediaQuery.of(context).size.height * 0.8,
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Daftar Penerima Bantuan',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: DataTable(
|
||||||
|
columnSpacing: 20,
|
||||||
|
horizontalMargin: 20,
|
||||||
|
columns: const [
|
||||||
|
DataColumn(label: Text('No')),
|
||||||
|
DataColumn(label: Text('Nama')),
|
||||||
|
DataColumn(label: Text('NIK')),
|
||||||
|
DataColumn(label: Text('Alamat')),
|
||||||
|
],
|
||||||
|
rows: pengajuanData
|
||||||
|
.asMap()
|
||||||
|
.entries
|
||||||
|
.map((entry) {
|
||||||
|
final warga =
|
||||||
|
entry.value['warga'];
|
||||||
|
return DataRow(
|
||||||
|
cells: [
|
||||||
|
DataCell(
|
||||||
|
Text('${entry.key + 1}')),
|
||||||
|
DataCell(Text(
|
||||||
|
warga['nama_lengkap'] ??
|
||||||
|
'-')),
|
||||||
|
DataCell(Text(
|
||||||
|
warga['nik'] ?? '-')),
|
||||||
|
DataCell(Text(
|
||||||
|
warga['alamat'] ?? '-')),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.people),
|
||||||
|
label: const Text('Lihat Daftar Penerima'),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink()),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Tanggal Penyaluran
|
// Tanggal Penyaluran
|
||||||
@ -321,10 +424,9 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
|||||||
controller.tambahPenyaluran(
|
controller.tambahPenyaluran(
|
||||||
nama: namaController.text,
|
nama: namaController.text,
|
||||||
deskripsi: deskripsiController.text,
|
deskripsi: deskripsiController.text,
|
||||||
kategoriBantuanId: selectedKategoriBantuanId.value!,
|
skemaId: selectedSkemaBantuanId.value!,
|
||||||
lokasiPenyaluranId: selectedLokasiPenyaluranId.value!,
|
lokasiPenyaluranId: selectedLokasiPenyaluranId.value!,
|
||||||
jumlahPenerima:
|
jumlahPenerima: jumlahPenerima.value,
|
||||||
int.parse(jumlahPenerimaController.text),
|
|
||||||
tanggalPenyaluran: tanggalWaktuPenyaluran,
|
tanggalPenyaluran: tanggalWaktuPenyaluran,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ class SupabaseService extends GetxService {
|
|||||||
.select('*')
|
.select('*')
|
||||||
.gte('tanggal_penyaluran', todayUtc)
|
.gte('tanggal_penyaluran', todayUtc)
|
||||||
.lt('tanggal_penyaluran', tomorrowUtc)
|
.lt('tanggal_penyaluran', tomorrowUtc)
|
||||||
.inFilter('status', ['DISETUJUI', 'BERLANGSUNG', 'DIJADWALKAN']);
|
.inFilter('status', ['AKTIF', 'DIJADWALKAN']);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -267,7 +267,7 @@ class SupabaseService extends GetxService {
|
|||||||
.select('*')
|
.select('*')
|
||||||
.gte('tanggal_penyaluran', tomorrowUtc)
|
.gte('tanggal_penyaluran', tomorrowUtc)
|
||||||
.lt('tanggal_penyaluran', weekUtc)
|
.lt('tanggal_penyaluran', weekUtc)
|
||||||
.inFilter('status', ['DISETUJUI', 'DIJADWALKAN']);
|
.inFilter('status', ['DIJADWALKAN']);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -276,12 +276,12 @@ class SupabaseService extends GetxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Map<String, dynamic>>?> getJadwalSelesai() async {
|
Future<List<Map<String, dynamic>>?> getJadwalTerlaksana() async {
|
||||||
try {
|
try {
|
||||||
final response = await client
|
final response = await client
|
||||||
.from('penyaluran_bantuan')
|
.from('penyaluran_bantuan')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('status', 'SELESAI')
|
.eq('status', 'TERLAKSANA')
|
||||||
.order('tanggal_penyaluran', ascending: false)
|
.order('tanggal_penyaluran', ascending: false)
|
||||||
.limit(10);
|
.limit(10);
|
||||||
|
|
||||||
@ -1124,12 +1124,33 @@ class SupabaseService extends GetxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi untuk menambahkan penyaluran baru
|
// Fungsi untuk menambahkan penyaluran baru
|
||||||
Future<void> tambahPenyaluran(Map<String, dynamic> penyaluran) async {
|
Future<Map<String, dynamic>> tambahPenyaluran(
|
||||||
|
Map<String, dynamic> penyaluran) async {
|
||||||
try {
|
try {
|
||||||
await client.from('penyaluran_bantuan').insert(penyaluran);
|
final response = await client
|
||||||
|
.from('penyaluran_bantuan')
|
||||||
|
.insert(penyaluran)
|
||||||
|
.select()
|
||||||
|
.single();
|
||||||
|
|
||||||
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error menambahkan penyaluran: $e');
|
print('Error menambahkan penyaluran: $e');
|
||||||
throw e.toString();
|
throw e.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<Map<String, dynamic>>?> getAllSkemaBantuan() async {
|
||||||
|
try {
|
||||||
|
final response = await client
|
||||||
|
.from('xx02_skema_bantuan')
|
||||||
|
.select('*')
|
||||||
|
.order('created_at', ascending: false);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
print('Error getting all skema bantuan: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user