188 lines
5.8 KiB
Dart
188 lines
5.8 KiB
Dart
// lib/data/models/offer_model.dart
|
|
|
|
import 'package:equatable/equatable.dart';
|
|
import 'package:proxibuy/data/models/comment_model.dart';
|
|
import 'package:proxibuy/data/models/discount_info_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 DiscountInfoModel? discountInfo;
|
|
final List<CommentModel> comments;
|
|
final String qrCodeData;
|
|
|
|
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 [],
|
|
this.discountInfo,
|
|
this.comments = const [],
|
|
required this.qrCodeData,
|
|
});
|
|
|
|
factory OfferModel.fromJson(Map<String, dynamic> json) { // <-- پارامتر calculatedDistance حذف شد
|
|
final shopData = ShopData.fromJson(json['shopData']);
|
|
|
|
final now = DateTime.now();
|
|
bool checkIsOpen = false;
|
|
try {
|
|
final startTimeParts = (json['StartTime'] as String).split(':');
|
|
final endTimeParts = (json['EndTime'] as String).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;
|
|
|
|
// **رفع خطا: تبدیل امن عدد فاصله به int**
|
|
final distanceFromServer = (json['distance'] as num?)?.round() ?? 0;
|
|
|
|
|
|
return OfferModel(
|
|
id: json['ID'] ?? '',
|
|
title: json['Name'] ?? 'بدون عنوان',
|
|
discount: json['Description'] ?? '',
|
|
imageUrls: (json['Images'] as List<dynamic>?)
|
|
?.map((imgId) => "$imgId")
|
|
.toList() ?? [],
|
|
category: json['shopData']['Category']?.toString() ?? 'بدون دستهبندی',
|
|
expiryTime: DateTime.tryParse(json['EndDate'] ?? '') ?? DateTime.now().add(const Duration(days: 1)),
|
|
discountType: json['Type']?.toString() ?? '',
|
|
originalPrice: originalPriceValue,
|
|
finalPrice: finalPriceValue,
|
|
qrCodeData: json['QRcode'] ?? '',
|
|
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: null,
|
|
);
|
|
}
|
|
|
|
|
|
OfferModel copyWith() {
|
|
return OfferModel(
|
|
id: id,
|
|
storeName: storeName,
|
|
title: title,
|
|
discount: discount,
|
|
imageUrls: imageUrls,
|
|
category: category,
|
|
distanceInMeters: distanceInMeters,
|
|
expiryTime: expiryTime,
|
|
address: address,
|
|
workingHours: workingHours,
|
|
discountType: discountType,
|
|
isOpen: isOpen,
|
|
rating: rating,
|
|
ratingCount: ratingCount,
|
|
latitude: latitude,
|
|
longitude: longitude,
|
|
originalPrice: originalPrice,
|
|
finalPrice: finalPrice,
|
|
features: features,
|
|
discountInfo: discountInfo,
|
|
comments: comments,
|
|
qrCodeData: qrCodeData,
|
|
);
|
|
}
|
|
|
|
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 کیلومتر";
|
|
}
|
|
}
|
|
} |