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:
@ -1,17 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:penyaluran_app/app/data/models/donatur_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/petugas_desa_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/user_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/warga_model.dart';
|
||||
import 'package:penyaluran_app/app/data/providers/auth_provider.dart';
|
||||
import 'package:penyaluran_app/app/routes/app_pages.dart';
|
||||
import 'package:penyaluran_app/app/modules/warga/controllers/warga_dashboard_controller.dart';
|
||||
|
||||
class AuthController extends GetxController {
|
||||
static AuthController get to => Get.find();
|
||||
|
||||
final AuthProvider _authProvider = AuthProvider();
|
||||
|
||||
final Rx<UserModel?> _user = Rx<UserModel?>(null);
|
||||
UserModel? get user => _user.value;
|
||||
final Rx<UserData?> _userData = Rx<UserData?>(null);
|
||||
UserData? get userData => _userData.value;
|
||||
|
||||
// Getter untuk BaseUserModel
|
||||
BaseUserModel? get baseUser => _userData.value?.baseUser;
|
||||
|
||||
// Getter untuk role
|
||||
String get role => _userData.value?.baseUser.roleName.toLowerCase() ?? '';
|
||||
|
||||
// Getter dinamis untuk data role-specific
|
||||
dynamic get roleData => _userData.value?.roleData;
|
||||
|
||||
// Getter untuk memeriksa tipe roleData
|
||||
bool get isWarga =>
|
||||
_userData.value?.roleData is WargaModel && role == 'warga';
|
||||
bool get isDonatur =>
|
||||
_userData.value?.roleData is DonaturModel && role == 'donatur';
|
||||
bool get isPetugasDesa =>
|
||||
_userData.value?.roleData is PetugasDesaModel && role == 'petugas_desa';
|
||||
|
||||
// Helper method untuk mendapatkan nama display
|
||||
String get displayName {
|
||||
if (roleData == null) return baseUser?.email ?? 'Pengguna';
|
||||
|
||||
if (isWarga) {
|
||||
return (roleData as WargaModel).displayName;
|
||||
} else if (isDonatur) {
|
||||
return (roleData as DonaturModel).displayName;
|
||||
} else if (isPetugasDesa) {
|
||||
return (roleData as PetugasDesaModel).displayName;
|
||||
}
|
||||
|
||||
return baseUser?.email ?? 'Pengguna';
|
||||
}
|
||||
|
||||
final RxBool isLoading = false.obs;
|
||||
final RxBool isWargaProfileComplete = false.obs;
|
||||
@ -74,21 +108,21 @@ class AuthController extends GetxController {
|
||||
print('Memeriksa status autentikasi...');
|
||||
|
||||
// Jika user sudah ada di memori dan profil sudah diambil, gunakan data yang ada
|
||||
if (_user.value != null && _hasLoadedProfile.value) {
|
||||
if (_userData.value != null && _hasLoadedProfile.value) {
|
||||
print('Menggunakan data user yang sudah ada di memori');
|
||||
_handleAuthenticatedUser(_user.value!);
|
||||
_handleAuthenticatedUser(_userData.value!);
|
||||
return;
|
||||
}
|
||||
|
||||
// Jika belum ada data user, ambil dari provider
|
||||
final currentUser = await _authProvider.getCurrentUser();
|
||||
final currentUserData = await _authProvider.getCurrentUser();
|
||||
|
||||
if (currentUser != null) {
|
||||
if (currentUserData != null) {
|
||||
print(
|
||||
'User terautentikasi: ${currentUser.email}, role: ${currentUser.role}');
|
||||
_user.value = currentUser;
|
||||
'User terautentikasi: ${currentUserData.baseUser.email}, role: ${currentUserData.baseUser.roleName}');
|
||||
_userData.value = currentUserData;
|
||||
_hasLoadedProfile.value = true;
|
||||
_handleAuthenticatedUser(currentUser);
|
||||
_handleAuthenticatedUser(currentUserData);
|
||||
} else {
|
||||
print('Tidak ada user yang terautentikasi');
|
||||
_handleUnauthenticatedUser();
|
||||
@ -104,13 +138,13 @@ class AuthController extends GetxController {
|
||||
}
|
||||
|
||||
// Metode untuk menangani user yang terautentikasi
|
||||
void _handleAuthenticatedUser(UserModel user) {
|
||||
void _handleAuthenticatedUser(UserData userData) {
|
||||
// Hindari navigasi jika sudah berada di halaman yang sesuai
|
||||
final currentRoute = Get.currentRoute;
|
||||
print('Rute saat ini: $currentRoute');
|
||||
|
||||
// Pastikan role tidak null, gunakan default jika null
|
||||
final role = user.role.isNotEmpty ? user.role : 'WARGA';
|
||||
// Dapatkan role dari BaseUserModel
|
||||
final role = userData.baseUser.roleName.toLowerCase();
|
||||
print('Role yang digunakan: $role');
|
||||
|
||||
// Untuk semua role, arahkan ke dashboard masing-masing
|
||||
@ -146,9 +180,8 @@ class AuthController extends GetxController {
|
||||
// Memeriksa status profil warga
|
||||
Future<void> checkWargaProfileStatus() async {
|
||||
try {
|
||||
if (_user.value?.role == 'WARGA') {
|
||||
final wargaData = await _authProvider.getWargaData();
|
||||
isWargaProfileComplete.value = wargaData != null;
|
||||
if (role == 'warga') {
|
||||
isWargaProfileComplete.value = roleData != null;
|
||||
} else {
|
||||
isWargaProfileComplete.value = true;
|
||||
}
|
||||
@ -177,17 +210,14 @@ class AuthController extends GetxController {
|
||||
// Bersihkan dependensi form sebelum navigasi
|
||||
clearFormDependencies();
|
||||
|
||||
switch (role) {
|
||||
case 'WARGA':
|
||||
switch (role.toLowerCase()) {
|
||||
case 'warga':
|
||||
Get.offAllNamed(Routes.wargaDashboard);
|
||||
break;
|
||||
case 'PETUGASVERIFIKASI':
|
||||
Get.offAllNamed(Routes.petugasVerifikasiDashboard);
|
||||
break;
|
||||
case 'PETUGASDESA':
|
||||
case 'petugas_desa':
|
||||
Get.offAllNamed(Routes.petugasDesaDashboard);
|
||||
break;
|
||||
case 'DONATUR':
|
||||
case 'donatur':
|
||||
Get.offAllNamed(Routes.donaturDashboard);
|
||||
break;
|
||||
default:
|
||||
@ -229,88 +259,81 @@ class AuthController extends GetxController {
|
||||
isLoading.value = true;
|
||||
|
||||
print('DEBUG: Memanggil _authProvider.signIn');
|
||||
final user = await _authProvider.signIn(
|
||||
final userData = await _authProvider.signIn(
|
||||
email,
|
||||
password,
|
||||
);
|
||||
|
||||
print('DEBUG: Hasil signIn: ${user != null ? 'Berhasil' : 'Gagal'}');
|
||||
if (user != null) {
|
||||
print('DEBUG: User ditemukan, role: ${user.role}');
|
||||
_user.value = user;
|
||||
print('DEBUG: Hasil signIn: ${userData != null ? 'Berhasil' : 'Gagal'}');
|
||||
if (userData != null) {
|
||||
print('DEBUG: User ditemukan, role: ${userData.baseUser.roleName}');
|
||||
_userData.value = userData;
|
||||
_hasLoadedProfile.value = true; // Tandai bahwa profil sudah diambil
|
||||
clearControllers();
|
||||
|
||||
// Arahkan ke dashboard sesuai peran
|
||||
print('DEBUG: Navigasi berdasarkan peran: ${user.role}');
|
||||
navigateBasedOnRole(user.role);
|
||||
print(
|
||||
'DEBUG: Navigasi berdasarkan peran: ${userData.baseUser.roleName}');
|
||||
navigateBasedOnRole(userData.baseUser.roleName.toLowerCase());
|
||||
} else {
|
||||
print('DEBUG: User null setelah login berhasil');
|
||||
handleLoginError(Exception('Data pengguna tidak ditemukan'));
|
||||
}
|
||||
} catch (e) {
|
||||
print('DEBUG: Error detail pada login: $e');
|
||||
print('DEBUG: Stack trace: ${StackTrace.current}');
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Login gagal: ${e.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
handleLoginError(e);
|
||||
} finally {
|
||||
print('DEBUG: Mengatur isLoading ke false');
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Metode untuk logout
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
// Ambil semua controller yang mungkin perlu dibersihkan
|
||||
try {
|
||||
final wargaController = Get.find<WargaDashboardController>();
|
||||
wargaController.penerimaPenyaluran.clear();
|
||||
wargaController.pengajuanKelayakan.clear();
|
||||
wargaController.pengaduan.clear();
|
||||
} catch (e) {
|
||||
// Jika controller tidak ditemukan, abaikan
|
||||
print('Controller tidak ditemukan: $e');
|
||||
}
|
||||
// Menangani error saat login
|
||||
void handleLoginError(dynamic error) {
|
||||
print('DEBUG: Error login: $error');
|
||||
|
||||
// Logout dari Supabase
|
||||
await _authProvider.signOut();
|
||||
String errorMessage = 'Terjadi kesalahan saat login. Silakan coba lagi.';
|
||||
|
||||
// Reset semua state
|
||||
_user.value = null;
|
||||
_hasLoadedProfile.value = false;
|
||||
isWargaProfileComplete.value = false;
|
||||
|
||||
// Bersihkan dependensi form sebelum navigasi
|
||||
clearFormDependencies();
|
||||
|
||||
// Navigasi ke halaman login
|
||||
Get.offAllNamed(Routes.login);
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Logout gagal: ${e.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
if (error.toString().contains('Invalid login credentials')) {
|
||||
errorMessage = 'Email atau password salah. Silakan coba lagi.';
|
||||
} else if (error.toString().contains('Too many requests')) {
|
||||
errorMessage = 'Terlalu banyak percobaan login. Silakan coba lagi nanti.';
|
||||
}
|
||||
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
errorMessage,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
}
|
||||
|
||||
// Metode untuk membersihkan controller
|
||||
void clearControllers() {
|
||||
emailController.clear();
|
||||
passwordController.clear();
|
||||
confirmPasswordController.clear();
|
||||
}
|
||||
|
||||
// Metode untuk logout
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
if (emailController.text.isNotEmpty) emailController.clear();
|
||||
if (passwordController.text.isNotEmpty) passwordController.clear();
|
||||
if (confirmPasswordController.text.isNotEmpty) {
|
||||
confirmPasswordController.clear();
|
||||
}
|
||||
isLoading.value = true;
|
||||
await _authProvider.signOut();
|
||||
_userData.value = null;
|
||||
_hasLoadedProfile.value = false;
|
||||
Get.offAllNamed(Routes.login);
|
||||
} catch (e) {
|
||||
print('Error clearing controllers: $e');
|
||||
print('Error saat logout: $e');
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Terjadi kesalahan saat logout. Silakan coba lagi.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,16 +378,42 @@ class AuthController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
// Metode untuk refresh data user setelah update profil
|
||||
Future<void> refreshUserData() async {
|
||||
try {
|
||||
print('Memperbarui data pengguna...');
|
||||
isLoading.value = true;
|
||||
|
||||
// Hapus cache profil yang sudah tidak valid
|
||||
_hasLoadedProfile.value = false;
|
||||
|
||||
// Ambil data user terbaru dari provider dengan menskip cache
|
||||
final currentUserData =
|
||||
await _authProvider.getCurrentUser(skipCache: true);
|
||||
|
||||
if (currentUserData != null) {
|
||||
print(
|
||||
'Data pengguna berhasil diperbarui: ${currentUserData.baseUser.name}');
|
||||
_userData.value = currentUserData;
|
||||
_hasLoadedProfile.value = true;
|
||||
} else {
|
||||
print('Gagal memperbarui data pengguna');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error refreshing user data: $e');
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mendapatkan rute target berdasarkan role
|
||||
String _getTargetRouteForRole(String role) {
|
||||
switch (role) {
|
||||
case 'WARGA':
|
||||
switch (role.toLowerCase()) {
|
||||
case 'warga':
|
||||
return Routes.wargaDashboard;
|
||||
case 'PETUGASVERIFIKASI':
|
||||
return Routes.petugasVerifikasiDashboard;
|
||||
case 'PETUGASDESA':
|
||||
case 'petugas_desa':
|
||||
return Routes.petugasDesaDashboard;
|
||||
case 'DONATUR':
|
||||
case 'donatur':
|
||||
return Routes.donaturDashboard;
|
||||
default:
|
||||
return Routes.home;
|
||||
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
@ -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,
|
||||
|
@ -54,12 +54,12 @@ class DetailPenyaluranController extends GetxController {
|
||||
final user = _supabaseService.client.auth.currentUser;
|
||||
if (user != null) {
|
||||
final userData = await _supabaseService.client
|
||||
.from('users')
|
||||
.from('user_profile')
|
||||
.select('role')
|
||||
.eq('id', user.id)
|
||||
.single();
|
||||
|
||||
if (userData['role'] == 'petugas_desa') {
|
||||
if (userData['role'] == 'PETUGASDESA') {
|
||||
isPetugasDesa.value = true;
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ class DonaturController extends GetxController {
|
||||
|
||||
try {
|
||||
final donatur = daftarDonatur.firstWhere((d) => d.id == donaturId);
|
||||
return donatur.nama;
|
||||
return donatur.namaLengkap;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class JadwalPenyaluranController extends GetxController {
|
||||
// Controller untuk pencarian
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
|
@ -32,7 +32,7 @@ class PenerimaBantuanController extends GetxController {
|
||||
// Form key
|
||||
final GlobalKey<FormState> penerimaFormKey = GlobalKey<FormState>();
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -79,19 +79,21 @@ class PenerimaBantuanController extends GetxController {
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
final penerima = WargaModel(
|
||||
nama: namaController.text,
|
||||
nik: nikController.text,
|
||||
alamat: alamatController.text,
|
||||
telepon: teleponController.text,
|
||||
email: emailController.text,
|
||||
catatan: catatanController.text,
|
||||
status: 'AKTIF',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
// Biarkan Supabase yang akan menghasilkan ID saat insert
|
||||
// Kita hanya perlu menyediakan data lainnya
|
||||
final penerima = {
|
||||
'nama_lengkap': namaController.text,
|
||||
'nik': nikController.text,
|
||||
'alamat': alamatController.text,
|
||||
'no_hp': teleponController.text,
|
||||
'email': emailController.text,
|
||||
'catatan': catatanController.text,
|
||||
'status': 'AKTIF',
|
||||
'created_at': DateTime.now().toIso8601String(),
|
||||
'updated_at': DateTime.now().toIso8601String(),
|
||||
};
|
||||
|
||||
await _supabaseService.tambahPenerima(penerima.toJson());
|
||||
await _supabaseService.tambahPenerima(penerima);
|
||||
|
||||
// Clear form
|
||||
clearForm();
|
||||
@ -125,18 +127,17 @@ class PenerimaBantuanController extends GetxController {
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
final penerima = WargaModel(
|
||||
id: penerimaId,
|
||||
nama: namaController.text,
|
||||
nik: nikController.text,
|
||||
alamat: alamatController.text,
|
||||
telepon: teleponController.text,
|
||||
email: emailController.text,
|
||||
catatan: catatanController.text,
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
final penerima = {
|
||||
'nama_lengkap': namaController.text,
|
||||
'nik': nikController.text,
|
||||
'alamat': alamatController.text,
|
||||
'no_hp': teleponController.text,
|
||||
'email': emailController.text,
|
||||
'catatan': catatanController.text,
|
||||
'updated_at': DateTime.now().toIso8601String(),
|
||||
};
|
||||
|
||||
await _supabaseService.updatePenerima(penerimaId, penerima.toJson());
|
||||
await _supabaseService.updatePenerima(penerimaId, penerima);
|
||||
|
||||
// Clear form
|
||||
clearForm();
|
||||
@ -218,10 +219,10 @@ class PenerimaBantuanController extends GetxController {
|
||||
}
|
||||
|
||||
void setFormData(WargaModel penerima) {
|
||||
namaController.text = penerima.nama ?? '';
|
||||
namaController.text = penerima.namaLengkap ?? '';
|
||||
nikController.text = penerima.nik ?? '';
|
||||
alamatController.text = penerima.alamat ?? '';
|
||||
teleponController.text = penerima.telepon ?? '';
|
||||
teleponController.text = penerima.noHp ?? '';
|
||||
emailController.text = penerima.email ?? '';
|
||||
catatanController.text = penerima.catatan ?? '';
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class PengaduanController extends GetxController {
|
||||
// Image picker
|
||||
final ImagePicker _imagePicker = ImagePicker();
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
|
@ -53,7 +53,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
// Tambahkan properti untuk waktu terakhir update
|
||||
final Rx<DateTime> lastUpdateTime = DateTime.now().obs;
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
// Getter untuk counter dari CounterService
|
||||
RxInt get jumlahMenunggu => _counterService.jumlahMenunggu;
|
||||
@ -72,10 +72,9 @@ class PenitipanBantuanController extends GetxController {
|
||||
|
||||
loadPenitipanData();
|
||||
loadKategoriBantuanData();
|
||||
// Tambahkan delay untuk memastikan data petugas desa dimuat setelah penitipan
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
loadAllPetugasDesaData();
|
||||
});
|
||||
|
||||
// Hapus delay dan muat data petugas desa langsung
|
||||
loadAllPetugasDesaData();
|
||||
|
||||
// Listener untuk pencarian donatur
|
||||
donaturSearchController.addListener(() {
|
||||
@ -123,25 +122,24 @@ class PenitipanBantuanController extends GetxController {
|
||||
// Muat informasi petugas desa untuk item yang terverifikasi
|
||||
print(
|
||||
'Memuat informasi petugas desa untuk ${daftarPenitipan.length} penitipan');
|
||||
|
||||
List<Future> petugasLoaders = [];
|
||||
|
||||
for (var item in daftarPenitipan) {
|
||||
if (item.status == 'TERVERIFIKASI' && item.petugasDesaId != null) {
|
||||
print(
|
||||
'Memuat informasi petugas desa untuk penitipan ID: ${item.id}, petugasDesaId: ${item.petugasDesaId}');
|
||||
final petugasData = await getPetugasDesaInfo(item.petugasDesaId);
|
||||
if (petugasData != null) {
|
||||
print(
|
||||
'Berhasil memuat data petugas desa: ${petugasData['name']} untuk ID: ${item.petugasDesaId}');
|
||||
} else {
|
||||
print(
|
||||
'Gagal memuat data petugas desa untuk ID: ${item.petugasDesaId}');
|
||||
}
|
||||
petugasLoaders.add(getPetugasDesaInfo(item.petugasDesaId));
|
||||
}
|
||||
}
|
||||
|
||||
// Tunggu semua data petugas desa selesai dimuat
|
||||
await Future.wait(petugasLoaders);
|
||||
|
||||
// Debug: print semua data petugas desa yang sudah dimuat
|
||||
print('Data petugas desa yang sudah dimuat:');
|
||||
petugasDesaCache.forEach((key, value) {
|
||||
print('ID: $key, Nama: $value');
|
||||
print('ID: $key, Nama: ${value['nama_lengkap']}');
|
||||
});
|
||||
|
||||
// Update waktu terakhir refresh
|
||||
@ -490,7 +488,8 @@ class PenitipanBantuanController extends GetxController {
|
||||
final donaturId = item.donaturId;
|
||||
String donaturNama = '';
|
||||
if (donaturId != null && donaturCache.containsKey(donaturId)) {
|
||||
donaturNama = donaturCache[donaturId]?.nama?.toLowerCase() ?? '';
|
||||
donaturNama =
|
||||
donaturCache[donaturId]?.namaLengkap?.toLowerCase() ?? '';
|
||||
}
|
||||
final donaturMatch = donaturNama.contains(searchText);
|
||||
|
||||
@ -551,25 +550,37 @@ class PenitipanBantuanController extends GetxController {
|
||||
if (!petugasDesaCache.containsKey(petugasDesaId)) {
|
||||
print(
|
||||
'Data petugas desa tidak ditemukan di cache untuk ID: $petugasDesaId');
|
||||
// Jadwalkan pengambilan data untuk nanti
|
||||
// Muat data petugas dan perbarui UI
|
||||
loadPetugasDesaData(petugasDesaId);
|
||||
return 'Memuat...';
|
||||
|
||||
// Coba cek lagi setelah pemuatan
|
||||
if (petugasDesaCache.containsKey(petugasDesaId)) {
|
||||
// Akses nama dari struktur data petugas_desa
|
||||
final nama = petugasDesaCache[petugasDesaId]?['nama_lengkap'];
|
||||
return nama ?? 'Tidak diketahui';
|
||||
}
|
||||
|
||||
return 'Memuat data...';
|
||||
}
|
||||
|
||||
// Sekarang data seharusnya ada di cache
|
||||
final nama = petugasDesaCache[petugasDesaId]?['name'];
|
||||
// Akses nama dari struktur data petugas_desa
|
||||
final nama = petugasDesaCache[petugasDesaId]?['nama_lengkap'];
|
||||
print('Nama petugas desa: $nama untuk ID: $petugasDesaId');
|
||||
return nama ?? 'Tidak diketahui';
|
||||
}
|
||||
|
||||
// Fungsi untuk memuat data petugas desa dan memperbarui UI
|
||||
void loadPetugasDesaData(String petugasDesaId) async {
|
||||
Future<void> loadPetugasDesaData(String petugasDesaId) async {
|
||||
try {
|
||||
print('Memuat data petugas desa untuk ID: $petugasDesaId');
|
||||
final petugasData = await getPetugasDesaInfo(petugasDesaId);
|
||||
if (petugasData != null) {
|
||||
// Data sudah dimasukkan ke cache oleh getPetugasDesaInfo
|
||||
// Refresh UI
|
||||
update();
|
||||
print('Berhasil memuat data petugas: ${petugasData['nama_lengkap']}');
|
||||
|
||||
// Refresh UI segera
|
||||
update(['petugas_data']);
|
||||
} else {
|
||||
print(
|
||||
'Gagal mengambil data petugas desa dari server untuk ID: $petugasDesaId');
|
||||
@ -597,7 +608,7 @@ class PenitipanBantuanController extends GetxController {
|
||||
// Debug: print semua data petugas desa yang sudah dimuat
|
||||
print('Data petugas desa yang sudah dimuat setelah reload:');
|
||||
petugasDesaCache.forEach((key, value) {
|
||||
print('ID: $key, Nama: $value');
|
||||
print('ID: $key, Nama: ${value['nama_lengkap']}');
|
||||
});
|
||||
} catch (e) {
|
||||
print('Error saat memuat ulang data petugas desa: $e');
|
||||
@ -643,15 +654,15 @@ class PenitipanBantuanController extends GetxController {
|
||||
|
||||
Future<String?> tambahDonatur({
|
||||
required String nama,
|
||||
required String telepon,
|
||||
required String noHp,
|
||||
String? alamat,
|
||||
String? email,
|
||||
String? jenis,
|
||||
}) async {
|
||||
try {
|
||||
final donaturData = {
|
||||
'nama': nama,
|
||||
'telepon': telepon,
|
||||
'nama_lengkap': nama,
|
||||
'no_hp': noHp,
|
||||
'alamat': alamat,
|
||||
'email': email,
|
||||
'jenis': jenis,
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:penyaluran_app/app/data/models/desa_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/user_model.dart';
|
||||
import 'package:penyaluran_app/app/data/models/petugas_desa_model.dart';
|
||||
import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart';
|
||||
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/counter_service.dart';
|
||||
import 'package:penyaluran_app/app/services/supabase_service.dart';
|
||||
@ -49,9 +50,57 @@ class PetugasDesaController extends GetxController {
|
||||
// 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';
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
String get role => user?.roleName ?? 'PETUGAS_DESA';
|
||||
|
||||
// Helper method untuk format role agar lebih rapi
|
||||
String get formattedRole {
|
||||
final roleText = role.toLowerCase();
|
||||
if (roleText.contains('_')) {
|
||||
return roleText
|
||||
.split('_')
|
||||
.map((word) =>
|
||||
word.isNotEmpty ? word[0].toUpperCase() + word.substring(1) : '')
|
||||
.join(' ');
|
||||
}
|
||||
return roleText.isNotEmpty
|
||||
? roleText[0].toUpperCase() + roleText.substring(1)
|
||||
: 'Petugas Desa';
|
||||
}
|
||||
|
||||
String get nama {
|
||||
// 1. Coba ambil dari AuthController displayName yang paling lengkap
|
||||
final authDisplayName = _authController.displayName;
|
||||
if (authDisplayName != null &&
|
||||
authDisplayName != 'Pengguna' &&
|
||||
authDisplayName != user?.email) {
|
||||
return authDisplayName;
|
||||
}
|
||||
|
||||
// 2. Coba ambil dari roleData jika merupakan PetugasDesaModel
|
||||
final userData = _authController.userData;
|
||||
if (userData != null && userData.roleData is PetugasDesaModel) {
|
||||
final petugasData = userData.roleData as PetugasDesaModel;
|
||||
if (petugasData.namaLengkap != null &&
|
||||
petugasData.namaLengkap!.isNotEmpty) {
|
||||
return petugasData.namaLengkap!;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Coba ambil dari user.name
|
||||
if (user?.name != null && user!.name!.isNotEmpty) {
|
||||
return user!.name!;
|
||||
}
|
||||
|
||||
// 4. Fallback ke nama dari userProfile
|
||||
if (userProfile['name'] != null &&
|
||||
userProfile['name'].toString().isNotEmpty) {
|
||||
return userProfile['name'];
|
||||
}
|
||||
|
||||
// 5. Default fallback
|
||||
return 'Petugas Desa';
|
||||
}
|
||||
|
||||
// Getter untuk counter dari CounterService
|
||||
RxInt get jumlahNotifikasiBelumDibaca =>
|
||||
@ -64,6 +113,13 @@ class PetugasDesaController extends GetxController {
|
||||
|
||||
// Getter untuk nama desa dari profil pengguna
|
||||
String get desa {
|
||||
// Debug info
|
||||
print('DEBUG: Memeriksa data desa...');
|
||||
if (user != null) {
|
||||
print('DEBUG: User ID: ${user!.id}, User email: ${user!.email}');
|
||||
print('DEBUG: User desa: ${user!.desa}');
|
||||
}
|
||||
|
||||
// Prioritaskan model desa dari user
|
||||
if (user?.desa != null) {
|
||||
print('DEBUG: Menggunakan desa dari user model: ${user!.desa!.nama}');
|
||||
@ -77,9 +133,15 @@ class PetugasDesaController extends GetxController {
|
||||
return desaNama;
|
||||
}
|
||||
|
||||
// Jika masih tidak ada, coba dari desaModel
|
||||
if (desaModel.value != null) {
|
||||
print('DEBUG: Menggunakan desa dari desaModel: ${desaModel.value!.nama}');
|
||||
return desaModel.value!.nama;
|
||||
}
|
||||
|
||||
// Fallback ke nilai default
|
||||
print('DEBUG: Menggunakan nilai default untuk desa');
|
||||
return userProfile['desa_id'] != null ? 'Desa' : 'Desa';
|
||||
return 'Desa';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -109,34 +171,76 @@ class PetugasDesaController extends GetxController {
|
||||
// Metode untuk memuat data profil pengguna dari cache
|
||||
Future<void> loadUserProfile() async {
|
||||
try {
|
||||
// Jika user sudah ada di AuthController, tidak perlu mengambil data lagi
|
||||
// Jika user sudah ada di AuthController, gunakan data yang ada
|
||||
if (user != null) {
|
||||
print('DEBUG: User ditemukan di AuthController: ${user!.email}');
|
||||
print('DEBUG: User desa: ${user!.desa?.nama}');
|
||||
|
||||
// Ambil data tambahan jika diperlukan, tapi gunakan cache
|
||||
final profileData = await _supabaseService.getUserProfile();
|
||||
if (profileData != null) {
|
||||
print('DEBUG: Profile data ditemukan: ${profileData['name']}');
|
||||
userProfile.value = profileData;
|
||||
// Tidak perlu mengambil data tambahan jika user.desa sudah ada
|
||||
if (user!.desa != null) {
|
||||
print(
|
||||
'DEBUG: Menggunakan desa dari AuthController: ${user!.desa!.nama}');
|
||||
desaModel.value = user!.desa;
|
||||
|
||||
// Parse data desa jika ada
|
||||
if (profileData['desa'] != null &&
|
||||
profileData['desa'] is Map<String, dynamic>) {
|
||||
// Perbarui userProfile untuk konsistensi
|
||||
if (userProfile.isEmpty) {
|
||||
userProfile.value = {
|
||||
'name': user!.name ?? _authController.displayName,
|
||||
'desa': user!.desa?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
return; // Data sudah lengkap, tidak perlu fetch lagi
|
||||
}
|
||||
|
||||
print(
|
||||
'DEBUG: Data desa tidak ditemukan di AuthController, mencoba ambil dari cache');
|
||||
|
||||
// Jika tidak ada desa di AuthController, coba ambil dari userData roleData
|
||||
final userData = _authController.userData;
|
||||
if (userData != null) {
|
||||
if (userData.roleData is PetugasDesaModel) {
|
||||
final petugasData = userData.roleData as PetugasDesaModel;
|
||||
if (petugasData.desa != null) {
|
||||
print(
|
||||
'DEBUG: Menggunakan desa dari roleData: ${petugasData.desa!.nama}');
|
||||
desaModel.value = petugasData.desa;
|
||||
|
||||
// Perbarui userProfile untuk konsistensi
|
||||
userProfile.value = {
|
||||
'name': petugasData.displayName,
|
||||
'desa': petugasData.desa?.toJson(),
|
||||
};
|
||||
|
||||
return; // Data sudah lengkap, tidak perlu fetch lagi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Jika tidak ada di cache, ambil dari API hanya jika benar-benar diperlukan
|
||||
print('DEBUG: Data desa tidak ditemukan di cache, mengambil dari API');
|
||||
final baseProfile = await _supabaseService.getUserProfile();
|
||||
if (baseProfile != null) {
|
||||
userProfile.value = baseProfile;
|
||||
|
||||
if (baseProfile['desa'] != null &&
|
||||
baseProfile['desa'] is Map<String, dynamic>) {
|
||||
try {
|
||||
final desaData = profileData['desa'] as Map<String, dynamic>;
|
||||
print('DEBUG: Desa data ditemukan: $desaData');
|
||||
final desaData = baseProfile['desa'] as Map<String, dynamic>;
|
||||
print('DEBUG: Desa data ditemukan dari API: $desaData');
|
||||
desaModel.value = DesaModel.fromJson(desaData);
|
||||
} catch (e) {
|
||||
print('Error parsing desa data: $e');
|
||||
}
|
||||
} else {
|
||||
print('DEBUG: Desa data tidak ditemukan atau bukan Map');
|
||||
print('DEBUG: Desa data tidak ditemukan di API');
|
||||
}
|
||||
} else {
|
||||
print('DEBUG: Profile data tidak ditemukan');
|
||||
print('DEBUG: Profile data tidak ditemukan dari API');
|
||||
}
|
||||
} else {
|
||||
print('DEBUG: User tidak ditemukan di AuthController');
|
||||
print(
|
||||
'DEBUG: User tidak ditemukan di AuthController, mungkin belum login');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error loading user profile: $e');
|
||||
|
@ -27,7 +27,7 @@ class PetugasDesaDashboardController extends GetxController {
|
||||
// Controller untuk pencarian
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
String get role => user?.role ?? 'PETUGASDESA';
|
||||
String get nama => user?.name ?? 'Petugas Desa';
|
||||
|
||||
|
@ -17,7 +17,7 @@ class RiwayatPengaduanController extends GetxController {
|
||||
// Controller untuk pencarian
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
|
@ -36,7 +36,7 @@ class StokBantuanController extends GetxController {
|
||||
// Tambahkan properti untuk waktu terakhir update
|
||||
Rx<DateTime> lastUpdateTime = DateTime.now().obs;
|
||||
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
|
@ -198,7 +198,7 @@ class DetailDonaturView extends GetView<DonaturController> {
|
||||
donatur.alamat ?? 'Tidak ada alamat'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoItem(Icons.phone, 'Telepon',
|
||||
donatur.telepon ?? 'Tidak ada telepon'),
|
||||
donatur.noHp ?? 'Tidak ada telepon'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoItem(
|
||||
Icons.email, 'Email', donatur.email ?? 'Tidak ada email'),
|
||||
|
@ -1223,8 +1223,11 @@ class DetailPenyaluranPage extends StatelessWidget {
|
||||
const Divider(height: 24),
|
||||
if (warga != null) ...[
|
||||
_buildInfoRow('NIK', warga['nik'] ?? '-'),
|
||||
_buildInfoRow('Alamat Lengkap',
|
||||
'${warga['alamat'] ?? '-'} Desa ${warga['desa'] ?? '-'} Kecamatan ${warga['kecamatan'] ?? '-'} Kabupaten ${warga['kabupaten'] ?? '-'} Provinsi ${warga['provinsi'] ?? '-'}'),
|
||||
_buildInfoRow('Alamat', warga['alamat'] ?? '-'),
|
||||
_buildInfoRow('Desa', warga['desa'] ?? '-'),
|
||||
_buildInfoRow('Kecamatan', warga['kecamatan'] ?? '-'),
|
||||
_buildInfoRow('Kabupaten', warga['kabupaten'] ?? '-'),
|
||||
_buildInfoRow('Provinsi', warga['provinsi'] ?? '-'),
|
||||
_buildInfoRow(
|
||||
'Jenis Kelamin', warga['jenis_kelamin'] ?? '-'),
|
||||
_buildInfoRow('No. Telepon', warga['no_hp'] ?? '-'),
|
||||
|
@ -918,9 +918,8 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (selectedDonatur.value!.telepon !=
|
||||
null)
|
||||
Text(selectedDonatur.value!.telepon!),
|
||||
if (selectedDonatur.value!.noHp != null)
|
||||
Text(selectedDonatur.value!.noHp!),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -984,9 +983,9 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
return ListTile(
|
||||
title:
|
||||
Text(donatur.nama ?? 'Tidak ada nama'),
|
||||
subtitle: donatur.telepon != null
|
||||
? Text(donatur.telepon!)
|
||||
: null,
|
||||
subtitle: donatur.noHp != null
|
||||
? Text(donatur.noHp!)
|
||||
: const Text('Tidak ada nomor telepon'),
|
||||
dense: true,
|
||||
onTap: () {
|
||||
selectedDonatur.value = donatur;
|
||||
@ -1300,7 +1299,7 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
BuildContext context, Function(String) onDonaturAdded) {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final TextEditingController namaController = TextEditingController();
|
||||
final TextEditingController teleponController = TextEditingController();
|
||||
final TextEditingController noHpController = TextEditingController();
|
||||
final TextEditingController alamatController = TextEditingController();
|
||||
final TextEditingController emailController = TextEditingController();
|
||||
final TextEditingController jenisController = TextEditingController();
|
||||
@ -1352,24 +1351,24 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
|
||||
// Telepon
|
||||
Text(
|
||||
'Nomor Telepon',
|
||||
'Nomor HP',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
controller: teleponController,
|
||||
controller: noHpController,
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
hintText: 'Masukkan nomor telepon',
|
||||
hintText: 'Masukkan nomor HP',
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 8),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Nomor telepon harus diisi';
|
||||
return 'Nomor HP harus diisi';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@ -1396,24 +1395,16 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
: jenisController.text,
|
||||
items: const [
|
||||
DropdownMenuItem<String>(
|
||||
value: 'Perorangan',
|
||||
child: Text('Perorangan'),
|
||||
value: 'Individu',
|
||||
child: Text('Individu'),
|
||||
),
|
||||
DropdownMenuItem<String>(
|
||||
value: 'Perusahaan',
|
||||
child: Text('Perusahaan'),
|
||||
),
|
||||
DropdownMenuItem<String>(
|
||||
value: 'Lembaga',
|
||||
child: Text('Lembaga'),
|
||||
),
|
||||
DropdownMenuItem<String>(
|
||||
value: 'Komunitas',
|
||||
child: Text('Komunitas'),
|
||||
),
|
||||
DropdownMenuItem<String>(
|
||||
value: 'Lainnya',
|
||||
child: Text('Lainnya'),
|
||||
value: 'Organisasi',
|
||||
child: Text('Organisasi'),
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
@ -1478,7 +1469,7 @@ class PenitipanView extends GetView<PenitipanBantuanController> {
|
||||
if (formKey.currentState!.validate()) {
|
||||
final donaturId = await controller.tambahDonatur(
|
||||
nama: namaController.text,
|
||||
telepon: teleponController.text,
|
||||
noHp: noHpController.text,
|
||||
alamat: alamatController.text.isEmpty
|
||||
? null
|
||||
: alamatController.text,
|
||||
|
@ -151,7 +151,6 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
return const DashboardView();
|
||||
case 1:
|
||||
return const PenyaluranView();
|
||||
|
||||
case 2:
|
||||
return const PenitipanView();
|
||||
case 3:
|
||||
@ -182,22 +181,15 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundColor: Colors.white,
|
||||
backgroundImage: controller.user?.avatar != null &&
|
||||
controller.user!.avatar!.isNotEmpty
|
||||
? NetworkImage(controller.user!.avatar!)
|
||||
: null,
|
||||
child: controller.user?.avatar == null ||
|
||||
controller.user!.avatar!.isEmpty
|
||||
? const Icon(
|
||||
Icons.person,
|
||||
size: 40,
|
||||
color: AppTheme.primaryColor,
|
||||
)
|
||||
: null,
|
||||
child: const Icon(
|
||||
Icons.person,
|
||||
size: 40,
|
||||
color: AppTheme.primaryColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
controller.user?.name ?? 'Petugas Desa',
|
||||
controller.nama,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
@ -206,8 +198,8 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
),
|
||||
Text(
|
||||
controller.user?.desa?.nama != null
|
||||
? '${controller.user?.role} - ${controller.user!.desa!.nama}'
|
||||
: controller.user?.role ?? 'PETUGAS_DESA',
|
||||
? '${controller.formattedRole} - ${controller.user!.desa!.nama}'
|
||||
: controller.formattedRole,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withAlpha(200),
|
||||
fontSize: 14,
|
||||
@ -251,9 +243,9 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
? Badge(
|
||||
label: Text(controller.jumlahDiproses.value.toString()),
|
||||
backgroundColor: Colors.red,
|
||||
child: const Icon(Icons.support_outlined),
|
||||
child: const Icon(Icons.warning_amber_outlined),
|
||||
)
|
||||
: const Icon(Icons.support_outlined),
|
||||
: const Icon(Icons.warning_amber_outlined),
|
||||
title: const Text('Pengaduan'),
|
||||
selected: controller.activeTabIndex.value == 3,
|
||||
selectedColor: AppTheme.primaryColor,
|
||||
@ -272,6 +264,7 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
controller.changeTab(4);
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.person_add_outlined),
|
||||
title: const Text('Kelola Penerima'),
|
||||
@ -296,7 +289,6 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
Get.toNamed('/laporan-penyaluran');
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.person_outline),
|
||||
title: const Text('Profil'),
|
||||
|
@ -310,11 +310,15 @@ class RiwayatPenitipanView extends GetView<PenitipanBantuanController> {
|
||||
if (item.status == 'TERVERIFIKASI' &&
|
||||
item.petugasDesaId != null)
|
||||
Expanded(
|
||||
child: _buildItemDetail(
|
||||
context,
|
||||
icon: Icons.person,
|
||||
label: 'Diverifikasi Oleh',
|
||||
value: controller.getPetugasDesaNama(item.petugasDesaId),
|
||||
child: GetBuilder<PenitipanBantuanController>(
|
||||
id: 'petugas_data',
|
||||
builder: (controller) => _buildItemDetail(
|
||||
context,
|
||||
icon: Icons.person,
|
||||
label: 'Diverifikasi Oleh',
|
||||
value:
|
||||
controller.getPetugasDesaNama(item.petugasDesaId),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -1,14 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:penyaluran_app/app/data/models/user_model.dart';
|
||||
import 'package:penyaluran_app/app/services/auth_service.dart';
|
||||
import 'package:penyaluran_app/app/services/supabase_service.dart';
|
||||
import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart';
|
||||
|
||||
class ProfileController extends GetxController {
|
||||
final AuthService _authService = Get.find<AuthService>();
|
||||
final SupabaseService _supabaseService = Get.find<SupabaseService>();
|
||||
final AuthController _authController = Get.find<AuthController>();
|
||||
|
||||
final Rx<User?> user = Rx<User?>(null);
|
||||
final Rx<BaseUserModel?> user = Rx<BaseUserModel?>(null);
|
||||
final RxBool isLoading = true.obs;
|
||||
final RxBool isEditing = false.obs;
|
||||
final Rx<Map<String, dynamic>?> roleData = Rx<Map<String, dynamic>?>(null);
|
||||
|
||||
// Form controllers
|
||||
late TextEditingController nameController;
|
||||
@ -36,14 +39,23 @@ class ProfileController extends GetxController {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
// Mendapatkan data user dari service
|
||||
final userData = await _authService.getCurrentUser();
|
||||
user.value = userData;
|
||||
|
||||
// Mengisi form controllers dengan data user
|
||||
final userData = await _supabaseService.getUserProfile();
|
||||
if (userData != null) {
|
||||
nameController.text = userData.name ?? '';
|
||||
emailController.text = userData.email ?? '';
|
||||
phoneController.text = userData.phone ?? '';
|
||||
user.value = BaseUserModel.fromJson(userData);
|
||||
|
||||
// Mengisi form controllers dengan data user
|
||||
nameController.text = user.value?.name ?? '';
|
||||
emailController.text = user.value?.email ?? '';
|
||||
// Catatan: BaseUserModel tidak memiliki properti phone
|
||||
// Jika ada data role_data, simpan untuk ditampilkan
|
||||
if (userData['role_data'] != null) {
|
||||
roleData.value = userData['role_data'] as Map<String, dynamic>?;
|
||||
// Jika role adalah warga, ambil no telepon dari role data
|
||||
if (user.value?.role?.toLowerCase() == 'warga' &&
|
||||
roleData.value?['no_hp'] != null) {
|
||||
phoneController.text = roleData.value?['no_hp'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
@ -76,22 +88,45 @@ class ProfileController extends GetxController {
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
// Update user data
|
||||
final updatedUser = User(
|
||||
id: user.value?.id,
|
||||
name: nameController.text,
|
||||
email: emailController.text,
|
||||
phone: phoneController.text,
|
||||
role: user.value?.role,
|
||||
token: user.value?.token,
|
||||
);
|
||||
final userData = user.value;
|
||||
if (userData == null) throw 'Data user tidak ditemukan';
|
||||
|
||||
// Panggil API untuk update profil
|
||||
await _authService.updateProfile(updatedUser);
|
||||
// Update data sesuai role
|
||||
switch (userData.role?.toLowerCase() ?? 'unknown') {
|
||||
case 'warga':
|
||||
await _supabaseService.updateWargaProfile(
|
||||
userId: userData.id,
|
||||
namaLengkap: nameController.text,
|
||||
noHp: phoneController.text,
|
||||
email: emailController.text,
|
||||
);
|
||||
break;
|
||||
case 'donatur':
|
||||
await _supabaseService.updateDonaturProfile(
|
||||
userId: userData.id,
|
||||
nama: nameController.text,
|
||||
noHp: phoneController.text,
|
||||
email: emailController.text,
|
||||
);
|
||||
break;
|
||||
case 'petugas_desa':
|
||||
await _supabaseService.updatePetugasDesaProfile(
|
||||
userId: userData.id,
|
||||
nama: nameController.text,
|
||||
noHp: phoneController.text,
|
||||
email: emailController.text,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw 'Role tidak valid';
|
||||
}
|
||||
|
||||
// Refresh data
|
||||
// Refresh data lokal
|
||||
await loadUserData();
|
||||
|
||||
// Refresh data di AuthController untuk menyebarkan perubahan ke seluruh aplikasi
|
||||
await _authController.refreshUserData();
|
||||
|
||||
// Keluar dari mode edit
|
||||
isEditing.value = false;
|
||||
|
||||
@ -131,7 +166,7 @@ class ProfileController extends GetxController {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
// Panggil API untuk ganti password
|
||||
await _authService.changePassword(currentPassword, newPassword);
|
||||
await _supabaseService.changePassword(currentPassword, newPassword);
|
||||
|
||||
Get.back(); // Tutup dialog
|
||||
|
||||
|
@ -87,6 +87,7 @@ class ProfileView extends GetView<ProfileController> {
|
||||
Widget _buildProfileForm() {
|
||||
return Obx(() {
|
||||
final isEditing = controller.isEditing.value;
|
||||
final user = controller.user.value;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -119,7 +120,7 @@ class ProfileView extends GetView<ProfileController> {
|
||||
labelText: 'Email',
|
||||
border: OutlineInputBorder(),
|
||||
prefixIcon: Icon(Icons.email),
|
||||
enabled: isEditing,
|
||||
enabled: false, // Email tidak bisa diubah
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
),
|
||||
@ -136,6 +137,113 @@ class ProfileView extends GetView<ProfileController> {
|
||||
),
|
||||
keyboardType: TextInputType.phone,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Informasi tambahan sesuai role
|
||||
if (user != null) ...[
|
||||
if (user.role?.toLowerCase() == 'warga') ...[
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
'Informasi Warga',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Obx(() {
|
||||
final roleData = controller.roleData.value;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoRow(
|
||||
Icons.perm_identity, 'NIK', roleData?['nik'] ?? '-'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.wc, 'Jenis Kelamin',
|
||||
roleData?['jenis_kelamin'] ?? '-'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(
|
||||
Icons.home, 'Alamat', roleData?['alamat'] ?? '-'),
|
||||
if (user.desa != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(
|
||||
Icons.location_city, 'Desa', user.desa!.nama),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Kecamatan',
|
||||
user.desa!.kecamatan ?? ''),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Kabupaten',
|
||||
user.desa!.kabupaten ?? ''),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Provinsi',
|
||||
user.desa!.provinsi ?? ''),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
if (user.role?.toLowerCase() == 'donatur') ...[
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
'Informasi Donatur',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Obx(() {
|
||||
final roleData = controller.roleData.value;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoRow(Icons.business, 'Instansi',
|
||||
roleData?['instansi'] ?? '-'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(
|
||||
Icons.work, 'Jabatan', roleData?['jabatan'] ?? '-'),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
if (user.role?.toLowerCase() == 'petugas_desa') ...[
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
'Informasi Petugas Desa',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Obx(() {
|
||||
final roleData = controller.roleData.value;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoRow(Icons.badge, 'NIP', roleData?['nip'] ?? '-'),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(
|
||||
Icons.work, 'Jabatan', roleData?['jabatan'] ?? '-'),
|
||||
if (user.desa != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(
|
||||
Icons.location_city, 'Desa', user.desa!.nama),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Kecamatan',
|
||||
user.desa!.kecamatan ?? ''),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Kabupaten',
|
||||
user.desa!.kabupaten ?? ''),
|
||||
const SizedBox(height: 8),
|
||||
_buildInfoRow(Icons.location_on, 'Provinsi',
|
||||
user.desa!.provinsi ?? ''),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
});
|
||||
@ -230,4 +338,23 @@ class ProfileView extends GetView<ProfileController> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoRow(IconData icon, String label, String value) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(icon, size: 18, color: Colors.grey[700]),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$label: $value',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class WargaDashboardController extends GetxController {
|
||||
final AuthController _authController = Get.find<AuthController>();
|
||||
final SupabaseService _supabaseService = SupabaseService.to;
|
||||
|
||||
final Rx<UserModel?> currentUser = Rx<UserModel?>(null);
|
||||
final Rx<BaseUserModel?> currentUser = Rx<BaseUserModel?>(null);
|
||||
|
||||
// Indeks tab yang aktif di bottom navigation bar
|
||||
final RxInt activeTabIndex = 0.obs;
|
||||
@ -41,9 +41,18 @@ class WargaDashboardController extends GetxController {
|
||||
final RxInt jumlahNotifikasiBelumDibaca = 0.obs;
|
||||
|
||||
// Getter untuk data user
|
||||
UserModel? get user => _authController.user;
|
||||
BaseUserModel? get user => _authController.baseUser;
|
||||
String get role => user?.role ?? 'WARGA';
|
||||
String get nama => user?.name ?? 'Warga';
|
||||
String get nama {
|
||||
// Gunakan namaLengkap dari roleData jika tersedia
|
||||
if (_authController.isWarga && _authController.roleData != null) {
|
||||
return _authController.roleData.namaLengkap ??
|
||||
_authController.displayName;
|
||||
}
|
||||
// Gunakan displayName dari AuthController
|
||||
return _authController.displayName;
|
||||
}
|
||||
|
||||
String? get desa => user?.desa?.nama;
|
||||
|
||||
@override
|
||||
@ -54,7 +63,30 @@ class WargaDashboardController extends GetxController {
|
||||
}
|
||||
|
||||
void loadUserData() {
|
||||
currentUser.value = _authController.user;
|
||||
currentUser.value = _authController.baseUser;
|
||||
|
||||
// Tambahkan log debugging
|
||||
print('DEBUG WARGA: Memuat data user dari AuthController');
|
||||
print('DEBUG WARGA: baseUser: ${_authController.baseUser}');
|
||||
print('DEBUG WARGA: roleData: ${_authController.roleData}');
|
||||
print('DEBUG WARGA: nama yang akan ditampilkan: ${nama}');
|
||||
print(
|
||||
'DEBUG WARGA: displayName dari auth controller: ${_authController.displayName}');
|
||||
|
||||
if (_authController.userData != null) {
|
||||
print(
|
||||
'DEBUG WARGA: userData ada, role: ${_authController.userData!.baseUser.roleName}');
|
||||
|
||||
if (_authController.isWarga) {
|
||||
print('DEBUG WARGA: User adalah warga');
|
||||
var wargaData = _authController.roleData;
|
||||
print('DEBUG WARGA: Data warga: ${wargaData?.namaLengkap}');
|
||||
} else {
|
||||
print('DEBUG WARGA: User bukan warga');
|
||||
}
|
||||
} else {
|
||||
print('DEBUG WARGA: userData null');
|
||||
}
|
||||
}
|
||||
|
||||
void fetchData() async {
|
||||
@ -90,14 +122,8 @@ class WargaDashboardController extends GetxController {
|
||||
// Reset data terlebih dahulu untuk memastikan tidak ada data lama yang tersimpan
|
||||
penerimaPenyaluran.clear();
|
||||
|
||||
// Pertama, cari warga_id berdasarkan user_id
|
||||
final wargaResponse = await _supabaseService.client
|
||||
.from('warga')
|
||||
.select('id')
|
||||
.eq('user_id', user!.id)
|
||||
.single();
|
||||
|
||||
final wargaId = wargaResponse['id'];
|
||||
// Gunakan langsung ID pengguna sebagai warga_id
|
||||
final wargaId = user!.id;
|
||||
|
||||
// Ambil data penerima penyaluran dengan join ke warga, stok bantuan, dan penyaluran bantuan
|
||||
final response =
|
||||
@ -221,14 +247,8 @@ class WargaDashboardController extends GetxController {
|
||||
// Fungsi untuk mengambil data pengajuan kelayakan
|
||||
Future<void> fetchPengajuanKelayakan() async {
|
||||
try {
|
||||
// Pertama, cari warga_id berdasarkan user_id
|
||||
final wargaResponse = await _supabaseService.client
|
||||
.from('warga')
|
||||
.select('id')
|
||||
.eq('user_id', user!.id)
|
||||
.single();
|
||||
|
||||
final wargaId = wargaResponse['id'];
|
||||
// Gunakan langsung ID pengguna sebagai warga_id
|
||||
final wargaId = user!.id;
|
||||
|
||||
final response = await _supabaseService.client
|
||||
.from('xx02_pengajuan_kelayakan_bantuan')
|
||||
@ -257,19 +277,17 @@ class WargaDashboardController extends GetxController {
|
||||
totalPengajuanDitolak.value =
|
||||
pengajuan.where((p) => p.status == StatusKelayakan.DITOLAK).length;
|
||||
} catch (e) {
|
||||
print('Error fetching pengajuan kelayakan: $e');
|
||||
print('Error fetchPengajuanKelayakan: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk mengambil data pengaduan
|
||||
Future<void> fetchPengaduan() async {
|
||||
try {
|
||||
final wargaData = await _supabaseService.getWargaByUserId();
|
||||
if (wargaData == null) {
|
||||
return;
|
||||
}
|
||||
// Gunakan langsung ID user dari AuthController, bukan getWargaByUserId()
|
||||
String wargaId = user!.id;
|
||||
print('DEBUG WARGA: Mengambil pengaduan untuk warga ID: $wargaId');
|
||||
|
||||
final String wargaId = wargaData['id'];
|
||||
final response = await _supabaseService
|
||||
.getPengaduanWargaWithPenerimaPenyaluran(wargaId);
|
||||
|
||||
@ -287,15 +305,21 @@ class WargaDashboardController extends GetxController {
|
||||
.length;
|
||||
totalPengaduanSelesai.value =
|
||||
pengaduanList.where((p) => p.status == 'SELESAI').length;
|
||||
|
||||
print(
|
||||
'DEBUG WARGA: Berhasil mendapatkan ${pengaduanList.length} pengaduan');
|
||||
} else {
|
||||
print('DEBUG WARGA: Tidak ada pengaduan yang ditemukan');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error fetching pengaduan: $e');
|
||||
print('DEBUG WARGA: Error fetching pengaduan: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk mengambil data notifikasi
|
||||
Future<void> fetchNotifikasi() async {
|
||||
try {
|
||||
// Notifikasi masih menggunakan user_id karena tabelnya terpisah
|
||||
final response = await _supabaseService.client
|
||||
.from('notifikasi')
|
||||
.select('*')
|
||||
@ -429,13 +453,8 @@ class WargaDashboardController extends GetxController {
|
||||
try {
|
||||
isLoading.value = true;
|
||||
|
||||
// Cari warga_id berdasarkan user_id
|
||||
final wargaData = await _supabaseService.getWargaByUserId();
|
||||
if (wargaData == null) {
|
||||
throw Exception('Data warga tidak ditemukan');
|
||||
}
|
||||
|
||||
final String wargaId = wargaData['id'];
|
||||
// Gunakan langsung ID pengguna sebagai warga_id
|
||||
final String wargaId = user!.id;
|
||||
|
||||
// Upload foto pengaduan jika ada
|
||||
List<String> fotoPengaduanUrls = [];
|
||||
|
Reference in New Issue
Block a user