fix(mobile): use full absolute foto_url from API for Kontrakan and Laundry
This commit is contained in:
parent
f197bfaccb
commit
5f54fe7db9
|
|
@ -12,6 +12,7 @@ class Kontrakan {
|
||||||
final String status;
|
final String status;
|
||||||
final String? fotoUtama;
|
final String? fotoUtama;
|
||||||
final String? foto;
|
final String? foto;
|
||||||
|
final String? fotoUrl; // Full absolute URL dari API (foto_url)
|
||||||
final String? noWhatsapp;
|
final String? noWhatsapp;
|
||||||
final List<Galeri> galeri;
|
final List<Galeri> galeri;
|
||||||
final double? avgRating;
|
final double? avgRating;
|
||||||
|
|
@ -31,6 +32,7 @@ class Kontrakan {
|
||||||
required this.status,
|
required this.status,
|
||||||
this.fotoUtama,
|
this.fotoUtama,
|
||||||
this.foto,
|
this.foto,
|
||||||
|
this.fotoUrl,
|
||||||
this.noWhatsapp,
|
this.noWhatsapp,
|
||||||
this.galeri = const [],
|
this.galeri = const [],
|
||||||
this.avgRating,
|
this.avgRating,
|
||||||
|
|
@ -81,6 +83,7 @@ class Kontrakan {
|
||||||
status: json['status'] ?? 'tersedia',
|
status: json['status'] ?? 'tersedia',
|
||||||
fotoUtama: json['foto_utama'],
|
fotoUtama: json['foto_utama'],
|
||||||
foto: json['foto'],
|
foto: json['foto'],
|
||||||
|
fotoUrl: json['foto_url'], // Full URL dari API (SAW response)
|
||||||
noWhatsapp: json['no_whatsapp'],
|
noWhatsapp: json['no_whatsapp'],
|
||||||
galeri: galleryList,
|
galeri: galleryList,
|
||||||
avgRating: json['avg_rating'] != null
|
avgRating: json['avg_rating'] != null
|
||||||
|
|
@ -113,6 +116,12 @@ class Kontrakan {
|
||||||
}
|
}
|
||||||
|
|
||||||
String get primaryPhoto {
|
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) {
|
if (foto != null && foto!.isNotEmpty) {
|
||||||
return _resolveKontrakanPhotoPath(foto!);
|
return _resolveKontrakanPhotoPath(foto!);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class Laundry {
|
||||||
final String? deskripsi;
|
final String? deskripsi;
|
||||||
final String? fotoUtama;
|
final String? fotoUtama;
|
||||||
final String? foto; // Field foto dari API
|
final String? foto; // Field foto dari API
|
||||||
|
final String? fotoUrl; // Full absolute URL dari API (foto_url)
|
||||||
final List<GaleriLaundry> galeri;
|
final List<GaleriLaundry> galeri;
|
||||||
final double? avgRating;
|
final double? avgRating;
|
||||||
final int? totalReviews;
|
final int? totalReviews;
|
||||||
|
|
@ -37,6 +38,7 @@ class Laundry {
|
||||||
this.deskripsi,
|
this.deskripsi,
|
||||||
this.fotoUtama,
|
this.fotoUtama,
|
||||||
this.foto,
|
this.foto,
|
||||||
|
this.fotoUrl,
|
||||||
this.galeri = const [],
|
this.galeri = const [],
|
||||||
this.avgRating,
|
this.avgRating,
|
||||||
this.totalReviews,
|
this.totalReviews,
|
||||||
|
|
@ -126,6 +128,7 @@ class Laundry {
|
||||||
deskripsi: json['deskripsi'],
|
deskripsi: json['deskripsi'],
|
||||||
fotoUtama: json['foto_utama'],
|
fotoUtama: json['foto_utama'],
|
||||||
foto: json['foto'], // Store raw foto field
|
foto: json['foto'], // Store raw foto field
|
||||||
|
fotoUrl: json['foto_url'], // Full URL dari API
|
||||||
galeri: galleryList,
|
galeri: galleryList,
|
||||||
avgRating: json['avg_rating'] != null
|
avgRating: json['avg_rating'] != null
|
||||||
? double.tryParse(json['avg_rating'].toString())
|
? double.tryParse(json['avg_rating'].toString())
|
||||||
|
|
@ -157,17 +160,20 @@ class Laundry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get primary photo URL
|
// Get primary photo URL
|
||||||
// Prioritize 'foto' field (Admin-set primary photo) over galeri entries,
|
// Priority: foto_url (full URL from API) > foto field > galeri
|
||||||
// because galeri items may reference files that have been deleted/replaced.
|
|
||||||
String get primaryPhoto {
|
String get primaryPhoto {
|
||||||
// 1. Prefer the explicit 'foto' field (most up-to-date primary photo)
|
// 1. Gunakan foto_url dari API jika sudah full URL (paling akurat)
|
||||||
|
if (fotoUrl != null && fotoUrl!.isNotEmpty) {
|
||||||
|
return fotoUrl!;
|
||||||
|
}
|
||||||
|
// 2. Construct URL dari nama file foto
|
||||||
if (foto != null && foto!.isNotEmpty) {
|
if (foto != null && foto!.isNotEmpty) {
|
||||||
if (foto!.startsWith('http')) {
|
if (foto!.startsWith('http')) {
|
||||||
return foto!;
|
return foto!;
|
||||||
}
|
}
|
||||||
return '${AppConfig.serverUrl}/uploads/Laundry/$foto';
|
return '${AppConfig.serverUrl}/uploads/Laundry/$foto';
|
||||||
}
|
}
|
||||||
// 2. Fall back to galeri items if foto is not set
|
// 3. Fall back to galeri items if foto is not set
|
||||||
if (galeri.isNotEmpty) {
|
if (galeri.isNotEmpty) {
|
||||||
final primary = galeri.firstWhere(
|
final primary = galeri.firstWhere(
|
||||||
(g) => g.isPrimary,
|
(g) => g.isPrimary,
|
||||||
|
|
@ -180,8 +186,6 @@ class Laundry {
|
||||||
return primary.photoUrl;
|
return primary.photoUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return empty string when no photo available to avoid unnecessary
|
|
||||||
// network requests to placeholder services (prevents TLS/handshake errors)
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue