amoriai/lib/models/recommendation_model.dart

270 lines
6.8 KiB
Dart

import 'package:hive/hive.dart';
import 'menu_model.dart';
part 'recommendation_model.g.dart';
@HiveType(typeId: 3)
class RecommendationModel extends HiveObject {
@HiveField(0)
String id;
@HiveField(1)
String userId;
@HiveField(2)
List<MenuRecommendation> recommendations;
@HiveField(3)
String originalMenuText;
@HiveField(4)
String? menuImageUrl;
@HiveField(5)
String prompt;
@HiveField(6)
String aiResponse;
@HiveField(7)
double confidence;
@HiveField(8)
DateTime createdAt;
@HiveField(9)
bool isFavorite;
@HiveField(10)
String sessionId;
@HiveField(11)
String? selectedMenuName;
@HiveField(12)
List<String>? menuImagePaths;
RecommendationModel({
required this.id,
required this.userId,
required this.recommendations,
required this.originalMenuText,
this.menuImageUrl,
this.menuImagePaths,
required this.prompt,
required this.aiResponse,
this.confidence = 0.0,
required this.createdAt,
this.isFavorite = false,
required this.sessionId,
this.selectedMenuName,
});
factory RecommendationModel.fromJson(Map<String, dynamic> json) {
return RecommendationModel(
id: json['id'] as String,
userId: json['userId'] as String,
recommendations: (json['recommendations'] as List)
.map((e) => MenuRecommendation.fromJson(e as Map<String, dynamic>))
.toList(),
originalMenuText: json['originalMenuText'] as String,
menuImageUrl: json['menuImageUrl'] as String?,
menuImagePaths: (json['menuImagePaths'] as List<dynamic>?)
?.map((e) => e as String)
.toList(),
prompt: json['prompt'] as String,
aiResponse: json['aiResponse'] as String,
confidence: (json['confidence'] as num?)?.toDouble() ?? 0.0,
createdAt: DateTime.parse(json['createdAt'] as String),
isFavorite: json['isFavorite'] as bool? ?? false,
sessionId: json['sessionId'] as String,
selectedMenuName: json['selectedMenuName'] as String?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'userId': userId,
'recommendations': recommendations.map((e) => e.toJson()).toList(),
'originalMenuText': originalMenuText,
'menuImageUrl': menuImageUrl,
'menuImagePaths': menuImagePaths,
'prompt': prompt,
'aiResponse': aiResponse,
'confidence': confidence,
'createdAt': createdAt.toIso8601String(),
'isFavorite': isFavorite,
'sessionId': sessionId,
'selectedMenuName': selectedMenuName,
};
}
RecommendationModel copyWith({
String? id,
String? userId,
List<MenuRecommendation>? recommendations,
String? originalMenuText,
String? menuImageUrl,
List<String>? menuImagePaths,
String? prompt,
String? aiResponse,
double? confidence,
DateTime? createdAt,
bool? isFavorite,
String? sessionId,
String? selectedMenuName,
}) {
return RecommendationModel(
id: id ?? this.id,
userId: userId ?? this.userId,
recommendations: recommendations ?? this.recommendations,
originalMenuText: originalMenuText ?? this.originalMenuText,
menuImageUrl: menuImageUrl ?? this.menuImageUrl,
menuImagePaths: menuImagePaths ?? this.menuImagePaths,
prompt: prompt ?? this.prompt,
aiResponse: aiResponse ?? this.aiResponse,
confidence: confidence ?? this.confidence,
createdAt: createdAt ?? this.createdAt,
isFavorite: isFavorite ?? this.isFavorite,
sessionId: sessionId ?? this.sessionId,
selectedMenuName: selectedMenuName ?? this.selectedMenuName,
);
}
List<MenuRecommendation> get topRecommendations {
final sorted = List<MenuRecommendation>.from(recommendations);
sorted.sort((a, b) => b.score.compareTo(a.score));
return sorted.take(3).toList();
}
String get formattedDate {
final now = DateTime.now();
final difference = now.difference(createdAt);
if (difference.inDays > 0) {
return '${difference.inDays} hari yang lalu';
} else if (difference.inHours > 0) {
return '${difference.inHours} jam yang lalu';
} else if (difference.inMinutes > 0) {
return '${difference.inMinutes} menit yang lalu';
} else {
return 'Baru saja';
}
}
}
@HiveType(typeId: 4)
class MenuRecommendation extends HiveObject {
@HiveField(0)
String menuName;
@HiveField(1)
String description;
@HiveField(2)
double price;
@HiveField(3)
String reason;
@HiveField(4)
double score;
@HiveField(5)
List<String> tags;
@HiveField(6)
String category;
@HiveField(7)
String? imageUrl;
@HiveField(8)
bool isRecommended;
@HiveField(9)
String? slotType;
MenuRecommendation({
required this.menuName,
required this.description,
required this.price,
required this.reason,
this.score = 0.0,
this.tags = const [],
required this.category,
this.imageUrl,
this.isRecommended = true,
this.slotType,
});
factory MenuRecommendation.fromJson(Map<String, dynamic> json) {
return MenuRecommendation(
menuName: json['menuName'] as String,
description: json['description'] as String,
price: (json['price'] as num).toDouble(),
reason: json['reason'] as String,
score: (json['score'] as num?)?.toDouble() ?? 0.0,
tags: List<String>.from(json['tags'] ?? []),
category: json['category'] as String,
imageUrl: json['imageUrl'] as String?,
isRecommended: json['isRecommended'] as bool? ?? true,
slotType: json['slotType'] as String?,
);
}
Map<String, dynamic> toJson() {
return {
'menuName': menuName,
'description': description,
'price': price,
'reason': reason,
'score': score,
'tags': tags,
'category': category,
'imageUrl': imageUrl,
'isRecommended': isRecommended,
'slotType': slotType,
};
}
MenuRecommendation copyWith({
String? menuName,
String? description,
double? price,
String? reason,
double? score,
List<String>? tags,
String? category,
String? imageUrl,
bool? isRecommended,
String? slotType,
}) {
return MenuRecommendation(
menuName: menuName ?? this.menuName,
description: description ?? this.description,
price: price ?? this.price,
reason: reason ?? this.reason,
score: score ?? this.score,
tags: tags ?? this.tags,
category: category ?? this.category,
imageUrl: imageUrl ?? this.imageUrl,
isRecommended: isRecommended ?? this.isRecommended,
slotType: slotType ?? this.slotType,
);
}
String get formattedPrice {
return 'Rp ${price.toStringAsFixed(0).replaceAllMapped(RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]}.')}';
}
int get starRating {
return (score * 5).round().clamp(1, 5);
}
String get scorePercentage {
return '${(score * 100).toStringAsFixed(0)}%';
}
}