update products

This commit is contained in:
Phuoc Nguyen
2025-10-15 16:58:20 +07:00
parent f6d2971224
commit 4038f8e8a6
17 changed files with 1172 additions and 314 deletions

View File

@@ -25,6 +25,13 @@ class _ProductsPageState extends ConsumerState<ProductsPage> {
final selectedCategory = ref.watch(product_providers.selectedCategoryProvider);
final productsAsync = ref.watch(productsProvider);
// Debug: Log product loading state
productsAsync.whenOrNull(
data: (products) => debugPrint('Products loaded: ${products.length} items'),
loading: () => debugPrint('Products loading...'),
error: (error, stack) => debugPrint('Products error: $error'),
);
// Get filtered products from the provider
final filteredProducts = productsAsync.when(
data: (products) => products,
@@ -168,12 +175,14 @@ class _ProductsPageState extends ConsumerState<ProductsPage> {
),
),
),
body: RefreshIndicator(
onRefresh: () async {
await ref.refresh(productsProvider.future);
await ref.refresh(categoriesProvider.future);
},
child: Column(
body: productsAsync.when(
data: (products) => RefreshIndicator(
onRefresh: () async {
// Force sync with API
await ref.read(productsProvider.notifier).syncProducts();
await ref.refresh(categoriesProvider.future);
},
child: Column(
children: [
// Results count
if (filteredProducts.isNotEmpty)
@@ -194,6 +203,23 @@ class _ProductsPageState extends ConsumerState<ProductsPage> {
),
],
),
),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text('Error loading products: $error'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => ref.refresh(productsProvider),
child: const Text('Retry'),
),
],
),
),
),
);
}

View File

@@ -1,32 +1,92 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../domain/entities/product.dart';
import '../../data/providers/product_providers.dart';
import '../../../../core/providers/providers.dart';
part 'products_provider.g.dart';
/// Provider for products list
/// Provider for products list with API-first approach
@riverpod
class Products extends _$Products {
@override
Future<List<Product>> build() async {
// TODO: Implement with repository
return [];
// API-first: Try to load from API first
final repository = ref.watch(productRepositoryProvider);
final networkInfo = ref.watch(networkInfoProvider);
// Check if online
final isConnected = await networkInfo.isConnected;
if (isConnected) {
// Try API first
try {
final syncResult = await repository.syncProducts();
return syncResult.fold(
(failure) {
// API failed, fallback to cache
print('API failed, falling back to cache: ${failure.message}');
return _loadFromCache();
},
(products) => products,
);
} catch (e) {
// API error, fallback to cache
print('API error, falling back to cache: $e');
return _loadFromCache();
}
} else {
// Offline, load from cache
print('Offline, loading from cache');
return _loadFromCache();
}
}
/// Load products from local cache
Future<List<Product>> _loadFromCache() async {
final repository = ref.read(productRepositoryProvider);
final result = await repository.getAllProducts();
return result.fold(
(failure) {
print('Cache load failed: ${failure.message}');
return <Product>[];
},
(products) => products,
);
}
/// Refresh products from local storage
Future<void> refresh() async {
// TODO: Implement refresh logic
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
// Fetch products from repository
return [];
final repository = ref.read(productRepositoryProvider);
final result = await repository.getAllProducts();
return result.fold(
(failure) => throw Exception(failure.message),
(products) => products,
);
});
}
/// Sync products from API and update local storage
Future<void> syncProducts() async {
// TODO: Implement sync logic with remote data source
final networkInfo = ref.read(networkInfoProvider);
final isConnected = await networkInfo.isConnected;
if (!isConnected) {
throw Exception('No internet connection');
}
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
// Sync products from API
return [];
final repository = ref.read(productRepositoryProvider);
final result = await repository.syncProducts();
return result.fold(
(failure) => throw Exception(failure.message),
(products) => products,
);
});
}
}

View File

@@ -8,15 +8,15 @@ part of 'products_provider.dart';
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Provider for products list
/// Provider for products list with API-first approach
@ProviderFor(Products)
const productsProvider = ProductsProvider._();
/// Provider for products list
/// Provider for products list with API-first approach
final class ProductsProvider
extends $AsyncNotifierProvider<Products, List<Product>> {
/// Provider for products list
/// Provider for products list with API-first approach
const ProductsProvider._()
: super(
from: null,
@@ -36,9 +36,9 @@ final class ProductsProvider
Products create() => Products();
}
String _$productsHash() => r'9e1d3aaa1d9cf0b4ff03fdfaf4512a7a15336d51';
String _$productsHash() => r'0ff8c2de46bb4b1e29678cc811ec121c9fb4c8eb';
/// Provider for products list
/// Provider for products list with API-first approach
abstract class _$Products extends $AsyncNotifier<List<Product>> {
FutureOr<List<Product>> build();