This commit is contained in:
Phuoc Nguyen
2025-10-10 16:38:07 +07:00
parent e5b247d622
commit b94c158004
177 changed files with 25080 additions and 152 deletions

View File

@@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../widgets/category_grid.dart';
import '../providers/categories_provider.dart';
import '../../../products/presentation/providers/selected_category_provider.dart' as product_providers;
/// Categories page - displays all categories in a grid
class CategoriesPage extends ConsumerWidget {
const CategoriesPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final categoriesAsync = ref.watch(categoriesProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Categories'),
actions: [
// Refresh button
IconButton(
icon: const Icon(Icons.refresh),
tooltip: 'Refresh categories',
onPressed: () {
ref.invalidate(categoriesProvider);
},
),
],
),
body: RefreshIndicator(
onRefresh: () async {
await ref.refresh(categoriesProvider.future);
},
child: categoriesAsync.when(
loading: () => const Center(
child: CircularProgressIndicator(),
),
error: (error, stack) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.error_outline,
size: 64,
color: Theme.of(context).colorScheme.error,
),
const SizedBox(height: 16),
Text(
'Error loading categories',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
Text(
error.toString(),
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: () => ref.invalidate(categoriesProvider),
icon: const Icon(Icons.refresh),
label: const Text('Retry'),
),
],
),
),
data: (categories) {
return Column(
children: [
// Categories count
if (categories.isNotEmpty)
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${categories.length} categor${categories.length == 1 ? 'y' : 'ies'}',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
// Category grid
Expanded(
child: CategoryGrid(
onCategoryTap: (category) {
// Set selected category
ref
.read(product_providers.selectedCategoryProvider.notifier)
.selectCategory(category.id);
// Show snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Filtering products by ${category.name}',
),
duration: const Duration(seconds: 2),
action: SnackBarAction(
label: 'View',
onPressed: () {
// Navigate to products tab
// This will be handled by the parent widget
// For now, just show a message
},
),
),
);
},
),
),
],
);
},
),
),
);
}
}