/// Provider: Promotions Provider /// /// Manages the state of promotions data using Riverpod. /// Uses the same data source as news articles (single API call). /// /// Uses AsyncNotifierProvider for automatic loading, error, and data states. library; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:worker/features/home/domain/entities/promotion.dart'; import 'package:worker/features/news/presentation/providers/news_provider.dart'; part 'promotions_provider.g.dart'; /// Max number of promotions to display on home page const int _maxPromotions = 5; /// Promotions Provider /// /// Uses the same data source as news articles to avoid duplicate API calls. /// Converts NewsArticle to Promotion entity for display in PromotionSlider. /// Limited to 5 items max. /// /// Usage: /// ```dart /// // In a ConsumerWidget /// final promotionsAsync = ref.watch(promotionsProvider); /// /// promotionsAsync.when( /// data: (promotions) => PromotionSlider(promotions: promotions), /// loading: () => CircularProgressIndicator(), /// error: (error, stack) => ErrorWidget(error), /// ); /// ``` @riverpod Future> promotions(Ref ref) async { // Use newsArticles provider (same API call, no duplicate request) final articles = await ref.watch(newsArticlesProvider.future); // Take max 5 articles and convert to Promotion final limitedArticles = articles.take(_maxPromotions).toList(); return limitedArticles.map((article) { final now = DateTime.now(); return Promotion( id: article.id, title: article.title, description: article.excerpt, imageUrl: article.imageUrl, startDate: article.publishedDate, endDate: now.add(const Duration(days: 365)), // Always active ); }).toList(); }