add auth
This commit is contained in:
@@ -19,20 +19,36 @@ import 'package:worker/features/news/presentation/widgets/news_card.dart';
|
||||
///
|
||||
/// Features:
|
||||
/// - Standard AppBar with title "Tin tức & chuyên môn"
|
||||
/// - Horizontal scrollable category chips (Tất cả, Tin tức, Chuyên môn, Dự án, Sự kiện, Khuyến mãi)
|
||||
/// - Horizontal scrollable category chips (dynamic from Frappe API)
|
||||
/// - Featured article section (large card)
|
||||
/// - "Mới nhất" section with news cards list
|
||||
/// - RefreshIndicator for pull-to-refresh
|
||||
/// - Loading and error states
|
||||
class NewsListPage extends ConsumerWidget {
|
||||
class NewsListPage extends ConsumerStatefulWidget {
|
||||
const NewsListPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
ConsumerState<NewsListPage> createState() => _NewsListPageState();
|
||||
}
|
||||
|
||||
class _NewsListPageState extends ConsumerState<NewsListPage> {
|
||||
/// Currently selected category name (null = All)
|
||||
String? selectedCategoryName;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Watch providers
|
||||
final featuredArticleAsync = ref.watch(featuredArticleProvider);
|
||||
final filteredArticlesAsync = ref.watch(filteredNewsArticlesProvider);
|
||||
final selectedCategory = ref.watch(selectedNewsCategoryProvider);
|
||||
final newsArticlesAsync = ref.watch(newsArticlesProvider);
|
||||
|
||||
// Filter articles by selected category
|
||||
final filteredArticles = newsArticlesAsync.whenData((articles) {
|
||||
if (selectedCategoryName == null) {
|
||||
return articles;
|
||||
}
|
||||
// TODO: Filter by category when articles have category field
|
||||
return articles;
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
@@ -40,9 +56,10 @@ class NewsListPage extends ConsumerWidget {
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
// Invalidate providers to trigger refresh
|
||||
ref.invalidate(newsArticlesProvider);
|
||||
ref.invalidate(featuredArticleProvider);
|
||||
ref.invalidate(filteredNewsArticlesProvider);
|
||||
ref
|
||||
..invalidate(newsArticlesProvider)
|
||||
..invalidate(featuredArticleProvider)
|
||||
..invalidate(blogCategoriesProvider);
|
||||
},
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
@@ -51,11 +68,11 @@ class NewsListPage extends ConsumerWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 4, bottom: AppSpacing.md),
|
||||
child: CategoryFilterChips(
|
||||
selectedCategory: selectedCategory,
|
||||
onCategorySelected: (category) {
|
||||
ref
|
||||
.read(selectedNewsCategoryProvider.notifier)
|
||||
.setCategory(category);
|
||||
selectedCategoryName: selectedCategoryName,
|
||||
onCategorySelected: (categoryName) {
|
||||
setState(() {
|
||||
selectedCategoryName = categoryName;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -148,7 +165,7 @@ class NewsListPage extends ConsumerWidget {
|
||||
const SliverToBoxAdapter(child: SizedBox(height: AppSpacing.md)),
|
||||
|
||||
// News List
|
||||
filteredArticlesAsync.when(
|
||||
filteredArticles.when(
|
||||
data: (articles) {
|
||||
if (articles.isEmpty) {
|
||||
return SliverFillRemaining(child: _buildEmptyState());
|
||||
|
||||
Reference in New Issue
Block a user