semua fitur selesai

This commit is contained in:
Andreas Malvino
2025-06-30 15:22:38 +07:00
parent 8284c93aa5
commit 0423c2fdf9
54 changed files with 11844 additions and 3143 deletions

View File

@ -59,6 +59,13 @@ class PembayaranSewaController extends GetxController
final RxList<WebImageFile> imagesToDeleteTagihanAwal = <WebImageFile>[].obs;
final RxList<WebImageFile> imagesToDeleteDenda = <WebImageFile>[].obs;
// Package related properties
final isPaket = false.obs;
final paketId = ''.obs;
final paketDetails = Rx<Map<String, dynamic>>({});
final paketItems = <Map<String, dynamic>>[].obs;
final isPaketItemsLoaded = false.obs;
// Flag to track if there are changes that need to be saved
final RxBool hasUnsavedChangesTagihanAwal = false.obs;
final RxBool hasUnsavedChangesDenda = false.obs;
@ -255,6 +262,24 @@ class PembayaranSewaController extends GetxController
if (Get.arguments['orderId'] != null) {
orderId.value = Get.arguments['orderId'];
// Get isPaket flag and paketId
isPaket.value = Get.arguments['isPaket'] == true;
if (isPaket.value && Get.arguments['paketId'] != null) {
paketId.value = Get.arguments['paketId'];
debugPrint(
'📦 This is a package order with paketId: ${paketId.value}',
);
}
// Set initial tab if specified
if (Get.arguments['initialTab'] != null) {
int initialTab = Get.arguments['initialTab'];
if (initialTab >= 0 && initialTab < tabController.length) {
debugPrint('Setting initial tab to: $initialTab');
tabController.animateTo(initialTab);
}
}
// If rental data is passed, use it directly
if (Get.arguments['rentalData'] != null) {
Map<String, dynamic> rentalData = Get.arguments['rentalData'];
@ -367,6 +392,11 @@ class PembayaranSewaController extends GetxController
'✅ Sewa aset details loaded: ${sewaAsetDetails.value['id']}',
);
// If this is a package order, load package details
if (isPaket.value && paketId.value.isNotEmpty) {
loadPaketDetails();
}
// Debug all fields in the sewaAsetDetails
debugPrint('📋 SEWA ASET DETAILS (COMPLETE DATA):');
data.forEach((key, value) {
@ -1250,4 +1280,56 @@ class PembayaranSewaController extends GetxController
return Future.value();
}
// Load package details and items
Future<void> loadPaketDetails() async {
if (!isPaket.value || paketId.value.isEmpty) return;
try {
debugPrint('🔄 Loading package details for ID: ${paketId.value}');
// Get package details
final paketResponse =
await client
.from('paket')
.select('*')
.eq('id', paketId.value)
.maybeSingle();
if (paketResponse != null) {
paketDetails.value = paketResponse;
debugPrint('✅ Package details loaded: ${paketDetails.value['nama']}');
}
// Load package items
debugPrint('🔄 Loading package items for package ID: ${paketId.value}');
final itemsResponse = await client
.from('paket_item')
.select('*, aset(*)')
.eq('paket_id', paketId.value);
if (itemsResponse != null &&
itemsResponse is List &&
itemsResponse.isNotEmpty) {
paketItems.value = List<Map<String, dynamic>>.from(itemsResponse);
isPaketItemsLoaded.value = true;
debugPrint('✅ Loaded ${paketItems.length} package items');
} else {
paketItems.clear();
debugPrint('⚠️ No package items found');
}
} catch (e) {
debugPrint('❌ Error loading package details: $e');
}
}
// Check if the sewa_aset table has the necessary columns
// Handle back button press - navigate to warga sewa page
void onBackPressed() {
debugPrint(
'🔙 Back button pressed in PembayaranSewaView - navigating to WargaSewa',
);
navigationService.toWargaSewa();
}
}

View File

@ -1,9 +1,14 @@
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import '../../../data/providers/auth_provider.dart';
import '../../../routes/app_routes.dart';
import '../../../services/navigation_service.dart';
import '../../../data/providers/aset_provider.dart';
import '../../../theme/app_colors.dart';
import 'package:intl/intl.dart';
import 'package:flutter/foundation.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:image_picker/image_picker.dart';
class WargaDashboardController extends GetxController {
// Dependency injection
@ -19,6 +24,10 @@ class WargaDashboardController extends GetxController {
final userNik = ''.obs;
final userPhone = ''.obs;
final userAddress = ''.obs;
final userTanggalLahir = ''.obs;
final userRtRw = ''.obs;
final userKelurahanDesa = ''.obs;
final userKecamatan = ''.obs;
// Navigation state is now managed by NavigationService
@ -90,6 +99,18 @@ class WargaDashboardController extends GetxController {
userNik.value = await _authProvider.getUserNIK() ?? '';
userPhone.value = await _authProvider.getUserPhone() ?? '';
userAddress.value = await _authProvider.getUserAddress() ?? '';
// Load additional profile data
final tanggalLahir = await _authProvider.getUserTanggalLahir();
final rtRw = await _authProvider.getUserRtRw();
final kelurahanDesa = await _authProvider.getUserKelurahanDesa();
final kecamatan = await _authProvider.getUserKecamatan();
// Set values for additional profile data
userTanggalLahir.value = tanggalLahir ?? 'Tidak tersedia';
userRtRw.value = rtRw ?? 'Tidak tersedia';
userKelurahanDesa.value = kelurahanDesa ?? 'Tidak tersedia';
userKecamatan.value = kecamatan ?? 'Tidak tersedia';
} catch (e) {
print('Error loading user data: $e');
}
@ -330,4 +351,369 @@ class WargaDashboardController extends GetxController {
print('Error fetching profile from warga_desa: $e');
}
}
// Method to update user profile data in warga_desa table
Future<bool> updateUserProfile({
required String namaLengkap,
required String noHp,
}) async {
try {
final user = _authProvider.currentUser;
if (user == null) {
print('Cannot update profile: No current user');
return false;
}
final userId = user.id;
// Update data in warga_desa table
await _authProvider.client
.from('warga_desa')
.update({'nama_lengkap': namaLengkap, 'no_hp': noHp})
.eq('user_id', userId);
// Update local values
userName.value = namaLengkap;
userPhone.value = noHp;
print('Profile updated successfully for user: $userId');
return true;
} catch (e) {
print('Error updating user profile: $e');
return false;
}
}
// Method to delete user avatar
Future<bool> deleteUserAvatar() async {
try {
final user = _authProvider.currentUser;
if (user == null) {
print('Cannot delete avatar: No current user');
return false;
}
final userId = user.id;
final currentAvatarUrl = userAvatar.value;
// If there's an avatar URL, delete it from storage
if (currentAvatarUrl != null && currentAvatarUrl.isNotEmpty) {
try {
print('Attempting to delete avatar from URL: $currentAvatarUrl');
// Extract filename from URL
// The URL format is typically:
// https://[project-ref].supabase.co/storage/v1/object/public/warga/[filename]
final uri = Uri.parse(currentAvatarUrl);
final path = uri.path;
// Find the filename after the last slash
final filename = path.substring(path.lastIndexOf('/') + 1);
if (filename.isNotEmpty) {
print('Extracted filename: $filename');
// Delete from storage bucket 'warga'
final response = await _authProvider.client.storage
.from('warga')
.remove([filename]);
print('Storage deletion response: $response');
} else {
print('Failed to extract filename from avatar URL');
}
} catch (e) {
print('Error deleting avatar from storage: $e');
// Continue with database update even if storage delete fails
}
}
// Update warga_desa table to set avatar to null
await _authProvider.client
.from('warga_desa')
.update({'avatar': null})
.eq('user_id', userId);
// Update local value
userAvatar.value = '';
print('Avatar deleted successfully for user: $userId');
return true;
} catch (e) {
print('Error deleting user avatar: $e');
return false;
}
}
// Method to update user avatar URL
Future<bool> updateUserAvatar(String avatarUrl) async {
try {
final user = _authProvider.currentUser;
if (user == null) {
print('Cannot update avatar: No current user');
return false;
}
final userId = user.id;
// Update data in warga_desa table
await _authProvider.client
.from('warga_desa')
.update({'avatar': avatarUrl})
.eq('user_id', userId);
// Update local value
userAvatar.value = avatarUrl;
print('Avatar updated successfully for user: $userId');
return true;
} catch (e) {
print('Error updating user avatar: $e');
return false;
}
}
// Method to upload avatar image to Supabase storage
Future<String?> uploadAvatar(Uint8List fileBytes, String fileName) async {
try {
final user = _authProvider.currentUser;
if (user == null) {
print('Cannot upload avatar: No current user');
return null;
}
// Generate a unique filename using timestamp and user ID
final timestamp = DateTime.now().millisecondsSinceEpoch;
final extension = fileName.split('.').last;
final uniqueFileName = 'avatar_${user.id}_$timestamp.$extension';
// Upload to 'warga' bucket
final response = await _authProvider.client.storage
.from('warga')
.uploadBinary(
uniqueFileName,
fileBytes,
fileOptions: const FileOptions(cacheControl: '3600', upsert: true),
);
// Get the public URL
final publicUrl = _authProvider.client.storage
.from('warga')
.getPublicUrl(uniqueFileName);
print('Avatar uploaded successfully: $publicUrl');
return publicUrl;
} catch (e) {
print('Error uploading avatar: $e');
return null;
}
}
// Method to handle image picking from camera or gallery
Future<XFile?> pickImage(ImageSource source) async {
try {
// Pick image directly without permission checks
final ImagePicker picker = ImagePicker();
final XFile? pickedFile = await picker.pickImage(
source: source,
maxWidth: 800,
maxHeight: 800,
imageQuality: 85,
);
if (pickedFile != null) {
print('Image picked: ${pickedFile.path}');
}
return pickedFile;
} catch (e) {
print('Error picking image: $e');
// Show error message if there's an issue
Get.snackbar(
'Gagal',
'Tidak dapat mengakses ${source == ImageSource.camera ? 'kamera' : 'galeri'}',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade700,
colorText: Colors.white,
duration: const Duration(seconds: 3),
);
return null;
}
}
// Method to show image source selection dialog
Future<void> showImageSourceDialog() async {
await Get.bottomSheet(
Container(
padding: const EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(bottom: 20),
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
),
const Text(
'Pilih Sumber Gambar',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildImageSourceOption(
icon: Icons.camera_alt_rounded,
label: 'Kamera',
onTap: () async {
Get.back();
final pickedFile = await pickImage(ImageSource.camera);
if (pickedFile != null) {
await processPickedImage(pickedFile);
}
},
),
_buildImageSourceOption(
icon: Icons.photo_library_rounded,
label: 'Galeri',
onTap: () async {
Get.back();
final pickedFile = await pickImage(ImageSource.gallery);
if (pickedFile != null) {
await processPickedImage(pickedFile);
}
},
),
],
),
const SizedBox(height: 20),
],
),
),
isDismissible: true,
enableDrag: true,
);
}
// Helper method to build image source option
Widget _buildImageSourceOption({
required IconData icon,
required String label,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.primary.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(icon, color: AppColors.primary, size: 32),
),
const SizedBox(height: 8),
Text(
label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.grey.shade800,
),
),
],
),
);
}
// Method to process picked image (temporary preview before saving)
Future<void> processPickedImage(XFile pickedFile) async {
try {
// Read file as bytes
final bytes = await pickedFile.readAsBytes();
// Store the picked file temporarily for later use when saving
tempPickedFile.value = pickedFile;
// Update UI with temporary avatar preview
tempAvatarBytes.value = bytes;
print('Image processed for preview');
} catch (e) {
print('Error processing picked image: $e');
}
}
// Method to save the picked image to Supabase and update profile
Future<bool> saveNewAvatar() async {
try {
if (tempPickedFile.value == null || tempAvatarBytes.value == null) {
print('No temporary image to save');
return false;
}
final pickedFile = tempPickedFile.value!;
final bytes = tempAvatarBytes.value!;
// First delete the old avatar if exists
final currentAvatarUrl = userAvatar.value;
if (currentAvatarUrl != null && currentAvatarUrl.isNotEmpty) {
try {
await deleteUserAvatar();
} catch (e) {
print('Error deleting old avatar: $e');
// Continue with upload even if delete fails
}
}
// Upload new avatar
final newAvatarUrl = await uploadAvatar(bytes, pickedFile.name);
if (newAvatarUrl == null) {
print('Failed to upload new avatar');
return false;
}
// Update avatar URL in database
final success = await updateUserAvatar(newAvatarUrl);
if (success) {
// Clear temporary data
tempPickedFile.value = null;
tempAvatarBytes.value = null;
print('Avatar updated successfully');
}
return success;
} catch (e) {
print('Error saving new avatar: $e');
return false;
}
}
// Method to cancel avatar change
void cancelAvatarChange() {
tempPickedFile.value = null;
tempAvatarBytes.value = null;
print('Avatar change canceled');
}
// Temporary storage for picked image
final Rx<XFile?> tempPickedFile = Rx<XFile?>(null);
final Rx<Uint8List?> tempAvatarBytes = Rx<Uint8List?>(null);
}

