142 lines
4.6 KiB
Dart
142 lines
4.6 KiB
Dart
import 'package:wisata_app/config/api_config.dart';
|
|
|
|
class Destination {
|
|
final String id;
|
|
final String title;
|
|
final String category;
|
|
final String location;
|
|
final String imagePath;
|
|
final double rating;
|
|
final String distance;
|
|
final String elevation;
|
|
final String tiketParkir;
|
|
final String jamOperasional;
|
|
final String shortDescription;
|
|
final String overview;
|
|
final String modelPath;
|
|
final String arDescription;
|
|
final double? latitude;
|
|
final double? longitude;
|
|
final bool isVideo;
|
|
final String videoPath;
|
|
|
|
const Destination({
|
|
required this.id,
|
|
required this.title,
|
|
required this.category,
|
|
required this.location,
|
|
required this.imagePath,
|
|
required this.rating,
|
|
required this.distance,
|
|
required this.elevation,
|
|
required this.tiketParkir,
|
|
required this.jamOperasional,
|
|
required this.shortDescription,
|
|
required this.overview,
|
|
required this.modelPath,
|
|
required this.arDescription,
|
|
required this.latitude,
|
|
required this.longitude,
|
|
required this.isVideo,
|
|
required this.videoPath,
|
|
});
|
|
|
|
factory Destination.fromJson(Map<String, dynamic> json) {
|
|
final categoryValue = json['category'];
|
|
final categoryName = categoryValue is Map<String, dynamic>
|
|
? _string(categoryValue['name'])
|
|
: _string(categoryValue);
|
|
final shortDescription = _string(
|
|
json['short_description'] ?? json['description'] ?? json['deskripsi'],
|
|
);
|
|
final overview = _string(
|
|
json['overview'] ??
|
|
json['deskripsi_lengkap'] ??
|
|
json['deskripsiLengkap'] ??
|
|
shortDescription,
|
|
);
|
|
|
|
return Destination(
|
|
id: _string(json['id']),
|
|
title: _string(json['title'] ?? json['nama_wisata'] ?? json['nama']),
|
|
category: _string(json['category_name'] ?? categoryName),
|
|
location: _string(json['location'] ?? json['lokasi']),
|
|
imagePath: _resolveFileUrl(json['image_url'] ?? json['image']),
|
|
rating: _double(json['rating']),
|
|
distance: _string(json['distance'] ?? json['jarak']),
|
|
elevation: _string(json['elevation'] ?? json['ketinggian']),
|
|
tiketParkir: _string(json['tiket_parkir'] ?? json['tiketParkir']),
|
|
jamOperasional:
|
|
_string(json['jam_operasional'] ?? json['jamOperasional']),
|
|
shortDescription: shortDescription,
|
|
overview: overview,
|
|
modelPath: _resolveFileUrl(
|
|
json['model_url'] ?? json['model_glb'] ?? json['model_path'],
|
|
),
|
|
arDescription: _string(json['ar_description'] ?? overview),
|
|
latitude: _nullableDouble(json['latitude']),
|
|
longitude: _nullableDouble(json['longitude']),
|
|
isVideo: _bool(json['is_video']),
|
|
videoPath: _resolveFileUrl(json['video_url'] ?? json['video_path']),
|
|
);
|
|
}
|
|
|
|
String get nama => title;
|
|
String get deskripsi => shortDescription;
|
|
String get kategori => category;
|
|
String get gambar => imagePath;
|
|
String get deskripsiLengkap => overview;
|
|
String get lokasi => location;
|
|
String get alamat => location;
|
|
String get ketinggian => elevation.trim().isEmpty ? '-' : elevation;
|
|
|
|
String get displayLocation =>
|
|
location.trim().isEmpty ? 'Lumajang, Jawa Timur' : location;
|
|
|
|
bool get hasCoordinates => latitude != null && longitude != null;
|
|
|
|
static String _string(Object? value) => value?.toString().trim() ?? '';
|
|
|
|
static double _double(Object? value) => _nullableDouble(value) ?? 0;
|
|
|
|
static double? _nullableDouble(Object? value) {
|
|
if (value == null) return null;
|
|
if (value is num) return value.toDouble();
|
|
return double.tryParse(value.toString());
|
|
}
|
|
|
|
static bool _bool(Object? value) {
|
|
if (value is bool) return value;
|
|
if (value is num) return value != 0;
|
|
final normalized = value?.toString().toLowerCase().trim();
|
|
return normalized == 'true' || normalized == '1' || normalized == 'yes';
|
|
}
|
|
|
|
static String _resolveFileUrl(Object? value) {
|
|
final path = _string(value).replaceAll('\\', '/');
|
|
if (path.isEmpty ||
|
|
path.startsWith('http://') ||
|
|
path.startsWith('https://')) {
|
|
return ApiConfig.normalizeBackendUrl(path);
|
|
}
|
|
|
|
if (path.startsWith('storage/')) {
|
|
return '${ApiConfig.storageUrl}${path.replaceFirst('storage/', '')}';
|
|
}
|
|
|
|
if (path.startsWith('assets/images/')) {
|
|
return '${ApiConfig.storageUrl}wisata/${path.replaceFirst('assets/images/', '')}';
|
|
}
|
|
|
|
if (path.startsWith('assets/models/')) {
|
|
return '${ApiConfig.storageUrl}models/${path.replaceFirst('assets/models/', '')}';
|
|
}
|
|
|
|
if (path.startsWith('assets/videos/')) {
|
|
return '${ApiConfig.storageUrl}videos/${path.replaceFirst('assets/videos/', '')}';
|
|
}
|
|
|
|
return '${ApiConfig.storageUrl}$path';
|
|
}
|
|
}
|