news page

This commit is contained in:
Phuoc Nguyen
2025-11-03 11:48:41 +07:00
parent 21c1c3372c
commit ea485d8c3a
14 changed files with 2017 additions and 13 deletions

View File

@@ -0,0 +1,101 @@
/// 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/features/news/data/datasources/news_local_datasource.dart';
import 'package:worker/features/news/data/repositories/news_repository_impl.dart';
import 'package:worker/features/news/domain/entities/news_article.dart';
import 'package:worker/features/news/domain/repositories/news_repository.dart';
part 'news_provider.g.dart';
/// News Local DataSource Provider
///
/// Provides instance of NewsLocalDataSource.
@riverpod
NewsLocalDataSource newsLocalDataSource(Ref ref) {
return NewsLocalDataSource();
}
/// News Repository Provider
///
/// Provides instance of NewsRepository implementation.
@riverpod
NewsRepository newsRepository(Ref ref) {
final localDataSource = ref.watch(newsLocalDataSourceProvider);
return NewsRepositoryImpl(localDataSource: localDataSource);
}
/// 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 = ref.watch(newsRepositoryProvider);
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 = ref.watch(newsRepositoryProvider);
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 = ref.watch(newsRepositoryProvider);
// 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 = ref.watch(newsRepositoryProvider);
return repository.getArticleById(articleId);
}

View File

