fitur petugas

This commit is contained in:
Andreas Malvino
2025-06-22 09:25:58 +07:00
parent c4dd4fdfa2
commit 8284c93aa5
48 changed files with 8688 additions and 3436 deletions

View File

@ -5,6 +5,7 @@ class AsetModel {
final String nama;
final String deskripsi;
final String kategori;
final String jenis; // Add this line
final int harga;
final int? denda;
final String status;
@ -14,17 +15,21 @@ class AsetModel {
final int? kuantitasTerpakai;
final String? satuanUkur;
// Untuk menampung URL gambar pertama dari tabel foto_aset
// URL gambar utama (untuk backward compatibility)
String? imageUrl;
// List untuk menyimpan semua URL gambar aset
final RxList<String> imageUrls = <String>[].obs;
// Menggunakan RxList untuk membuatnya mutable dan reaktif
RxList<Map<String, dynamic>> satuanWaktuSewa = <Map<String, dynamic>>[].obs;
final RxList<Map<String, dynamic>> satuanWaktuSewa = <Map<String, dynamic>>[].obs;
AsetModel({
required this.id,
required this.nama,
required this.deskripsi,
required this.kategori,
this.jenis = 'Sewa', // Add this line with default value
required this.harga,
this.denda,
required this.status,
@ -42,31 +47,69 @@ class AsetModel {
}
}
// Menambahkan URL gambar dari JSON
void addImageUrl(String? url) {
if (url != null && url.isNotEmpty && !imageUrls.contains(url)) {
imageUrls.add(url);
// Update imageUrl untuk backward compatibility
if (imageUrl == null) {
imageUrl = url;
}
}
}
// Menghapus URL gambar
bool removeImageUrl(String url) {
final removed = imageUrls.remove(url);
if (removed && imageUrl == url) {
imageUrl = imageUrls.isNotEmpty ? imageUrls.first : null;
}
return removed;
}
factory AsetModel.fromJson(Map<String, dynamic> json) {
return AsetModel(
final model = AsetModel(
id: json['id'] ?? '',
nama: json['nama'] ?? '',
deskripsi: json['deskripsi'] ?? '',
kategori: json['kategori'] ?? '',
jenis: json['jenis'] ?? 'Sewa',
harga: json['harga'] ?? 0,
denda: json['denda'],
status: json['status'] ?? '',
createdAt:
json['created_at'] != null
? DateTime.parse(json['created_at'])
: null,
updatedAt:
json['updated_at'] != null
? DateTime.parse(json['updated_at'])
: null,
createdAt: json['created_at'] != null
? DateTime.parse(json['created_at'])
: null,
updatedAt: json['updated_at'] != null
? DateTime.parse(json['updated_at'])
: null,
kuantitas: json['kuantitas'],
kuantitasTerpakai: json['kuantitas_terpakai'],
satuanUkur: json['satuan_ukur'],
imageUrl: json['foto_aset'],
initialSatuanWaktuSewa: json['satuan_waktu_sewa'] != null
? List<Map<String, dynamic>>.from(json['satuan_waktu_sewa'])
: null,
);
// Add the main image URL to the list if it exists
if (json['foto_aset'] != null) {
model.addImageUrl(json['foto_aset']);
}
// Add any additional image URLs if they exist in the JSON
if (json['foto_aset_tambahan'] != null) {
final additionalImages = List<String>.from(json['foto_aset_tambahan']);
for (final url in additionalImages) {
model.addImageUrl(url);
}
}
return model;
}
Map<String, dynamic> toJson() {
return {
final data = <String, dynamic>{
'id': id,
'nama': nama,
'deskripsi': deskripsi,
@ -80,5 +123,23 @@ class AsetModel {
'kuantitas_terpakai': kuantitasTerpakai,
'satuan_ukur': satuanUkur,
};
// Add image URLs if they exist
if (imageUrls.isNotEmpty) {
data['foto_aset'] = imageUrl;
// Add additional images (excluding the main image)
final additionalImages = imageUrls.where((url) => url != imageUrl).toList();
if (additionalImages.isNotEmpty) {
data['foto_aset_tambahan'] = additionalImages;
}
}
// Add rental time units if they exist
if (satuanWaktuSewa.isNotEmpty) {
data['satuan_waktu_sewa'] = satuanWaktuSewa.toList();
}
return data;
}
}

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer' as developer;
class PaketModel {
final String id;
@ -6,12 +7,13 @@ class PaketModel {
final String deskripsi;
final double harga;
final int kuantitas;
final List<String> foto;
final List<Map<String, dynamic>> satuanWaktuSewa;
final String status;
List<String> foto;
List<Map<String, dynamic>> satuanWaktuSewa;
final DateTime createdAt;
final DateTime updatedAt;
final String? foto_paket; // Main photo URL
final List<String>? images; // List of photo URLs
String? foto_paket; // Main photo URL
List<String>? images; // List of photo URLs
PaketModel({
required this.id,
@ -19,13 +21,47 @@ class PaketModel {
required this.deskripsi,
required this.harga,
required this.kuantitas,
required this.foto,
required this.satuanWaktuSewa,
this.status = 'aktif',
required List<String> foto,
required List<Map<String, dynamic>> satuanWaktuSewa,
this.foto_paket,
this.images,
List<String>? images,
required this.createdAt,
required this.updatedAt,
});
}) : foto = List.from(foto),
satuanWaktuSewa = List.from(satuanWaktuSewa),
images = images != null ? List.from(images) : [];
// Add copyWith method for immutability patterns
PaketModel copyWith({
String? id,
String? nama,
String? deskripsi,
double? harga,
int? kuantitas,
String? status,
List<String>? foto,
List<Map<String, dynamic>>? satuanWaktuSewa,
String? foto_paket,
List<String>? images,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return PaketModel(
id: id ?? this.id,
nama: nama ?? this.nama,
deskripsi: deskripsi ?? this.deskripsi,
harga: harga ?? this.harga,
kuantitas: kuantitas ?? this.kuantitas,
status: status ?? this.status,
foto: foto ?? List.from(this.foto),
satuanWaktuSewa: satuanWaktuSewa ?? List.from(this.satuanWaktuSewa),
foto_paket: foto_paket ?? this.foto_paket,
images: images ?? (this.images != null ? List.from(this.images!) : null),
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
// Alias for fromJson to maintain compatibility
factory PaketModel.fromMap(Map<String, dynamic> json) => PaketModel.fromJson(json);
@ -63,10 +99,15 @@ class PaketModel {
}
}
developer.log('📦 [PaketModel.fromJson] Raw status: ${json['status']} (type: ${json['status']?.runtimeType})');
final status = json['status']?.toString().toLowerCase() ?? 'aktif';
developer.log(' 🏷️ Processed status: $status');
return PaketModel(
id: json['id']?.toString() ?? '',
nama: json['nama']?.toString() ?? '',
deskripsi: json['deskripsi']?.toString() ?? '',
status: status,
harga: (json['harga'] is num) ? (json['harga'] as num).toDouble() : 0.0,
kuantitas: (json['kuantitas'] is num) ? (json['kuantitas'] as num).toInt() : 1,
foto: fotoList,
@ -97,35 +138,7 @@ class PaketModel {
'updated_at': updatedAt.toIso8601String(),
};
// Create a copy of the model with some fields updated
PaketModel copyWith({
String? id,
String? nama,
String? deskripsi,
double? harga,
int? kuantitas,
List<String>? foto,
List<Map<String, dynamic>>? satuanWaktuSewa,
String? foto_paket,
List<String>? images,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return PaketModel(
id: id ?? this.id,
nama: nama ?? this.nama,
deskripsi: deskripsi ?? this.deskripsi,
harga: harga ?? this.harga,
kuantitas: kuantitas ?? this.kuantitas,
foto: foto ?? List.from(this.foto),
satuanWaktuSewa: satuanWaktuSewa ?? List.from(this.satuanWaktuSewa),
foto_paket: foto_paket ?? this.foto_paket,
images: images ?? (this.images != null ? List.from(this.images!) : null),
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
// Get the first photo URL or a placeholder
String get firstPhotoUrl => foto.isNotEmpty ? foto.first : '';

View File

@ -0,0 +1,22 @@
class PembayaranModel {
final String id;
final int totalPembayaran;
final String metodePembayaran;
final DateTime waktuPembayaran;
PembayaranModel({
required this.id,
required this.totalPembayaran,
required this.metodePembayaran,
required this.waktuPembayaran,
});
factory PembayaranModel.fromJson(Map<String, dynamic> json) {
return PembayaranModel(
id: json['id'] as String,
totalPembayaran: json['total_pembayaran'] as int,
metodePembayaran: json['metode_pembayaran'] as String,
waktuPembayaran: DateTime.parse(json['waktu_pembayaran'] as String),
);
}
}

View File

@ -1 +1,95 @@
class SewaModel {
final String id;
final String userId;
final String status;
final DateTime waktuMulai;
final DateTime waktuSelesai;
final DateTime tanggalPemesanan;
final String tipePesanan;
final int kuantitas;
// Untuk tunggal
final String? asetId;
final String? asetNama;
final String? asetFoto;
// Untuk paket
final String? paketId;
final String? paketNama;
final String? paketFoto;
// Tagihan
final double totalTagihan;
// Data warga
final String wargaNama;
final String wargaNoHp;
final String wargaAvatar;
final double? denda;
final double? dibayar;
final double? paidAmount;
SewaModel({
required this.id,
required this.userId,
required this.status,
required this.waktuMulai,
required this.waktuSelesai,
required this.tanggalPemesanan,
required this.tipePesanan,
required this.kuantitas,
this.asetId,
this.asetNama,
this.asetFoto,
this.paketId,
this.paketNama,
this.paketFoto,
required this.totalTagihan,
required this.wargaNama,
required this.wargaNoHp,
required this.wargaAvatar,
this.denda,
this.dibayar,
this.paidAmount,
});
factory SewaModel.fromJson(Map<String, dynamic> json) {
return SewaModel(
id: json['id'] ?? '',
userId: json['user_id'] ?? '',
status: json['status'] ?? '',
waktuMulai: DateTime.parse(
json['waktu_mulai'] ?? DateTime.now().toIso8601String(),
),
waktuSelesai: DateTime.parse(
json['waktu_selesai'] ?? DateTime.now().toIso8601String(),
),
tanggalPemesanan: DateTime.parse(
json['tanggal_pemesanan'] ?? DateTime.now().toIso8601String(),
),
tipePesanan: json['tipe_pesanan'] ?? '',
kuantitas: json['kuantitas'] ?? 1,
asetId: json['aset_id'],
asetNama: json['aset_nama'],
asetFoto: json['aset_foto'],
paketId: json['paket_id'],
paketNama: json['paket_nama'],
paketFoto: json['paket_foto'],
totalTagihan:
(json['total_tagihan'] is num)
? json['total_tagihan'].toDouble()
: double.tryParse(json['total_tagihan']?.toString() ?? '0') ?? 0,
wargaNama: json['warga_nama'] ?? '',
wargaNoHp: json['warga_no_hp'] ?? '',
wargaAvatar: json['warga_avatar'] ?? '',
denda:
(json['denda'] is num)
? json['denda'].toDouble()
: double.tryParse(json['denda']?.toString() ?? '0'),
dibayar:
(json['dibayar'] is num)
? json['dibayar'].toDouble()
: double.tryParse(json['dibayar']?.toString() ?? '0'),
paidAmount:
(json['paid_amount'] is num)
? json['paid_amount'].toDouble()
: double.tryParse(json['paid_amount']?.toString() ?? '0'),
);
}
}