Files
worker/lib/features/news/domain/entities/news_article.dart
2025-11-03 13:37:33 +07:00

209 lines
4.9 KiB
Dart

/// Domain Entity: News Article
///
/// Pure business entity representing a news article or blog post.
/// This entity is framework-independent and contains only business logic.
library;
/// News Article Entity
///
/// Represents a news article/blog post in the app.
/// Used for displaying news, tips, project showcases, and professional content.
class NewsArticle {
/// Unique article ID
final String id;
/// Article title
final String title;
/// Article excerpt/summary
final String excerpt;
/// Full article content (optional, may load separately)
final String? content;
/// Featured image URL
final String imageUrl;
/// Article category
final NewsCategory category;
/// Publication date
final DateTime 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 NewsArticle({
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,
});
/// Get formatted publication date (dd/MM/yyyy)
String get formattedDate {
return '${publishedDate.day.toString().padLeft(2, '0')}/'
'${publishedDate.month.toString().padLeft(2, '0')}/'
'${publishedDate.year}';
}
/// Get formatted view count (e.g., "2.3K")
String get formattedViewCount {
if (viewCount >= 1000) {
return '${(viewCount / 1000).toStringAsFixed(1)}K';
}
return viewCount.toString();
}
/// Get reading time display text
String get readingTimeText => '$readingTimeMinutes phút đọc';
/// Copy with method for immutability
NewsArticle copyWith({
String? id,
String? title,
String? excerpt,
String? content,
String? imageUrl,
NewsCategory? category,
DateTime? publishedDate,
int? viewCount,
int? readingTimeMinutes,
bool? isFeatured,
String? authorName,
String? authorAvatar,
List<String>? tags,
int? likeCount,
int? commentCount,
int? shareCount,
}) {
return NewsArticle(
id: id ?? this.id,
title: title ?? this.title,
excerpt: excerpt ?? this.excerpt,
content: content ?? this.content,
imageUrl: imageUrl ?? this.imageUrl,
category: category ?? this.category,
publishedDate: publishedDate ?? this.publishedDate,
viewCount: viewCount ?? this.viewCount,
readingTimeMinutes: readingTimeMinutes ?? this.readingTimeMinutes,
isFeatured: isFeatured ?? this.isFeatured,
authorName: authorName ?? this.authorName,
authorAvatar: authorAvatar ?? this.authorAvatar,
tags: tags ?? this.tags,
likeCount: likeCount ?? this.likeCount,
commentCount: commentCount ?? this.commentCount,
shareCount: shareCount ?? this.shareCount,
);
}
/// Equality operator
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is NewsArticle && other.id == id;
}
/// Hash code
@override
int get hashCode {
return id.hashCode;
}
/// String representation
@override
String toString() {
return 'NewsArticle(id: $id, title: $title, category: $category, '
'publishedDate: $publishedDate, isFeatured: $isFeatured)';
}
}
/// News Category enum
enum NewsCategory {
/// General news
news,
/// Professional/technical content
professional,
/// Project showcases
projects,
/// Events
events,
/// Promotions
promotions,
}
/// Extension for News Category display
extension NewsCategoryX on NewsCategory {
String get displayName {
switch (this) {
case NewsCategory.news:
return 'Tin tức';
case NewsCategory.professional:
return 'Chuyên môn';
case NewsCategory.projects:
return 'Dự án';
case NewsCategory.events:
return 'Sự kiện';
case NewsCategory.promotions:
return 'Khuyến mãi';
}
}
String get filterName {
switch (this) {
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';
}
}
}