@@ -0,0 +1,455 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'news_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// News Local DataSource Provider
///
/// Provides instance of NewsLocalDataSource.
@ProviderFor(newsLocalDataSource)
const newsLocalDataSourceProvider = NewsLocalDataSourceProvider._();
/// News Local DataSource Provider
///
/// Provides instance of NewsLocalDataSource.
final class NewsLocalDataSourceProvider
extends
$FunctionalProvider<
NewsLocalDataSource,
NewsLocalDataSource,
NewsLocalDataSource
>
with $Provider<NewsLocalDataSource> {
/// News Local DataSource Provider
///
/// Provides instance of NewsLocalDataSource.
const NewsLocalDataSourceProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'newsLocalDataSourceProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$newsLocalDataSourceHash();
@$internal
@override
$ProviderElement<NewsLocalDataSource> $createElement(
$ProviderPointer pointer,
) => $ProviderElement(pointer);
@override
NewsLocalDataSource create(Ref ref) {
return newsLocalDataSource(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(NewsLocalDataSource value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<NewsLocalDataSource>(value),
);
}
}
String _$newsLocalDataSourceHash() =>
r'e7e7d71d20274fe8b498c7b15f8aeb9eb515af27';
/// News Repository Provider
///
/// Provides instance of NewsRepository implementation.
@ProviderFor(newsRepository)
const newsRepositoryProvider = NewsRepositoryProvider._();
/// News Repository Provider
///
/// Provides instance of NewsRepository implementation.
final class NewsRepositoryProvider
extends $FunctionalProvider<NewsRepository, NewsRepository, NewsRepository>
with $Provider<NewsRepository> {
/// News Repository Provider
///
/// Provides instance of NewsRepository implementation.
const NewsRepositoryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'newsRepositoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$newsRepositoryHash();
@$internal
@override
$ProviderElement<NewsRepository> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
NewsRepository create(Ref ref) {
return newsRepository(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(NewsRepository value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<NewsRepository>(value),
);
}
}
String _$newsRepositoryHash() => r'1536188fae6934f147f022a8f5d7bd62ff9453b5';
/// News Articles Provider
///
/// Fetches all news articles sorted by published date.
/// Returns AsyncValue<List<NewsArticle>> for proper loading/error handling.
@ProviderFor(newsArticles)
const newsArticlesProvider = NewsArticlesProvider._();
/// News Articles Provider
///
/// Fetches all news articles sorted by published date.
/// Returns AsyncValue<List<NewsArticle>> for proper loading/error handling.
final class NewsArticlesProvider
extends
$FunctionalProvider<
AsyncValue<List<NewsArticle>>,
List<NewsArticle>,
FutureOr<List<NewsArticle>>
>
with
$FutureModifier<List<NewsArticle>>,
$FutureProvider<List<NewsArticle>> {
/// News Articles Provider
///
/// Fetches all news articles sorted by published date.
/// Returns AsyncValue<List<NewsArticle>> for proper loading/error handling.
const NewsArticlesProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'newsArticlesProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$newsArticlesHash();
@$internal
@override
$FutureProviderElement<List<NewsArticle>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<NewsArticle>> create(Ref ref) {
return newsArticles(ref);
}
}
String _$newsArticlesHash() => r'24d70e49f7137c614c024dc93c97451c6e161ce6';
/// Featured Article Provider
///
/// Fetches the featured article for the top section.
/// Returns AsyncValue<NewsArticle?> (null if no featured article).
@ProviderFor(featuredArticle)
const featuredArticleProvider = FeaturedArticleProvider._();
/// Featured Article Provider
///
/// Fetches the featured article for the top section.
/// Returns AsyncValue<NewsArticle?> (null if no featured article).
final class FeaturedArticleProvider
extends
$FunctionalProvider<
AsyncValue<NewsArticle?>,
NewsArticle?,
FutureOr<NewsArticle?>
>
with $FutureModifier<NewsArticle?>, $FutureProvider<NewsArticle?> {
/// Featured Article Provider
///
/// Fetches the featured article for the top section.
/// Returns AsyncValue<NewsArticle?> (null if no featured article).
const FeaturedArticleProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'featuredArticleProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$featuredArticleHash();
@$internal
@override
$FutureProviderElement<NewsArticle?> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<NewsArticle?> create(Ref ref) {
return featuredArticle(ref);
}
}
String _$featuredArticleHash() => r'f7146600bc3bbaf5987ab6b09262135b1558f1c0';
/// Selected News Category Provider
///
/// Manages the currently selected category filter.
/// null means "All" is selected (show all categories).
@ProviderFor(SelectedNewsCategory)
const selectedNewsCategoryProvider = SelectedNewsCategoryProvider._();
/// Selected News Category Provider
///
/// Manages the currently selected category filter.
/// null means "All" is selected (show all categories).
final class SelectedNewsCategoryProvider
extends $NotifierProvider<SelectedNewsCategory, NewsCategory?> {
/// Selected News Category Provider
///
/// Manages the currently selected category filter.
/// null means "All" is selected (show all categories).
const SelectedNewsCategoryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'selectedNewsCategoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$selectedNewsCategoryHash();
@$internal
@override
SelectedNewsCategory create() => SelectedNewsCategory();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(NewsCategory? value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<NewsCategory?>(value),
);
}
}
String _$selectedNewsCategoryHash() =>
r'f1dca9a5d7de94cac90494d94ce05b727e6e4d5f';
/// Selected News Category Provider
///
/// Manages the currently selected category filter.
/// null means "All" is selected (show all categories).
abstract class _$SelectedNewsCategory extends $Notifier<NewsCategory?> {
NewsCategory? build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<NewsCategory?, NewsCategory?>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<NewsCategory?, NewsCategory?>,
NewsCategory?,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// Filtered News Articles Provider
///
/// Returns news articles filtered by selected category.
/// If no category is selected, returns all articles.
@ProviderFor(filteredNewsArticles)
const filteredNewsArticlesProvider = FilteredNewsArticlesProvider._();
/// Filtered News Articles Provider
///
/// Returns news articles filtered by selected category.
/// If no category is selected, returns all articles.
final class FilteredNewsArticlesProvider
extends
$FunctionalProvider<
AsyncValue<List<NewsArticle>>,
List<NewsArticle>,
FutureOr<List<NewsArticle>>
>
with
$FutureModifier<List<NewsArticle>>,
$FutureProvider<List<NewsArticle>> {
/// Filtered News Articles Provider
///
/// Returns news articles filtered by selected category.
/// If no category is selected, returns all articles.
const FilteredNewsArticlesProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'filteredNewsArticlesProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$filteredNewsArticlesHash();
@$internal
@override
$FutureProviderElement<List<NewsArticle>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<NewsArticle>> create(Ref ref) {
return filteredNewsArticles(ref);
}
}
String _$filteredNewsArticlesHash() =>
r'f40a737b74b44f2d4fa86977175314ed0da471fa';
/// News Article by ID Provider
///
/// Fetches a specific article by ID.
/// Used for article detail page.
@ProviderFor(newsArticleById)
const newsArticleByIdProvider = NewsArticleByIdFamily._();
/// News Article by ID Provider
///
/// Fetches a specific article by ID.
/// Used for article detail page.
final class NewsArticleByIdProvider
extends
$FunctionalProvider<
AsyncValue<NewsArticle?>,
NewsArticle?,
FutureOr<NewsArticle?>
>
with $FutureModifier<NewsArticle?>, $FutureProvider<NewsArticle?> {
/// News Article by ID Provider
///
/// Fetches a specific article by ID.
/// Used for article detail page.
const NewsArticleByIdProvider._({
required NewsArticleByIdFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'newsArticleByIdProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$newsArticleByIdHash();
@override
String toString() {
return r'newsArticleByIdProvider'
''
'($argument)';
}
@$internal
@override
$FutureProviderElement<NewsArticle?> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<NewsArticle?> create(Ref ref) {
final argument = this.argument as String;
return newsArticleById(ref, argument);
}
@override
bool operator ==(Object other) {
return other is NewsArticleByIdProvider && other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$newsArticleByIdHash() => r'4d28caa81d486fcd6cfefd16477355927bbcadc8';
/// News Article by ID Provider
///
/// Fetches a specific article by ID.
/// Used for article detail page.
final class NewsArticleByIdFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<NewsArticle?>, String> {
const NewsArticleByIdFamily._()
: super(
retry: null,
name: r'newsArticleByIdProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
/// News Article by ID Provider
///
/// Fetches a specific article by ID.
/// Used for article detail page.
NewsArticleByIdProvider call(String articleId) =>
NewsArticleByIdProvider._(argument: articleId, from: this);
@override
String toString() => r'newsArticleByIdProvider';
}