import '../config/app_config.dart'; class Kontrakan { final int id; final String nama; final String alamat; final double harga; final int jumlahKamar; final double jarakKampus; final String fasilitas; final String? deskripsi; final String status; final String? fotoUtama; final String? foto; final String? fotoUrl; // Full absolute URL dari API (foto_url) final String? noWhatsapp; final List galeri; final double? avgRating; final int? totalReviews; final double? latitude; final double? longitude; Kontrakan({ required this.id, required this.nama, required this.alamat, required this.harga, required this.jumlahKamar, required this.jarakKampus, required this.fasilitas, this.deskripsi, required this.status, this.fotoUtama, this.foto, this.fotoUrl, this.noWhatsapp, this.galeri = const [], this.avgRating, this.totalReviews, this.latitude, this.longitude, }); factory Kontrakan.fromJson(Map json) { double jarak = 0; if (json['jarak_kampus'] != null) { jarak = double.tryParse(json['jarak_kampus'].toString()) ?? 0; } else if (json['jarak'] != null) { jarak = (double.tryParse(json['jarak'].toString()) ?? 0) / 1000; } final List galleryList = []; if (json['galeri'] != null && (json['galeri'] as List).isNotEmpty) { galleryList.addAll( (json['galeri'] as List).map((g) => Galeri.fromJson(g)).toList(), ); } if (galleryList.isEmpty && json['foto'] != null && json['foto'].toString().isNotEmpty) { final resolved = json['foto_url'] != null && json['foto_url'].toString().isNotEmpty ? json['foto_url'].toString() : _resolveKontrakanPhotoPath(json['foto'].toString()); galleryList.add( Galeri( id: json['id'] ?? 0, foto: resolved, isPrimary: true, urutan: 0, ), ); } return Kontrakan( id: json['id'] ?? 0, nama: json['nama'] ?? '', alamat: json['alamat'] ?? '', harga: double.tryParse(json['harga']?.toString() ?? '0') ?? 0, jumlahKamar: json['jumlah_kamar'] ?? 0, jarakKampus: jarak, fasilitas: json['fasilitas'] ?? '', deskripsi: json['deskripsi'], status: json['status'] ?? 'tersedia', fotoUtama: json['foto_utama'], foto: json['foto'], fotoUrl: json['foto_url'], // Full URL dari API (SAW response) noWhatsapp: json['no_whatsapp'], galeri: galleryList, avgRating: json['avg_rating'] != null ? double.tryParse(json['avg_rating'].toString()) : null, totalReviews: json['total_reviews'], latitude: json['latitude'] != null ? double.tryParse(json['latitude'].toString()) : null, longitude: json['longitude'] != null ? double.tryParse(json['longitude'].toString()) : null, ); } bool get isAvailable => status == 'available' || status == 'tersedia'; bool get hasPhoto { bool isValidUrl(String? url) { if (url == null || url.isEmpty) return false; final lower = url.toLowerCase(); if (lower.contains('via.placeholder.com')) return false; return true; } if (isValidUrl(foto)) return true; if (galeri.any((g) => isValidUrl(g.foto))) return true; return false; } String get primaryPhoto { // 1. Gunakan foto_url dari API jika sudah full URL (paling akurat, tidak perlu tebak folder) if (fotoUrl != null && fotoUrl!.isNotEmpty) { return fotoUrl!; } // 2. Construct URL dari nama file foto if (foto != null && foto!.isNotEmpty) { return _resolveKontrakanPhotoPath(foto!); } if (fotoUtama != null && fotoUtama!.isNotEmpty) { return _resolveKontrakanPhotoPath(fotoUtama!); } if (galeri.isNotEmpty) { final primary = galeri.firstWhere( (g) => g.isPrimary, orElse: () => galeri.first, ); if (primary.foto.isNotEmpty) { return primary.photoUrl; } } return ''; } static String _resolveKontrakanPhotoPath(String path) { if (path.startsWith('http')) { return path; } if (path.startsWith('uploads/')) { return '${AppConfig.serverUrl}/$path'; } return '${AppConfig.serverUrl}/uploads/kontrakan/$path'; } String get formattedHarga { return 'Rp ${harga.toStringAsFixed(0).replaceAllMapped(RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]}.')}'; } List get fasilitasList { return fasilitas.split(',').map((f) => f.trim()).toList(); } } class Galeri { final int id; final String foto; final bool isPrimary; final int urutan; Galeri({ required this.id, required this.foto, required this.isPrimary, required this.urutan, }); factory Galeri.fromJson(Map json) { return Galeri( id: json['id'] ?? 0, foto: json['foto'] ?? '', isPrimary: json['is_primary'] == 1 || json['is_primary'] == true, urutan: json['urutan'] ?? 0, ); } String get photoUrl { if (foto.isEmpty) return ''; if (foto.startsWith('http')) { return foto; } if (foto.startsWith('uploads/')) { return '${AppConfig.serverUrl}/$foto'; } return '${AppConfig.serverUrl}/uploads/galeri/kontrakan/$foto'; } }