View File

@ -133,6 +133,111 @@ class WargaSewaController extends GetxController
super.onClose();
}
// Helper method to process rental data
Future<Map<String, dynamic>> _processRentalData(
Map<String, dynamic> sewaAset,
) async {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
// Check if this is a package or single asset rental
bool isPaket = sewaAset['aset_id'] == null && sewaAset['paket_id'] != null;
if (isPaket) {
// Use package data that was fetched in getSewaAsetByStatus
assetName = sewaAset['nama_paket'] ?? 'Paket';
imageUrl = sewaAset['foto_paket'];
debugPrint(
'Using package data: name=${assetName}, imageUrl=${imageUrl ?? "none"}',
);
} else if (sewaAset['aset_id'] != null) {
// Regular asset rental
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null && sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Return processed rental data
return {
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? '',
'totalPrice': totalPrice,
'countdown': '00:59:59', // Default countdown
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
'updated_at': sewaAset['updated_at'],
'isPaket': isPaket,
'paketId': isPaket ? sewaAset['paket_id'] : null,
};
}
// Load real data from sewa_aset table
Future<void> loadRentalsData() async {
try {
@ -151,93 +256,9 @@ class WargaSewaController extends GetxController
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Add to rentals list
rentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'MENUNGGU PEMBAYARAN',
'totalPrice': totalPrice,
'countdown': '00:59:59', // Default countdown
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
'updated_at': sewaAset['updated_at'],
});
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'MENUNGGU PEMBAYARAN';
rentals.add(processedData);
}
debugPrint('Processed ${rentals.length} rental records');
@ -335,6 +356,23 @@ class WargaSewaController extends GetxController
);
}
// Navigate directly to payment tab of payment page with the selected rental data
void viewPaymentTab(Map<String, dynamic> rental) {
debugPrint('Navigating to payment tab with rental ID: ${rental['id']}');
// Navigate to payment page with rental data and initialTab set to 2 (payment tab)
Get.toNamed(
Routes.PEMBAYARAN_SEWA,
arguments: {
'orderId': rental['id'],
'rentalData': rental,
'initialTab': 2, // Index 2 corresponds to the payment tab
'isPaket': rental['isPaket'] ?? false,
'paketId': rental['paketId'],
},
);
}
void payRental(String id) {
Get.snackbar(
'Info',
@ -358,91 +396,9 @@ class WargaSewaController extends GetxController
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Add to completed rentals list
completedRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'SELESAI',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
});
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'SELESAI';
completedRentals.add(processedData);
}
debugPrint(
@ -472,92 +428,11 @@ class WargaSewaController extends GetxController
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Add to cancelled rentals list
cancelledRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'DIBATALKAN',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
'alasanPembatalan': sewaAset['alasan_pembatalan'] ?? '-',
});
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'DIBATALKAN';
processedData['alasanPembatalan'] =
sewaAset['alasan_pembatalan'] ?? '-';
cancelledRentals.add(processedData);
}
debugPrint(
@ -570,6 +445,64 @@ class WargaSewaController extends GetxController
}
}
// Load data for the Dikembalikan tab (status: DIKEMBALIKAN)
Future<void> loadReturnedRentals() async {
try {
isLoadingReturned.value = true;
// Clear existing data
returnedRentals.clear();
// Get sewa_aset data with status "DIKEMBALIKAN"
final sewaAsetList = await authProvider.getSewaAsetByStatus([
'DIKEMBALIKAN',
]);
debugPrint('Fetched ${sewaAsetList.length} returned sewa_aset records');
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'DIKEMBALIKAN';
returnedRentals.add(processedData);
}
debugPrint('Processed ${returnedRentals.length} returned rental records');
} catch (e) {
debugPrint('Error loading returned rentals data: $e');
} finally {
isLoadingReturned.value = false;
}
}
// Load data for the Aktif tab (status: AKTIF)
Future<void> loadActiveRentals() async {
try {
isLoadingActive.value = true;
// Clear existing data
activeRentals.clear();
// Get sewa_aset data with status "AKTIF"
final sewaAsetList = await authProvider.getSewaAsetByStatus(['AKTIF']);
debugPrint('Fetched ${sewaAsetList.length} active sewa_aset records');
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'AKTIF';
activeRentals.add(processedData);
}
debugPrint('Processed ${activeRentals.length} active rental records');
} catch (e) {
debugPrint('Error loading active rentals data: $e');
} finally {
isLoadingActive.value = false;
}
}
// Load data for the Pending tab (status: PERIKSA PEMBAYARAN)
Future<void> loadPendingRentals() async {
try {
@ -588,91 +521,9 @@ class WargaSewaController extends GetxController
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Add to pending rentals list
pendingRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'PERIKSA PEMBAYARAN',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
});
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'PERIKSA PEMBAYARAN';
pendingRentals.add(processedData);
}
debugPrint('Processed ${pendingRentals.length} pending rental records');
@ -698,91 +549,9 @@ class WargaSewaController extends GetxController
// Process each sewa_aset record
for (var sewaAset in sewaAsetList) {
// Get asset details if aset_id is available
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
// Parse waktu mulai and waktu selesai
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
// Format for display
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
// Format based on satuan waktu
if (namaSatuanWaktu.toLowerCase() == 'jam') {
// For hours, show time range on same day
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
// For days, show date range
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
// Default format
rentangWaktu = '$jamMulai - $jamSelesai';
}
// Full time format for waktuSewa
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
// Format price
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
// Add to accepted rentals list
acceptedRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'DITERIMA',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
});
final processedData = await _processRentalData(sewaAset);
processedData['status'] = sewaAset['status'] ?? 'DITERIMA';
acceptedRentals.add(processedData);
}
debugPrint('Processed ${acceptedRentals.length} accepted rental records');
@ -792,166 +561,4 @@ class WargaSewaController extends GetxController
isLoadingAccepted.value = false;
}
}
Future<void> loadReturnedRentals() async {
try {
isLoadingReturned.value = true;
returnedRentals.clear();
final sewaAsetList = await authProvider.getSewaAsetByStatus([
'DIKEMBALIKAN',
]);
for (var sewaAset in sewaAsetList) {
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
if (namaSatuanWaktu.toLowerCase() == 'jam') {
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
rentangWaktu = '$jamMulai - $jamSelesai';
}
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
returnedRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'DIKEMBALIKAN',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
});
}
} catch (e) {
debugPrint('Error loading returned rentals data: $e');
} finally {
isLoadingReturned.value = false;
}
}
Future<void> loadActiveRentals() async {
try {
isLoadingActive.value = true;
activeRentals.clear();
final sewaAsetList = await authProvider.getSewaAsetByStatus(['AKTIF']);
for (var sewaAset in sewaAsetList) {
String assetName = 'Aset';
String? imageUrl;
String namaSatuanWaktu = sewaAset['nama_satuan_waktu'] ?? 'jam';
if (sewaAset['aset_id'] != null) {
final asetData = await asetProvider.getAsetById(sewaAset['aset_id']);
if (asetData != null) {
assetName = asetData.nama;
imageUrl = asetData.imageUrl;
}
}
DateTime? waktuMulai;
DateTime? waktuSelesai;
String waktuSewa = '';
String tanggalSewa = '';
String jamMulai = '';
String jamSelesai = '';
String rentangWaktu = '';
if (sewaAset['waktu_mulai'] != null &&
sewaAset['waktu_selesai'] != null) {
waktuMulai = DateTime.parse(sewaAset['waktu_mulai']);
waktuSelesai = DateTime.parse(sewaAset['waktu_selesai']);
final formatTanggal = DateFormat('dd-MM-yyyy');
final formatWaktu = DateFormat('HH:mm');
final formatTanggalLengkap = DateFormat('dd MMMM yyyy', 'id_ID');
tanggalSewa = formatTanggalLengkap.format(waktuMulai);
jamMulai = formatWaktu.format(waktuMulai);
jamSelesai = formatWaktu.format(waktuSelesai);
if (namaSatuanWaktu.toLowerCase() == 'jam') {
rentangWaktu = '$jamMulai - $jamSelesai';
} else if (namaSatuanWaktu.toLowerCase() == 'hari') {
final tanggalMulai = formatTanggalLengkap.format(waktuMulai);
final tanggalSelesai = formatTanggalLengkap.format(waktuSelesai);
rentangWaktu = '$tanggalMulai - $tanggalSelesai';
} else {
rentangWaktu = '$jamMulai - $jamSelesai';
}
waktuSewa =
'${formatTanggal.format(waktuMulai)} | ${formatWaktu.format(waktuMulai)} - '
'${formatTanggal.format(waktuSelesai)} | ${formatWaktu.format(waktuSelesai)}';
}
String totalPrice = 'Rp 0';
if (sewaAset['total'] != null) {
final formatter = NumberFormat.currency(
locale: 'id',
symbol: 'Rp ',
decimalDigits: 0,
);
totalPrice = formatter.format(sewaAset['total']);
}
activeRentals.add({
'id': sewaAset['id'] ?? '',
'name': assetName,
'imageUrl': imageUrl ?? 'assets/images/gambar_pendukung.jpg',
'jumlahUnit': sewaAset['kuantitas'] ?? 0,
'waktuSewa': waktuSewa,
'duration': '${sewaAset['durasi'] ?? 0} ${namaSatuanWaktu}',
'status': sewaAset['status'] ?? 'AKTIF',
'totalPrice': totalPrice,
'tanggalSewa': tanggalSewa,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'rentangWaktu': rentangWaktu,
'namaSatuanWaktu': namaSatuanWaktu,
'waktuMulai': sewaAset['waktu_mulai'],
'waktuSelesai': sewaAset['waktu_selesai'],
});
}
} catch (e) {
debugPrint('Error loading active rentals data: $e');
} finally {
isLoadingActive.value = false;
}
}
}