136 lines
4.3 KiB
Dart
136 lines
4.3 KiB
Dart
/// News Providers
|
|
///
|
|
/// State management for news articles using Riverpod.
|
|
/// Provides access to news data and filtering capabilities.
|
|
library;
|
|
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:worker/core/network/dio_client.dart';
|
|
import 'package:worker/core/services/frappe_auth_provider.dart';
|
|
import 'package:worker/features/news/data/datasources/news_local_datasource.dart';
|
|
import 'package:worker/features/news/data/datasources/news_remote_datasource.dart';
|
|
import 'package:worker/features/news/domain/entities/blog_category.dart';
|
|
import 'package:worker/features/news/domain/entities/news_article.dart';
|
|
import 'package:worker/features/news/domain/repositories/news_repository.dart';
|
|
import 'package:worker/features/news/data/repositories/news_repository_impl.dart';
|
|
|
|
part 'news_provider.g.dart';
|
|
|
|
/// News Local DataSource Provider
|
|
///
|
|
/// Provides instance of NewsLocalDataSource.
|
|
@riverpod
|
|
NewsLocalDataSource newsLocalDataSource(Ref ref) {
|
|
return NewsLocalDataSource();
|
|
}
|
|
|
|
/// News Remote DataSource Provider
|
|
///
|
|
/// Provides instance of NewsRemoteDataSource with Frappe auth service.
|
|
@riverpod
|
|
Future<NewsRemoteDataSource> newsRemoteDataSource(Ref ref) async {
|
|
final dioClient = await ref.watch(dioClientProvider.future);
|
|
final frappeAuthService = ref.watch(frappeAuthServiceProvider);
|
|
return NewsRemoteDataSource(dioClient, frappeAuthService);
|
|
}
|
|
|
|
/// News Repository Provider
|
|
///
|
|
/// Provides instance of NewsRepository implementation.
|
|
@riverpod
|
|
Future<NewsRepository> newsRepository(Ref ref) async {
|
|
final localDataSource = ref.watch(newsLocalDataSourceProvider);
|
|
final remoteDataSource = await ref.watch(newsRemoteDataSourceProvider.future);
|
|
return NewsRepositoryImpl(
|
|
localDataSource: localDataSource,
|
|
remoteDataSource: remoteDataSource,
|
|
);
|
|
}
|
|
|
|
/// News Articles Provider
|
|
///
|
|
/// Fetches all news articles sorted by published date.
|
|
/// Returns AsyncValue<List<NewsArticle>> for proper loading/error handling.
|
|
@riverpod
|
|
Future<List<NewsArticle>> newsArticles(Ref ref) async {
|
|
final repository = await ref.watch(newsRepositoryProvider.future);
|
|
return repository.getAllArticles();
|
|
}
|
|
|
|
/// Featured Article Provider
|
|
///
|
|
/// Fetches the featured article for the top section.
|
|
/// Returns AsyncValue<NewsArticle?> (null if no featured article).
|
|
@riverpod
|
|
Future<NewsArticle?> featuredArticle(Ref ref) async {
|
|
final repository = await ref.watch(newsRepositoryProvider.future);
|
|
return repository.getFeaturedArticle();
|
|
}
|
|
|
|
/// Selected News Category Provider
|
|
///
|
|
/// Manages the currently selected category filter.
|
|
/// null means "All" is selected (show all categories).
|
|
@riverpod
|
|
class SelectedNewsCategory extends _$SelectedNewsCategory {
|
|
@override
|
|
NewsCategory? build() {
|
|
// Default: show all categories
|
|
return null;
|
|
}
|
|
|
|
/// Set selected category
|
|
void setCategory(NewsCategory? category) {
|
|
state = category;
|
|
}
|
|
|
|
/// Clear selection (show all)
|
|
void clearSelection() {
|
|
state = null;
|
|
}
|
|
}
|
|
|
|
/// Filtered News Articles Provider
|
|
///
|
|
/// Returns news articles filtered by selected category.
|
|
/// If no category is selected, returns all articles.
|
|
@riverpod
|
|
Future<List<NewsArticle>> filteredNewsArticles(Ref ref) async {
|
|
final selectedCategory = ref.watch(selectedNewsCategoryProvider);
|
|
final repository = await ref.watch(newsRepositoryProvider.future);
|
|
|
|
// If no category selected, return all articles
|
|
if (selectedCategory == null) {
|
|
return repository.getAllArticles();
|
|
}
|
|
|
|
// Filter by selected category
|
|
return repository.getArticlesByCategory(selectedCategory);
|
|
}
|
|
|
|
/// News Article by ID Provider
|
|
///
|
|
/// Fetches a specific article by ID.
|
|
/// Used for article detail page.
|
|
@riverpod
|
|
Future<NewsArticle?> newsArticleById(Ref ref, String articleId) async {
|
|
final repository = await ref.watch(newsRepositoryProvider.future);
|
|
return repository.getArticleById(articleId);
|
|
}
|
|
|
|
/// Blog Categories Provider
|
|
///
|
|
/// Fetches all published blog categories from Frappe API.
|
|
/// Returns AsyncValue<List<BlogCategory>> (domain entities) for proper loading/error handling.
|
|
///
|
|
/// Example categories:
|
|
/// - Tin tức (News)
|
|
/// - Chuyên môn (Professional)
|
|
/// - Dự án (Projects)
|
|
/// - Khuyến mãi (Promotions)
|
|
@riverpod
|
|
Future<List<BlogCategory>> blogCategories(Ref ref) async {
|
|
final repository = await ref.watch(newsRepositoryProvider.future);
|
|
return repository.getBlogCategories();
|
|
}
|