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
This commit is contained in:
@ -5,6 +5,8 @@ class StokBantuanModel {
|
|||||||
final String? nama;
|
final String? nama;
|
||||||
final String? bentukBantuanId;
|
final String? bentukBantuanId;
|
||||||
final String? sumberBantuanId;
|
final String? sumberBantuanId;
|
||||||
|
final String? jenisBantuanId;
|
||||||
|
final Map<String, dynamic>? jenisBantuan;
|
||||||
final double? jumlah;
|
final double? jumlah;
|
||||||
final String? satuan;
|
final String? satuan;
|
||||||
final String? deskripsi;
|
final String? deskripsi;
|
||||||
@ -19,6 +21,8 @@ class StokBantuanModel {
|
|||||||
this.nama,
|
this.nama,
|
||||||
this.bentukBantuanId,
|
this.bentukBantuanId,
|
||||||
this.sumberBantuanId,
|
this.sumberBantuanId,
|
||||||
|
this.jenisBantuanId,
|
||||||
|
this.jenisBantuan,
|
||||||
this.jumlah,
|
this.jumlah,
|
||||||
this.satuan,
|
this.satuan,
|
||||||
this.deskripsi,
|
this.deskripsi,
|
||||||
@ -40,6 +44,8 @@ class StokBantuanModel {
|
|||||||
nama: json["nama"],
|
nama: json["nama"],
|
||||||
bentukBantuanId: json["bentuk_bantuan_id"],
|
bentukBantuanId: json["bentuk_bantuan_id"],
|
||||||
sumberBantuanId: json["sumber_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,
|
jumlah: json["jumlah"] != null ? json["jumlah"].toDouble() : 0.0,
|
||||||
satuan: json["satuan"],
|
satuan: json["satuan"],
|
||||||
deskripsi: json["deskripsi"],
|
deskripsi: json["deskripsi"],
|
||||||
@ -63,6 +69,7 @@ class StokBantuanModel {
|
|||||||
"nama": nama,
|
"nama": nama,
|
||||||
"bentuk_bantuan_id": bentukBantuanId,
|
"bentuk_bantuan_id": bentukBantuanId,
|
||||||
"sumber_bantuan_id": sumberBantuanId,
|
"sumber_bantuan_id": sumberBantuanId,
|
||||||
|
"jenis_bantuan_id": jenisBantuanId,
|
||||||
"jumlah": jumlah,
|
"jumlah": jumlah,
|
||||||
"satuan": satuan,
|
"satuan": satuan,
|
||||||
"deskripsi": deskripsi,
|
"deskripsi": deskripsi,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:penyaluran_app/app/utils/date_formatter.dart';
|
|
||||||
|
|
||||||
class PenerimaController extends GetxController {
|
class PenerimaController extends GetxController {
|
||||||
final RxList<Map<String, dynamic>> daftarPenerima =
|
final RxList<Map<String, dynamic>> daftarPenerima =
|
||||||
|
@ -17,6 +17,10 @@ class StokBantuanController extends GetxController {
|
|||||||
final RxDouble stokMasuk = 0.0.obs;
|
final RxDouble stokMasuk = 0.0.obs;
|
||||||
final RxDouble stokKeluar = 0.0.obs;
|
final RxDouble stokKeluar = 0.0.obs;
|
||||||
|
|
||||||
|
// Data untuk jenis bantuan
|
||||||
|
final RxList<Map<String, dynamic>> daftarJenisBantuan =
|
||||||
|
<Map<String, dynamic>>[].obs;
|
||||||
|
|
||||||
// Controller untuk pencarian
|
// Controller untuk pencarian
|
||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
final RxString searchQuery = ''.obs;
|
final RxString searchQuery = ''.obs;
|
||||||
@ -27,6 +31,7 @@ class StokBantuanController extends GetxController {
|
|||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
loadStokBantuanData();
|
loadStokBantuanData();
|
||||||
|
loadJenisBantuanData();
|
||||||
|
|
||||||
// Listener untuk pencarian
|
// Listener untuk pencarian
|
||||||
searchController.addListener(() {
|
searchController.addListener(() {
|
||||||
@ -69,6 +74,17 @@ class StokBantuanController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> loadJenisBantuanData() async {
|
||||||
|
try {
|
||||||
|
final jenisBantuanData = await _supabaseService.getJenisBantuan();
|
||||||
|
if (jenisBantuanData != null) {
|
||||||
|
daftarJenisBantuan.value = jenisBantuanData;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error loading jenis bantuan data: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> addStok(StokBantuanModel stok) async {
|
Future<void> addStok(StokBantuanModel stok) async {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
@ -151,6 +167,7 @@ class StokBantuanController extends GetxController {
|
|||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
await loadStokBantuanData();
|
await loadStokBantuanData();
|
||||||
|
await loadJenisBantuanData();
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -124,34 +124,7 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else if (activeTab == 4) {
|
} else if (activeTab == 4) {
|
||||||
return Row(
|
return notificationButton;
|
||||||
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,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return notificationButton;
|
return notificationButton;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.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/data/models/stok_bantuan_model.dart';
|
||||||
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart';
|
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/stok_bantuan_controller.dart';
|
||||||
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
||||||
@ -277,7 +276,9 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item.status ?? 'TERSEDIA',
|
item.jenisBantuan != null
|
||||||
|
? (item.jenisBantuan!['nama'] ?? 'Tidak Ada Jenis')
|
||||||
|
: 'Tidak Ada Jenis',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: AppTheme.primaryColor,
|
color: AppTheme.primaryColor,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@ -417,6 +418,7 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
final jumlahController = TextEditingController();
|
final jumlahController = TextEditingController();
|
||||||
final satuanController = TextEditingController();
|
final satuanController = TextEditingController();
|
||||||
final deskripsiController = TextEditingController();
|
final deskripsiController = TextEditingController();
|
||||||
|
String? selectedJenisBantuanId;
|
||||||
DateTime? tanggalMasuk = DateTime.now();
|
DateTime? tanggalMasuk = DateTime.now();
|
||||||
DateTime? tanggalKadaluarsa;
|
DateTime? tanggalKadaluarsa;
|
||||||
|
|
||||||
@ -444,6 +446,30 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
DropdownButtonFormField<String>(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Jenis Bantuan',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
value: selectedJenisBantuanId,
|
||||||
|
hint: const Text('Pilih Jenis Bantuan'),
|
||||||
|
items: controller.daftarJenisBantuan
|
||||||
|
.map((jenis) => DropdownMenuItem<String>(
|
||||||
|
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(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -558,6 +584,7 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
jumlah: double.parse(jumlahController.text),
|
jumlah: double.parse(jumlahController.text),
|
||||||
satuan: satuanController.text,
|
satuan: satuanController.text,
|
||||||
deskripsi: deskripsiController.text,
|
deskripsi: deskripsiController.text,
|
||||||
|
jenisBantuanId: selectedJenisBantuanId,
|
||||||
tanggalMasuk: tanggalMasuk,
|
tanggalMasuk: tanggalMasuk,
|
||||||
tanggalKadaluarsa: tanggalKadaluarsa,
|
tanggalKadaluarsa: tanggalKadaluarsa,
|
||||||
status: 'TERSEDIA',
|
status: 'TERSEDIA',
|
||||||
@ -582,6 +609,7 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
TextEditingController(text: stok.jumlah?.toString());
|
TextEditingController(text: stok.jumlah?.toString());
|
||||||
final satuanController = TextEditingController(text: stok.satuan);
|
final satuanController = TextEditingController(text: stok.satuan);
|
||||||
final deskripsiController = TextEditingController(text: stok.deskripsi);
|
final deskripsiController = TextEditingController(text: stok.deskripsi);
|
||||||
|
String? selectedJenisBantuanId = stok.jenisBantuanId;
|
||||||
DateTime? tanggalMasuk = stok.tanggalMasuk;
|
DateTime? tanggalMasuk = stok.tanggalMasuk;
|
||||||
DateTime? tanggalKadaluarsa = stok.tanggalKadaluarsa;
|
DateTime? tanggalKadaluarsa = stok.tanggalKadaluarsa;
|
||||||
|
|
||||||
@ -609,6 +637,30 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
DropdownButtonFormField<String>(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Jenis Bantuan',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
value: selectedJenisBantuanId,
|
||||||
|
hint: const Text('Pilih Jenis Bantuan'),
|
||||||
|
items: controller.daftarJenisBantuan
|
||||||
|
.map((jenis) => DropdownMenuItem<String>(
|
||||||
|
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(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -724,6 +776,7 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
|||||||
jumlah: double.parse(jumlahController.text),
|
jumlah: double.parse(jumlahController.text),
|
||||||
satuan: satuanController.text,
|
satuan: satuanController.text,
|
||||||
deskripsi: deskripsiController.text,
|
deskripsi: deskripsiController.text,
|
||||||
|
jenisBantuanId: selectedJenisBantuanId,
|
||||||
tanggalMasuk: tanggalMasuk,
|
tanggalMasuk: tanggalMasuk,
|
||||||
tanggalKadaluarsa: tanggalKadaluarsa,
|
tanggalKadaluarsa: tanggalKadaluarsa,
|
||||||
status: stok.status,
|
status: stok.status,
|
||||||
|
@ -268,7 +268,9 @@ class SupabaseService extends GetxService {
|
|||||||
// Stok bantuan methods
|
// Stok bantuan methods
|
||||||
Future<List<Map<String, dynamic>>?> getStokBantuan() async {
|
Future<List<Map<String, dynamic>>?> getStokBantuan() async {
|
||||||
try {
|
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;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -309,7 +311,6 @@ class SupabaseService extends GetxService {
|
|||||||
Future<List<Map<String, dynamic>>?> getBentukBantuan() async {
|
Future<List<Map<String, dynamic>>?> getBentukBantuan() async {
|
||||||
try {
|
try {
|
||||||
final response = await client.from('bentuk_bantuan').select('*');
|
final response = await client.from('bentuk_bantuan').select('*');
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error getting bentuk bantuan: $e');
|
print('Error getting bentuk bantuan: $e');
|
||||||
@ -317,9 +318,19 @@ class SupabaseService extends GetxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addStok(Map<String, dynamic> stok) async {
|
Future<List<Map<String, dynamic>>?> getJenisBantuan() async {
|
||||||
try {
|
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<void> addStok(Map<String, dynamic> stokData) async {
|
||||||
|
try {
|
||||||
|
await client.from('stok_bantuan').insert(stokData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error adding stok: $e');
|
print('Error adding stok: $e');
|
||||||
throw e.toString();
|
throw e.toString();
|
||||||
|
@ -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/services/supabase_service.dart';
|
||||||
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
import 'package:penyaluran_app/app/theme/app_theme.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:intl/intl.dart';
|
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
|
Reference in New Issue
Block a user