You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
5.5 KiB

import 'dart:convert';
/// Represents a recipe with metadata.
class RecipeModel {
/// Unique identifier for the recipe.
final String id;
/// Recipe title.
final String title;
/// Recipe description.
final String? description;
/// List of tags.
final List<String> tags;
/// Rating (0-5).
final int rating;
/// Whether the recipe is marked as favourite.
final bool isFavourite;
/// List of image URLs (from Immich/Blossom).
final List<String> imageUrls;
/// List of video URLs (from Blossom).
final List<String> videoUrls;
/// Timestamp when recipe was created (milliseconds since epoch).
final int createdAt;
/// Timestamp when recipe was last updated (milliseconds since epoch).
final int updatedAt;
/// Whether the recipe has been deleted.
final bool isDeleted;
/// Nostr event ID if synced to Nostr.
final String? nostrEventId;
/// Creates a [RecipeModel] instance.
RecipeModel({
required this.id,
required this.title,
this.description,
List<String>? tags,
this.rating = 0,
this.isFavourite = false,
List<String>? imageUrls,
List<String>? videoUrls,
int? createdAt,
int? updatedAt,
this.isDeleted = false,
this.nostrEventId,
}) : tags = tags ?? [],
imageUrls = imageUrls ?? [],
videoUrls = videoUrls ?? [],
createdAt = createdAt ?? DateTime.now().millisecondsSinceEpoch,
updatedAt = updatedAt ?? DateTime.now().millisecondsSinceEpoch;
/// Creates a [RecipeModel] from a database row (Map).
factory RecipeModel.fromMap(Map<String, dynamic> map) {
return RecipeModel(
id: map['id'] as String,
title: map['title'] as String,
description: map['description'] as String?,
tags: map['tags'] != null
? (jsonDecode(map['tags'] as String) as List<dynamic>)
.map((e) => e.toString())
.toList()
: [],
rating: map['rating'] as int? ?? 0,
isFavourite: (map['is_favourite'] as int? ?? 0) == 1,
imageUrls: map['image_urls'] != null
? (jsonDecode(map['image_urls'] as String) as List<dynamic>)
.map((e) => e.toString())
.toList()
: [],
videoUrls: map['video_urls'] != null
? (jsonDecode(map['video_urls'] as String) as List<dynamic>)
.map((e) => e.toString())
.toList()
: [],
createdAt: map['created_at'] as int,
updatedAt: map['updated_at'] as int,
isDeleted: (map['is_deleted'] as int? ?? 0) == 1,
nostrEventId: map['nostr_event_id'] as String?,
);
}
/// Converts the [RecipeModel] to a Map for database storage.
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
'description': description,
'tags': jsonEncode(tags),
'rating': rating,
'is_favourite': isFavourite ? 1 : 0,
'image_urls': jsonEncode(imageUrls),
'video_urls': jsonEncode(videoUrls),
'created_at': createdAt,
'updated_at': updatedAt,
'is_deleted': isDeleted ? 1 : 0,
'nostr_event_id': nostrEventId,
};
}
/// Creates a [RecipeModel] from JSON (for Nostr content).
factory RecipeModel.fromJson(Map<String, dynamic> json) {
return RecipeModel(
id: json['id'] as String,
title: json['title'] as String,
description: json['description'] as String?,
tags: (json['tags'] as List<dynamic>?)?.map((e) => e.toString()).toList() ?? [],
rating: json['rating'] as int? ?? 0,
isFavourite: json['isFavourite'] as bool? ?? false,
imageUrls: (json['imageUrls'] as List<dynamic>?)?.map((e) => e.toString()).toList() ?? [],
videoUrls: (json['videoUrls'] as List<dynamic>?)?.map((e) => e.toString()).toList() ?? [],
createdAt: json['createdAt'] as int? ?? DateTime.now().millisecondsSinceEpoch,
updatedAt: json['updatedAt'] as int? ?? DateTime.now().millisecondsSinceEpoch,
isDeleted: json['isDeleted'] as bool? ?? false,
nostrEventId: json['nostrEventId'] as String?,
);
}
/// Converts the [RecipeModel] to JSON (for Nostr content).
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
if (description != null) 'description': description,
'tags': tags,
'rating': rating,
'isFavourite': isFavourite,
'imageUrls': imageUrls,
'videoUrls': videoUrls,
'createdAt': createdAt,
'updatedAt': updatedAt,
'isDeleted': isDeleted,
if (nostrEventId != null) 'nostrEventId': nostrEventId,
};
}
/// Creates a copy of this [RecipeModel] with updated fields.
RecipeModel copyWith({
String? id,
String? title,
String? description,
List<String>? tags,
int? rating,
bool? isFavourite,
List<String>? imageUrls,
List<String>? videoUrls,
int? createdAt,
int? updatedAt,
bool? isDeleted,
String? nostrEventId,
}) {
return RecipeModel(
id: id ?? this.id,
title: title ?? this.title,
description: description ?? this.description,
tags: tags ?? this.tags,
rating: rating ?? this.rating,
isFavourite: isFavourite ?? this.isFavourite,
imageUrls: imageUrls ?? this.imageUrls,
videoUrls: videoUrls ?? this.videoUrls,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
isDeleted: isDeleted ?? this.isDeleted,
nostrEventId: nostrEventId ?? this.nostrEventId,
);
}
@override
String toString() {
return 'RecipeModel(id: $id, title: $title, tags: ${tags.length}, rating: $rating, favourite: $isFavourite)';
}
}

Powered by TurnKey Linux.