173 lines
5.9 KiB
Dart
173 lines
5.9 KiB
Dart
import 'package:equatable/equatable.dart';
|
||
import 'package:proxibuy/data/models/comment_model.dart';
|
||
import 'package:proxibuy/data/models/working_hours.dart';
|
||
|
||
class ShopData {
|
||
final String id;
|
||
final String name;
|
||
final String category;
|
||
final String address;
|
||
final double latitude;
|
||
final double longitude;
|
||
final List<String> properties;
|
||
|
||
const ShopData({
|
||
required this.id,
|
||
required this.name,
|
||
required this.category,
|
||
required this.address,
|
||
required this.latitude,
|
||
required this.longitude,
|
||
required this.properties,
|
||
});
|
||
|
||
factory ShopData.fromJson(Map<String, dynamic> json) {
|
||
return ShopData(
|
||
id: json['_id'] ?? '',
|
||
name: json['Name'] ?? 'نام فروشگاه نامشخص',
|
||
category: json['Category'] ?? 'بدون دستهبندی',
|
||
address: json['Address'] ?? 'آدرس نامشخص',
|
||
latitude: (json['Map']?['coordinates']?[1] as num?)?.toDouble() ?? 0.0,
|
||
longitude: (json['Map']?['coordinates']?[0] as num?)?.toDouble() ?? 0.0,
|
||
properties: List<String>.from(json['Property'] ?? []),
|
||
);
|
||
}
|
||
}
|
||
|
||
class OfferModel extends Equatable {
|
||
final String id;
|
||
final String storeName;
|
||
final String title;
|
||
final String discount;
|
||
final List<String> imageUrls;
|
||
final String category;
|
||
final int distanceInMeters;
|
||
final DateTime expiryTime;
|
||
final String address;
|
||
final List<WorkingHours> workingHours;
|
||
final String discountType;
|
||
final bool isOpen;
|
||
final double rating;
|
||
final int ratingCount;
|
||
final double latitude;
|
||
final double longitude;
|
||
final double originalPrice;
|
||
final double finalPrice;
|
||
final List<String> features;
|
||
final String discountInfo;
|
||
final List<CommentModel> comments;
|
||
|
||
const OfferModel({
|
||
required this.id,
|
||
required this.storeName,
|
||
required this.title,
|
||
required this.discount,
|
||
required this.imageUrls,
|
||
required this.category,
|
||
required this.distanceInMeters,
|
||
required this.expiryTime,
|
||
required this.address,
|
||
required this.workingHours,
|
||
required this.discountType,
|
||
required this.isOpen,
|
||
required this.rating,
|
||
required this.ratingCount,
|
||
required this.latitude,
|
||
required this.longitude,
|
||
required this.originalPrice,
|
||
required this.finalPrice,
|
||
this.features = const [],
|
||
required this.discountInfo,
|
||
this.comments = const [],
|
||
});
|
||
|
||
factory OfferModel.fromJson(Map<String, dynamic> json) {
|
||
final shopDataJson = json['shopData'] as Map<String, dynamic>? ?? {};
|
||
final shopData = ShopData.fromJson(shopDataJson);
|
||
|
||
final now = DateTime.now();
|
||
bool checkIsOpen = false;
|
||
try {
|
||
final startTimeString = json['StartTime'] as String?;
|
||
final endTimeString = json['EndTime'] as String?;
|
||
if (startTimeString != null && endTimeString != null) {
|
||
final startTimeParts = startTimeString.split(':');
|
||
final endTimeParts = endTimeString.split(':');
|
||
final startHour = int.parse(startTimeParts[0]);
|
||
final startMinute = int.parse(startTimeParts[1]);
|
||
final endHour = int.parse(endTimeParts[0]);
|
||
final endMinute = int.parse(endTimeParts[1]);
|
||
|
||
final startTime = DateTime(now.year, now.month, now.day, startHour, startMinute);
|
||
final endTime = DateTime(now.year, now.month, now.day, endHour, endMinute);
|
||
|
||
checkIsOpen = now.isAfter(startTime) && now.isBefore(endTime);
|
||
}
|
||
} catch(e) {
|
||
checkIsOpen = false;
|
||
}
|
||
|
||
final originalPriceValue = (json['Price'] as num?)?.toDouble() ?? 0.0;
|
||
final finalPriceValue = (json['NPrice'] as num?)?.toDouble() ?? 0.0;
|
||
|
||
// ******** شروع تغییر ۱ ********
|
||
// مدیریت هوشمند فاصله و عکسها از منابع مختلف
|
||
final distanceFromServer = (json['distance'] as num?)?.round() ?? (json['Distance'] as num?)?.round() ?? 0;
|
||
|
||
List<String> images = [];
|
||
if (json['imageData'] is List) { // برای سازگاری با پاسخ MQTT
|
||
images = (json['imageData'] as List<dynamic>)
|
||
.map((imageData) => imageData['Url']?.toString() ?? '')
|
||
.where((url) => url.isNotEmpty)
|
||
.toList();
|
||
} else if (json['Images'] is List) { // برای پاسخ جدید API رزرو
|
||
images = (json['Images'] as List<dynamic>)
|
||
.map((imageData) => (imageData is Map) ? imageData['Url']?.toString() ?? '' : '')
|
||
.where((url) => url.isNotEmpty)
|
||
.toList();
|
||
}
|
||
|
||
final typeData = json['typeData'] ?? json['Type'];
|
||
final discountTypeName = (typeData is Map) ? typeData['Name']?.toString() : typeData?.toString();
|
||
// ******** پایان تغییر ۱ ********
|
||
|
||
return OfferModel(
|
||
id: json['ID'] ?? '',
|
||
title: json['Name'] ?? 'بدون عنوان',
|
||
discount: json['Description'] ?? '',
|
||
imageUrls: images, // <-- استفاده از لیست جدید
|
||
category: json['categoryData']?['Name']?.toString() ?? '',
|
||
expiryTime: DateTime.tryParse(json['EndDate'] ?? '') ?? DateTime.now().add(const Duration(days: 1)),
|
||
discountType: discountTypeName ?? '',
|
||
originalPrice: originalPriceValue,
|
||
finalPrice: finalPriceValue,
|
||
storeName: shopData.name,
|
||
address: shopData.address,
|
||
latitude: shopData.latitude,
|
||
longitude: shopData.longitude,
|
||
features: shopData.properties,
|
||
distanceInMeters: distanceFromServer, // <-- استفاده از متغیر جدید
|
||
isOpen: checkIsOpen,
|
||
workingHours: [],
|
||
rating: 0.0,
|
||
ratingCount: 0,
|
||
comments: [],
|
||
discountInfo: json['Description'],
|
||
);
|
||
}
|
||
|
||
String get coverImageUrl =>
|
||
imageUrls.isNotEmpty ? imageUrls.first : 'https://via.placeholder.com/400x200.png?text=No+Image';
|
||
|
||
@override
|
||
List<Object?> get props => [id];
|
||
|
||
String get distanceAsString {
|
||
if (distanceInMeters < 1000) {
|
||
return "$distanceInMeters متر";
|
||
} else {
|
||
final distanceInKm = (distanceInMeters / 1000).toStringAsFixed(1);
|
||
return "$distanceInKm کیلومتر";
|
||
}
|
||
}
|
||
} |