/// 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(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(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> for proper loading/error handling. @riverpod Future> 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 (null if no featured article). @riverpod Future 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> 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 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> (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> blogCategories(Ref ref) async { final repository = await ref.watch(newsRepositoryProvider.future); return repository.getBlogCategories(); }