215 lines
5.6 KiB
Dart
215 lines
5.6 KiB
Dart
/// Data Model: News Article Model
|
|
///
|
|
/// Data layer model for news articles.
|
|
/// Handles JSON serialization and conversion to/from domain entity.
|
|
library;
|
|
|
|
import 'package:worker/features/news/domain/entities/news_article.dart';
|
|
|
|
/// News Article Model
|
|
///
|
|
/// Used in the data layer for:
|
|
/// - JSON serialization/deserialization from API
|
|
/// - Conversion to domain entity
|
|
/// - Local storage (if needed)
|
|
class NewsArticleModel {
|
|
/// Unique article ID
|
|
final String id;
|
|
|
|
/// Article title
|
|
final String title;
|
|
|
|
/// Article excerpt/summary
|
|
final String excerpt;
|
|
|
|
/// Full article content (optional)
|
|
final String? content;
|
|
|
|
/// Featured image URL
|
|
final String imageUrl;
|
|
|
|
/// Article category
|
|
final String category;
|
|
|
|
/// Publication date (ISO 8601 string)
|
|
final String publishedDate;
|
|
|
|
/// View count
|
|
final int viewCount;
|
|
|
|
/// Estimated reading time in minutes
|
|
final int readingTimeMinutes;
|
|
|
|
/// Whether this is a featured article
|
|
final bool isFeatured;
|
|
|
|
/// Author name (optional)
|
|
final String? authorName;
|
|
|
|
/// Author avatar URL (optional)
|
|
final String? authorAvatar;
|
|
|
|
/// Tags/keywords for the article
|
|
final List<String> tags;
|
|
|
|
/// Like count
|
|
final int likeCount;
|
|
|
|
/// Comment count
|
|
final int commentCount;
|
|
|
|
/// Share count
|
|
final int shareCount;
|
|
|
|
/// Constructor
|
|
const NewsArticleModel({
|
|
required this.id,
|
|
required this.title,
|
|
required this.excerpt,
|
|
this.content,
|
|
required this.imageUrl,
|
|
required this.category,
|
|
required this.publishedDate,
|
|
required this.viewCount,
|
|
required this.readingTimeMinutes,
|
|
this.isFeatured = false,
|
|
this.authorName,
|
|
this.authorAvatar,
|
|
this.tags = const [],
|
|
this.likeCount = 0,
|
|
this.commentCount = 0,
|
|
this.shareCount = 0,
|
|
});
|
|
|
|
/// Create model from JSON
|
|
factory NewsArticleModel.fromJson(Map<String, dynamic> json) {
|
|
return NewsArticleModel(
|
|
id: json['id'] as String,
|
|
title: json['title'] as String,
|
|
excerpt: json['excerpt'] as String,
|
|
content: json['content'] as String?,
|
|
imageUrl: json['image_url'] as String,
|
|
category: json['category'] as String,
|
|
publishedDate: json['published_date'] as String,
|
|
viewCount: json['view_count'] as int,
|
|
readingTimeMinutes: json['reading_time_minutes'] as int,
|
|
isFeatured: json['is_featured'] as bool? ?? false,
|
|
authorName: json['author_name'] as String?,
|
|
authorAvatar: json['author_avatar'] as String?,
|
|
tags:
|
|
(json['tags'] as List<dynamic>?)?.map((e) => e as String).toList() ??
|
|
const [],
|
|
likeCount: json['like_count'] as int? ?? 0,
|
|
commentCount: json['comment_count'] as int? ?? 0,
|
|
shareCount: json['share_count'] as int? ?? 0,
|
|
);
|
|
}
|
|
|
|
/// Convert model to JSON
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'id': id,
|
|
'title': title,
|
|
'excerpt': excerpt,
|
|
'content': content,
|
|
'image_url': imageUrl,
|
|
'category': category,
|
|
'published_date': publishedDate,
|
|
'view_count': viewCount,
|
|
'reading_time_minutes': readingTimeMinutes,
|
|
'is_featured': isFeatured,
|
|
'author_name': authorName,
|
|
'author_avatar': authorAvatar,
|
|
'tags': tags,
|
|
'like_count': likeCount,
|
|
'comment_count': commentCount,
|
|
'share_count': shareCount,
|
|
};
|
|
}
|
|
|
|
/// Convert model to domain entity
|
|
NewsArticle toEntity() {
|
|
return NewsArticle(
|
|
id: id,
|
|
title: title,
|
|
excerpt: excerpt,
|
|
content: content,
|
|
imageUrl: imageUrl,
|
|
category: _parseCategory(category),
|
|
publishedDate: DateTime.parse(publishedDate),
|
|
viewCount: viewCount,
|
|
readingTimeMinutes: readingTimeMinutes,
|
|
isFeatured: isFeatured,
|
|
authorName: authorName,
|
|
authorAvatar: authorAvatar,
|
|
tags: tags,
|
|
likeCount: likeCount,
|
|
commentCount: commentCount,
|
|
shareCount: shareCount,
|
|
);
|
|
}
|
|
|
|
/// Create model from domain entity
|
|
factory NewsArticleModel.fromEntity(NewsArticle entity) {
|
|
return NewsArticleModel(
|
|
id: entity.id,
|
|
title: entity.title,
|
|
excerpt: entity.excerpt,
|
|
content: entity.content,
|
|
imageUrl: entity.imageUrl,
|
|
category: _categoryToString(entity.category),
|
|
publishedDate: entity.publishedDate.toIso8601String(),
|
|
viewCount: entity.viewCount,
|
|
readingTimeMinutes: entity.readingTimeMinutes,
|
|
isFeatured: entity.isFeatured,
|
|
authorName: entity.authorName,
|
|
authorAvatar: entity.authorAvatar,
|
|
tags: entity.tags,
|
|
likeCount: entity.likeCount,
|
|
commentCount: entity.commentCount,
|
|
shareCount: entity.shareCount,
|
|
);
|
|
}
|
|
|
|
/// Parse category from string
|
|
static NewsCategory _parseCategory(String category) {
|
|
switch (category.toLowerCase()) {
|
|
case 'news':
|
|
return NewsCategory.news;
|
|
case 'professional':
|
|
case 'technique':
|
|
return NewsCategory.professional;
|
|
case 'projects':
|
|
return NewsCategory.projects;
|
|
case 'events':
|
|
return NewsCategory.events;
|
|
case 'promotions':
|
|
return NewsCategory.promotions;
|
|
default:
|
|
return NewsCategory.news;
|
|
}
|
|
}
|
|
|
|
/// Convert category to string
|
|
static String _categoryToString(NewsCategory category) {
|
|
switch (category) {
|
|
case NewsCategory.news:
|
|
return 'news';
|
|
case NewsCategory.professional:
|
|
return 'professional';
|
|
case NewsCategory.projects:
|
|
return 'projects';
|
|
case NewsCategory.events:
|
|
return 'events';
|
|
case NewsCategory.promotions:
|
|
return 'promotions';
|
|
}
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return 'NewsArticleModel(id: $id, title: $title, category: $category, '
|
|
'publishedDate: $publishedDate)';
|
|
}
|
|
}
|