From cdbd659d6380d2b6e699025172abaf558a60be6e Mon Sep 17 00:00:00 2001 From: Khafidh Fuadi Date: Tue, 11 Mar 2025 18:55:06 +0700 Subject: [PATCH] Tambahkan fitur jenis bantuan pada modul stok bantuan - Perbarui model StokBantuanModel untuk mendukung jenis bantuan - Tambahkan metode loadJenisBantuanData() di StokBantuanController - Integrasikan dropdown pemilihan jenis bantuan di form tambah/edit stok - Perbarui SupabaseService untuk mengambil data jenis bantuan - Tampilkan nama jenis bantuan di daftar stok bantuan --- lib/app/data/models/stok_bantuan_model.dart | 7 +++ .../controllers/penerima_controller.dart | 1 - .../controllers/stok_bantuan_controller.dart | 17 ++++++ .../petugas_desa/views/petugas_desa_view.dart | 29 +--------- .../petugas_desa/views/stok_bantuan_view.dart | 57 ++++++++++++++++++- lib/app/services/supabase_service.dart | 19 +++++-- lib/main.dart | 1 - 7 files changed, 95 insertions(+), 36 deletions(-) diff --git a/lib/app/data/models/stok_bantuan_model.dart b/lib/app/data/models/stok_bantuan_model.dart index 0f87e1a..160ce32 100644 --- a/lib/app/data/models/stok_bantuan_model.dart +++ b/lib/app/data/models/stok_bantuan_model.dart @@ -5,6 +5,8 @@ class StokBantuanModel { final String? nama; final String? bentukBantuanId; final String? sumberBantuanId; + final String? jenisBantuanId; + final Map? jenisBantuan; final double? jumlah; final String? satuan; final String? deskripsi; @@ -19,6 +21,8 @@ class StokBantuanModel { this.nama, this.bentukBantuanId, this.sumberBantuanId, + this.jenisBantuanId, + this.jenisBantuan, this.jumlah, this.satuan, this.deskripsi, @@ -40,6 +44,8 @@ class StokBantuanModel { nama: json["nama"], bentukBantuanId: json["bentuk_bantuan_id"], sumberBantuanId: json["sumber_bantuan_id"], + jenisBantuanId: json["jenis_bantuan_id"], + jenisBantuan: json["jenis_bantuan"], jumlah: json["jumlah"] != null ? json["jumlah"].toDouble() : 0.0, satuan: json["satuan"], deskripsi: json["deskripsi"], @@ -63,6 +69,7 @@ class StokBantuanModel { "nama": nama, "bentuk_bantuan_id": bentukBantuanId, "sumber_bantuan_id": sumberBantuanId, + "jenis_bantuan_id": jenisBantuanId, "jumlah": jumlah, "satuan": satuan, "deskripsi": deskripsi, diff --git a/lib/app/modules/petugas_desa/controllers/penerima_controller.dart b/lib/app/modules/petugas_desa/controllers/penerima_controller.dart index 7b7ae58..d18d898 100644 --- a/lib/app/modules/petugas_desa/controllers/penerima_controller.dart +++ b/lib/app/modules/petugas_desa/controllers/penerima_controller.dart @@ -1,7 +1,6 @@ import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import 'package:penyaluran_app/app/utils/date_formatter.dart'; class PenerimaController extends GetxController { final RxList> daftarPenerima = diff --git a/lib/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart b/lib/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart index 108ca2e..1f06932 100644 --- a/lib/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart +++ b/lib/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart @@ -17,6 +17,10 @@ class StokBantuanController extends GetxController { final RxDouble stokMasuk = 0.0.obs; final RxDouble stokKeluar = 0.0.obs; + // Data untuk jenis bantuan + final RxList> daftarJenisBantuan = + >[].obs; + // Controller untuk pencarian final TextEditingController searchController = TextEditingController(); final RxString searchQuery = ''.obs; @@ -27,6 +31,7 @@ class StokBantuanController extends GetxController { void onInit() { super.onInit(); loadStokBantuanData(); + loadJenisBantuanData(); // Listener untuk pencarian searchController.addListener(() { @@ -69,6 +74,17 @@ class StokBantuanController extends GetxController { } } + Future loadJenisBantuanData() async { + try { + final jenisBantuanData = await _supabaseService.getJenisBantuan(); + if (jenisBantuanData != null) { + daftarJenisBantuan.value = jenisBantuanData; + } + } catch (e) { + print('Error loading jenis bantuan data: $e'); + } + } + Future addStok(StokBantuanModel stok) async { isLoading.value = true; try { @@ -151,6 +167,7 @@ class StokBantuanController extends GetxController { isLoading.value = true; try { await loadStokBantuanData(); + await loadJenisBantuanData(); } finally { isLoading.value = false; } diff --git a/lib/app/modules/petugas_desa/views/petugas_desa_view.dart b/lib/app/modules/petugas_desa/views/petugas_desa_view.dart index 86e29e5..e82f009 100644 --- a/lib/app/modules/petugas_desa/views/petugas_desa_view.dart +++ b/lib/app/modules/petugas_desa/views/petugas_desa_view.dart @@ -124,34 +124,7 @@ class PetugasDesaView extends GetView { ], ); } else if (activeTab == 4) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: const Icon(Icons.add), - tooltip: 'Tambah Pengaduan', - onPressed: () { - // Implementasi untuk menambah pengaduan baru - }, - ), - IconButton( - icon: const Icon(Icons.filter_list), - tooltip: 'Filter Pengaduan', - onPressed: () { - // Implementasi untuk filter pengaduan - }, - ), - IconButton( - icon: const Icon(Icons.refresh), - tooltip: 'Perbarui Counter', - onPressed: () { - // Perbarui counter pengaduan secara manual - controller.updatePengaduanCounter(); - }, - ), - notificationButton, - ], - ); + return notificationButton; } else { return notificationButton; } diff --git a/lib/app/modules/petugas_desa/views/stok_bantuan_view.dart b/lib/app/modules/petugas_desa/views/stok_bantuan_view.dart index faee4a7..7acf7f7 100644 --- a/lib/app/modules/petugas_desa/views/stok_bantuan_view.dart +++ b/lib/app/modules/petugas_desa/views/stok_bantuan_view.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:intl/intl.dart'; import 'package:penyaluran_app/app/data/models/stok_bantuan_model.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart'; import 'package:penyaluran_app/app/theme/app_theme.dart'; @@ -277,7 +276,9 @@ class StokBantuanView extends GetView { borderRadius: BorderRadius.circular(8), ), child: Text( - item.status ?? 'TERSEDIA', + item.jenisBantuan != null + ? (item.jenisBantuan!['nama'] ?? 'Tidak Ada Jenis') + : 'Tidak Ada Jenis', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: AppTheme.primaryColor, fontWeight: FontWeight.bold, @@ -417,6 +418,7 @@ class StokBantuanView extends GetView { final jumlahController = TextEditingController(); final satuanController = TextEditingController(); final deskripsiController = TextEditingController(); + String? selectedJenisBantuanId; DateTime? tanggalMasuk = DateTime.now(); DateTime? tanggalKadaluarsa; @@ -444,6 +446,30 @@ class StokBantuanView extends GetView { }, ), const SizedBox(height: 16), + DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Jenis Bantuan', + border: OutlineInputBorder(), + ), + value: selectedJenisBantuanId, + hint: const Text('Pilih Jenis Bantuan'), + items: controller.daftarJenisBantuan + .map((jenis) => DropdownMenuItem( + value: jenis['id'], + child: Text(jenis['nama'] ?? ''), + )) + .toList(), + onChanged: (value) { + selectedJenisBantuanId = value; + }, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Jenis bantuan harus dipilih'; + } + return null; + }, + ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -558,6 +584,7 @@ class StokBantuanView extends GetView { jumlah: double.parse(jumlahController.text), satuan: satuanController.text, deskripsi: deskripsiController.text, + jenisBantuanId: selectedJenisBantuanId, tanggalMasuk: tanggalMasuk, tanggalKadaluarsa: tanggalKadaluarsa, status: 'TERSEDIA', @@ -582,6 +609,7 @@ class StokBantuanView extends GetView { TextEditingController(text: stok.jumlah?.toString()); final satuanController = TextEditingController(text: stok.satuan); final deskripsiController = TextEditingController(text: stok.deskripsi); + String? selectedJenisBantuanId = stok.jenisBantuanId; DateTime? tanggalMasuk = stok.tanggalMasuk; DateTime? tanggalKadaluarsa = stok.tanggalKadaluarsa; @@ -609,6 +637,30 @@ class StokBantuanView extends GetView { }, ), const SizedBox(height: 16), + DropdownButtonFormField( + decoration: const InputDecoration( + labelText: 'Jenis Bantuan', + border: OutlineInputBorder(), + ), + value: selectedJenisBantuanId, + hint: const Text('Pilih Jenis Bantuan'), + items: controller.daftarJenisBantuan + .map((jenis) => DropdownMenuItem( + value: jenis['id'], + child: Text(jenis['nama'] ?? ''), + )) + .toList(), + onChanged: (value) { + selectedJenisBantuanId = value; + }, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Jenis bantuan harus dipilih'; + } + return null; + }, + ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -724,6 +776,7 @@ class StokBantuanView extends GetView { jumlah: double.parse(jumlahController.text), satuan: satuanController.text, deskripsi: deskripsiController.text, + jenisBantuanId: selectedJenisBantuanId, tanggalMasuk: tanggalMasuk, tanggalKadaluarsa: tanggalKadaluarsa, status: stok.status, diff --git a/lib/app/services/supabase_service.dart b/lib/app/services/supabase_service.dart index 37a2932..bcaefb8 100644 --- a/lib/app/services/supabase_service.dart +++ b/lib/app/services/supabase_service.dart @@ -268,7 +268,9 @@ class SupabaseService extends GetxService { // Stok bantuan methods Future>?> getStokBantuan() async { try { - final response = await client.from('stok_bantuan').select('*'); + final response = await client + .from('stok_bantuan') + .select('*, jenis_bantuan:jenis_bantuan_id(id, nama)'); return response; } catch (e) { @@ -309,7 +311,6 @@ class SupabaseService extends GetxService { Future>?> getBentukBantuan() async { try { final response = await client.from('bentuk_bantuan').select('*'); - return response; } catch (e) { print('Error getting bentuk bantuan: $e'); @@ -317,9 +318,19 @@ class SupabaseService extends GetxService { } } - Future addStok(Map stok) async { + Future>?> getJenisBantuan() async { try { - await client.from('stok_bantuan').insert(stok); + final response = await client.from('jenis_bantuan').select('*'); + return response; + } catch (e) { + print('Error getting jenis bantuan: $e'); + return null; + } + } + + Future addStok(Map stokData) async { + try { + await client.from('stok_bantuan').insert(stokData); } catch (e) { print('Error adding stok: $e'); throw e.toString(); diff --git a/lib/main.dart b/lib/main.dart index 32aff6e..a391546 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,6 @@ import 'package:penyaluran_app/app/services/auth_service.dart'; import 'package:penyaluran_app/app/services/supabase_service.dart'; import 'package:penyaluran_app/app/theme/app_theme.dart'; import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart'; -import 'package:intl/intl.dart'; import 'package:intl/date_symbol_data_local.dart'; void main() async {