Perbarui model dan tampilan untuk mendukung perubahan struktur data pengguna. Ganti properti nama dan telepon dengan namaLengkap dan noHp di beberapa model, termasuk DonaturModel, PetugasDesaModel, dan WargaModel. Modifikasi tampilan dan controller untuk menggunakan properti baru ini. Tambahkan fungsionalitas baru untuk menampilkan nama lengkap dan nomor telepon dengan lebih baik di berbagai tampilan. Perbarui rute dan logika aplikasi untuk mencerminkan perubahan ini.

This commit is contained in:
Khafidh Fuadi
2025-03-25 10:43:21 +07:00
parent 54c4660302
commit 8e9553d1fc
39 changed files with 1819 additions and 704 deletions

View File

@ -34,6 +34,7 @@ class LaporanPenyaluranController extends GetxController {
final RxMap<String, dynamic> lokasiPenyaluran = RxMap<String, dynamic>();
final RxMap<String, dynamic> desaData = RxMap<String, dynamic>();
final RxMap<String, dynamic> kategoriBantuan = RxMap<String, dynamic>();
final RxMap<String, dynamic> petugasData = RxMap<String, dynamic>();
// Form controllers
final TextEditingController judulController = TextEditingController();
@ -53,8 +54,8 @@ class LaporanPenyaluranController extends GetxController {
final RxString filterStatus = 'SEMUA'.obs;
// Getter untuk data user
get user => _authController.user;
String get role => user?.role ?? 'WARGA';
dynamic get user => _authController.baseUser;
String get role => _authController.role;
@override
void onInit() {
@ -168,6 +169,8 @@ class LaporanPenyaluranController extends GetxController {
.single();
selectedPenyaluran.value = PenyaluranBantuanModel.fromJson(response);
print(
'PenyaluranDetail - petugasId: ${selectedPenyaluran.value?.petugasId}');
// Ambil data penerima terkait
await fetchPenerimaPenyaluran(penyaluranId);
@ -178,6 +181,11 @@ class LaporanPenyaluranController extends GetxController {
selectedPenyaluran.value!.lokasiPenyaluranId!);
}
// Ambil data petugas jika ada
if (selectedPenyaluran.value?.petugasId != null) {
await fetchPetugasData(selectedPenyaluran.value!.petugasId!);
}
// Hitung penggunaan stok bantuan
await calculateStokBantuanUsage(penyaluranId);
} catch (e) {
@ -251,6 +259,22 @@ class LaporanPenyaluranController extends GetxController {
}
}
// Mendapatkan data petugas
Future<void> fetchPetugasData(String petugasId) async {
try {
final response = await _supabaseService.client
.from('petugas_desa')
.select('*, desa(nama)')
.eq('id', petugasId)
.single();
petugasData.value = response;
print('Data petugas berhasil diambil: $petugasData');
} catch (e) {
print('Error fetching petugas data: $e');
}
}
// Menghitung penggunaan stok bantuan
Future<void> calculateStokBantuanUsage(String penyaluranId) async {
try {
@ -563,7 +587,8 @@ class LaporanPenyaluranController extends GetxController {
// Load logo - tidak perlu menampilkan error jika logo tidak ada
pw.MemoryImage? logoImage;
try {
final logoBytes = await rootBundle.load('assets/img/logo.png');
final logoBytes =
await rootBundle.load('assets/images/penyaluran-icon.png');
logoImage = pw.MemoryImage(logoBytes.buffer.asUint8List());
} catch (e) {
// Logo tidak ditemukan - tidak perlu print error
@ -600,7 +625,7 @@ class LaporanPenyaluranController extends GetxController {
children: [
logoImage != null
? pw.Image(logoImage, width: 60, height: 60)
: pw.SizedBox(width: 60),
: pw.SizedBox(width: 10, height: 10),
pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.end,
children: [
@ -924,10 +949,7 @@ class LaporanPenyaluranController extends GetxController {
isHeader: true,
align: pw.TextAlign.center,
color: PdfColors.blue900),
_buildPdfTableCell('Satuan', ttfBold,
isHeader: true,
align: pw.TextAlign.center,
color: PdfColors.blue900),
_buildPdfTableCell('Status', ttfBold,
isHeader: true,
align: pw.TextAlign.center,
@ -947,13 +969,19 @@ class LaporanPenyaluranController extends GetxController {
? '${penerima.jumlahBantuan} ${penerima.satuan ?? ''}'
: '-';
final isUang =
penerima.satuan?.toLowerCase() == 'rupiah';
final jumlahBantuan = penerima.jumlahBantuan ?? 0;
final formattedJumlah = isUang
? 'Rp ${NumberFormat.currency(locale: 'id', symbol: '', decimalDigits: 0).format(jumlahBantuan)}'
: '$jumlahBantuan ${penerima.satuan ?? ''}';
return pw.TableRow(
children: [
_buildPdfTableCell(nik, ttf),
_buildPdfTableCell(wargaNama, ttf),
_buildPdfTableCell(jumlah, ttf,
align: pw.TextAlign.center),
_buildPdfTableCell(penerima.satuan ?? '-', ttf,
_buildPdfTableCell(formattedJumlah, ttf,
align: pw.TextAlign.center),
_buildPdfTableCell(
penerima.statusPenerimaan ?? '-', ttf,
@ -1005,12 +1033,17 @@ class LaporanPenyaluranController extends GetxController {
'Dokumentasi dapat diakses melalui tautan berikut:',
style: pw.TextStyle(font: ttf)),
pw.SizedBox(height: 3),
pw.Text(laporan.dokumentasiUrl!,
pw.UrlLink(
destination: laporan.dokumentasiUrl!,
child: pw.Text(
laporan.dokumentasiUrl!,
style: pw.TextStyle(
font: ttf,
color: PdfColors.blue,
decoration: pw.TextDecoration.underline,
)),
),
),
),
if (laporan.beritaAcaraUrl != null)
pw.SizedBox(height: 10),
],
@ -1024,12 +1057,17 @@ class LaporanPenyaluranController extends GetxController {
'Berita acara dapat diakses melalui tautan berikut:',
style: pw.TextStyle(font: ttf)),
pw.SizedBox(height: 3),
pw.Text(laporan.beritaAcaraUrl!,
pw.UrlLink(
destination: laporan.beritaAcaraUrl!,
child: pw.Text(
laporan.beritaAcaraUrl!,
style: pw.TextStyle(
font: ttf,
color: PdfColors.blue,
decoration: pw.TextDecoration.underline,
)),
),
),
),
],
],
ttfBold,
@ -1046,7 +1084,9 @@ class LaporanPenyaluranController extends GetxController {
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
'Penanggung Jawab,',
petugasData.isNotEmpty
? 'Petugas ${petugasData['desa'] != null ? "Desa " + (petugasData['desa']['nama'] ?? '') : ''}'
: 'Penanggung Jawab,',
style: pw.TextStyle(font: ttf),
),
pw.SizedBox(height: 50), // Ruang untuk tanda tangan
@ -1057,12 +1097,23 @@ class LaporanPenyaluranController extends GetxController {
top: pw.BorderSide(color: PdfColors.black))),
padding: const pw.EdgeInsets.only(top: 5),
child: pw.Text(
// Sesuaikan dengan properti yang ada di model user
user?.email ?? 'Admin Sistem',
// Gunakan data petugas dari penyaluran, jika tidak ada gunakan data user
petugasData.isNotEmpty
? petugasData['nama_lengkap'] ?? 'Petugas Desa'
: user?.nama ?? 'Admin Sistem',
style: pw.TextStyle(font: ttfBold),
textAlign: pw.TextAlign.center,
),
),
// NIP atau nomor identitas petugas
pw.Text(
petugasData.isNotEmpty
? petugasData['nip'] ?? '-'
: user?.nip ?? '-',
style: pw.TextStyle(font: ttf),
textAlign: pw.TextAlign.center,
),
],
),
],

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:penyaluran_app/app/modules/laporan_penyaluran/controllers/laporan_penyaluran_controller.dart';
import 'package:penyaluran_app/app/theme/app_theme.dart';
import 'package:penyaluran_app/app/utils/date_time_helper.dart';
import 'package:penyaluran_app/app/widgets/custom_app_bar.dart';
import 'package:penyaluran_app/app/widgets/section_header.dart';
import 'package:penyaluran_app/app/widgets/status_badge.dart';
@ -185,15 +186,15 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
_buildInfoRow(
'Tanggal Penyaluran',
penyaluran.tanggalPenyaluran != null
? DateFormat('dd/MM/yyyy')
.format(penyaluran.tanggalPenyaluran!)
? DateTimeHelper.formatDateTime(
penyaluran.tanggalPenyaluran!)
: '-',
),
_buildInfoRow(
'Tanggal Selesai',
penyaluran.tanggalSelesai != null
? DateFormat('dd/MM/yyyy')
.format(penyaluran.tanggalSelesai!)
? DateTimeHelper.formatDateTime(
penyaluran.tanggalSelesai!)
: '-',
),
_buildInfoRow('Jumlah Penerima',
@ -525,7 +526,7 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
Expanded(
flex: 3,
child: Text(
'Nama Penerima',
'NIK',
style: TextStyle(
fontWeight: FontWeight.bold),
),
@ -533,7 +534,7 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
Expanded(
flex: 3,
child: Text(
'Jenis Bantuan',
'Nama Penerima',
style: TextStyle(
fontWeight: FontWeight.bold),
),
@ -568,12 +569,13 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
itemBuilder: (context, index) {
final penerima =
controller.daftarPenerima[index];
final wargaNik = penerima.warga != null
? penerima.warga!['nik'] ?? '-'
: '-';
final wargaNama = penerima.warga != null
? penerima.warga!['nama_lengkap'] ?? '-'
: '-';
final stokNama = penerima.stokBantuan != null
? penerima.stokBantuan!['nama'] ?? '-'
: '-';
final jumlah = penerima.jumlahBantuan != null
? '${penerima.jumlahBantuan} ${penerima.satuan ?? ''}'
: '-';
@ -591,11 +593,11 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
children: [
Expanded(
flex: 3,
child: Text(wargaNama),
child: Text(wargaNik),
),
Expanded(
flex: 3,
child: Text(stokNama),
child: Text(wargaNama),
),
Expanded(
flex: 2,
@ -867,9 +869,7 @@ class LaporanPenyaluranDetailView extends GetView<LaporanPenyaluranController> {
),
const SizedBox(height: 6),
Text(
tanggalLaporan != null
? DateFormat('dd/MM/yyyy').format(tanggalLaporan)
: '-',
DateTimeHelper.formatDateTime(tanggalLaporan),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,