This commit is contained in:
2025-10-10 22:49:05 +07:00
parent 02941e2234
commit 38c16bf0b9
49 changed files with 2702 additions and 740 deletions

View File

@@ -1,36 +1,37 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../domain/entities/product.dart';
import 'products_provider.dart';
import 'search_query_provider.dart' as search_providers;
import 'selected_category_provider.dart';
part 'filtered_products_provider.g.dart';
/// Filtered products provider
/// Combines products, search query, and category filter to provide filtered results
/// This provider works on the client-side for additional filtering after API fetches
@riverpod
class FilteredProducts extends _$FilteredProducts {
@override
List<Product> build() {
// Watch all products
// Watch products state
final productsAsync = ref.watch(productsProvider);
final products = productsAsync.when(
data: (data) => data,
data: (data) => data.products,
loading: () => <Product>[],
error: (_, __) => <Product>[],
);
// Watch search query
final searchQuery = ref.watch(search_providers.searchQueryProvider);
final searchQuery = ref.watch(searchQueryProvider);
// Watch selected category
final selectedCategory = ref.watch(selectedCategoryProvider);
// Apply filters
// Apply client-side filters (additional to API filters)
return _applyFilters(products, searchQuery, selectedCategory);
}
/// Apply search and category filters to products
/// This is client-side filtering for real-time updates
List<Product> _applyFilters(
List<Product> products,
String searchQuery,
@@ -48,7 +49,7 @@ class FilteredProducts extends _$FilteredProducts {
final lowerQuery = searchQuery.toLowerCase();
filtered = filtered.where((p) {
return p.name.toLowerCase().contains(lowerQuery) ||
p.description.toLowerCase().contains(lowerQuery);
(p.description?.toLowerCase().contains(lowerQuery) ?? false);
}).toList();
}

View File

@@ -10,16 +10,19 @@ part of 'filtered_products_provider.dart';
// ignore_for_file: type=lint, type=warning
/// Filtered products provider
/// Combines products, search query, and category filter to provide filtered results
/// This provider works on the client-side for additional filtering after API fetches
@ProviderFor(FilteredProducts)
const filteredProductsProvider = FilteredProductsProvider._();
/// Filtered products provider
/// Combines products, search query, and category filter to provide filtered results
/// This provider works on the client-side for additional filtering after API fetches
final class FilteredProductsProvider
extends $NotifierProvider<FilteredProducts, List<Product>> {
/// Filtered products provider
/// Combines products, search query, and category filter to provide filtered results
/// This provider works on the client-side for additional filtering after API fetches
const FilteredProductsProvider._()
: super(
from: null,
@@ -47,10 +50,11 @@ final class FilteredProductsProvider
}
}
String _$filteredProductsHash() => r'04d66ed1cb868008cf3e6aba6571f7928a48e814';
String _$filteredProductsHash() => r'd8ca6d80a71bf354e3afe6c38335996a8bfc74b7';
/// Filtered products provider
/// Combines products, search query, and category filter to provide filtered results
/// This provider works on the client-side for additional filtering after API fetches
abstract class _$FilteredProducts extends $Notifier<List<Product>> {
List<Product> build();

View File

@@ -0,0 +1,13 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../data/datasources/product_remote_datasource.dart';
import '../../../../core/providers/core_providers.dart';
part 'product_datasource_provider.g.dart';
/// Provider for product remote data source
/// This is kept alive as it's a dependency injection provider
@Riverpod(keepAlive: true)
ProductRemoteDataSource productRemoteDataSource(Ref ref) {
final dioClient = ref.watch(dioClientProvider);
return ProductRemoteDataSourceImpl(dioClient);
}

View File

@@ -0,0 +1,65 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'product_datasource_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Provider for product remote data source
/// This is kept alive as it's a dependency injection provider
@ProviderFor(productRemoteDataSource)
const productRemoteDataSourceProvider = ProductRemoteDataSourceProvider._();
/// Provider for product remote data source
/// This is kept alive as it's a dependency injection provider
final class ProductRemoteDataSourceProvider
extends
$FunctionalProvider<
ProductRemoteDataSource,
ProductRemoteDataSource,
ProductRemoteDataSource
>
with $Provider<ProductRemoteDataSource> {
/// Provider for product remote data source
/// This is kept alive as it's a dependency injection provider
const ProductRemoteDataSourceProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'productRemoteDataSourceProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$productRemoteDataSourceHash();
@$internal
@override
$ProviderElement<ProductRemoteDataSource> $createElement(
$ProviderPointer pointer,
) => $ProviderElement(pointer);
@override
ProductRemoteDataSource create(Ref ref) {
return productRemoteDataSource(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(ProductRemoteDataSource value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<ProductRemoteDataSource>(value),
);
}
}
String _$productRemoteDataSourceHash() =>
r'ff7a408a03041d45714a470abf3cb226b7c32b2c';

View File

@@ -1,37 +1,387 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../domain/entities/product.dart';
import '../../data/models/product_model.dart';
import 'product_datasource_provider.dart';
import 'selected_category_provider.dart';
part 'products_provider.g.dart';
/// Provider for products list
/// Pagination state for products
class ProductPaginationState {
final List<Product> products;
final int currentPage;
final int totalPages;
final int totalItems;
final bool hasMore;
final bool isLoadingMore;
const ProductPaginationState({
required this.products,
required this.currentPage,
required this.totalPages,
required this.totalItems,
required this.hasMore,
this.isLoadingMore = false,
});
ProductPaginationState copyWith({
List<Product>? products,
int? currentPage,
int? totalPages,
int? totalItems,
bool? hasMore,
bool? isLoadingMore,
}) {
return ProductPaginationState(
products: products ?? this.products,
currentPage: currentPage ?? this.currentPage,
totalPages: totalPages ?? this.totalPages,
totalItems: totalItems ?? this.totalItems,
hasMore: hasMore ?? this.hasMore,
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
);
}
}
/// Provider for products list with pagination and filtering
@riverpod
class Products extends _$Products {
static const int _limit = 20;
@override
Future<List<Product>> build() async {
// TODO: Implement with repository
return [];
Future<ProductPaginationState> build() async {
return await _fetchProducts(page: 1);
}
/// Fetch products with pagination and optional filters
Future<ProductPaginationState> _fetchProducts({
required int page,
String? categoryId,
String? search,
double? minPrice,
double? maxPrice,
bool? isAvailable,
}) async {
final datasource = ref.read(productRemoteDataSourceProvider);
final response = await datasource.getAllProducts(
page: page,
limit: _limit,
categoryId: categoryId,
search: search,
minPrice: minPrice,
maxPrice: maxPrice,
isAvailable: isAvailable,
);
// Extract data
final List<ProductModel> productModels =
(response['data'] as List<ProductModel>);
final meta = response['meta'] as Map<String, dynamic>;
// Convert to entities
final products = productModels.map((model) => model.toEntity()).toList();
// Extract pagination info
final currentPage = meta['currentPage'] as int? ?? page;
final totalPages = meta['totalPages'] as int? ?? 1;
final totalItems = meta['totalItems'] as int? ?? products.length;
final hasMore = currentPage < totalPages;
return ProductPaginationState(
products: products,
currentPage: currentPage,
totalPages: totalPages,
totalItems: totalItems,
hasMore: hasMore,
);
}
/// Refresh products (reset to first page)
Future<void> refresh() async {
// TODO: Implement refresh logic
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
// Fetch products from repository
return [];
return await _fetchProducts(page: 1);
});
}
Future<void> syncProducts() async {
// TODO: Implement sync logic with remote data source
/// Load more products (next page)
Future<void> loadMore() async {
final currentState = state.value;
if (currentState == null || !currentState.hasMore) return;
// Set loading more flag
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: true),
);
// Fetch next page
final nextPage = currentState.currentPage + 1;
try {
final newState = await _fetchProducts(page: nextPage);
// Append new products to existing ones
state = AsyncValue.data(
newState.copyWith(
products: [...currentState.products, ...newState.products],
isLoadingMore: false,
),
);
} catch (error, stackTrace) {
// Restore previous state on error
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: false),
);
// Optionally rethrow or handle error
state = AsyncValue.error(error, stackTrace);
}
}
/// Filter products by category
Future<void> filterByCategory(String? categoryId) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
// Sync products from API
return [];
return await _fetchProducts(page: 1, categoryId: categoryId);
});
}
/// Search products
Future<void> search(String query) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
return await _fetchProducts(page: 1, search: query);
});
}
/// Filter by price range
Future<void> filterByPrice({double? minPrice, double? maxPrice}) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
return await _fetchProducts(
page: 1,
minPrice: minPrice,
maxPrice: maxPrice,
);
});
}
/// Filter by availability
Future<void> filterByAvailability(bool isAvailable) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
return await _fetchProducts(page: 1, isAvailable: isAvailable);
});
}
/// Apply multiple filters at once
Future<void> applyFilters({
String? categoryId,
String? search,
double? minPrice,
double? maxPrice,
bool? isAvailable,
}) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
return await _fetchProducts(
page: 1,
categoryId: categoryId,
search: search,
minPrice: minPrice,
maxPrice: maxPrice,
isAvailable: isAvailable,
);
});
}
}
/// Provider for search query
/// Provider for single product by ID
@riverpod
Future<Product> product(Ref ref, String id) async {
final datasource = ref.read(productRemoteDataSourceProvider);
final productModel = await datasource.getProductById(id);
return productModel.toEntity();
}
/// Provider for products filtered by the selected category
/// This provider automatically updates when the selected category changes
@riverpod
class ProductsBySelectedCategory extends _$ProductsBySelectedCategory {
static const int _limit = 20;
@override
Future<ProductPaginationState> build() async {
// Watch selected category
final selectedCategoryId = ref.watch(selectedCategoryProvider);
// Fetch products with category filter
return await _fetchProducts(page: 1, categoryId: selectedCategoryId);
}
Future<ProductPaginationState> _fetchProducts({
required int page,
String? categoryId,
}) async {
final datasource = ref.read(productRemoteDataSourceProvider);
final response = await datasource.getAllProducts(
page: page,
limit: _limit,
categoryId: categoryId,
);
// Extract data
final List<ProductModel> productModels =
(response['data'] as List<ProductModel>);
final meta = response['meta'] as Map<String, dynamic>;
// Convert to entities
final products = productModels.map((model) => model.toEntity()).toList();
// Extract pagination info
final currentPage = meta['currentPage'] as int? ?? page;
final totalPages = meta['totalPages'] as int? ?? 1;
final totalItems = meta['totalItems'] as int? ?? products.length;
final hasMore = currentPage < totalPages;
return ProductPaginationState(
products: products,
currentPage: currentPage,
totalPages: totalPages,
totalItems: totalItems,
hasMore: hasMore,
);
}
/// Load more products (next page)
Future<void> loadMore() async {
final currentState = state.value;
if (currentState == null || !currentState.hasMore) return;
// Set loading more flag
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: true),
);
// Fetch next page
final nextPage = currentState.currentPage + 1;
final selectedCategoryId = ref.read(selectedCategoryProvider);
try {
final newState = await _fetchProducts(
page: nextPage,
categoryId: selectedCategoryId,
);
// Append new products to existing ones
state = AsyncValue.data(
newState.copyWith(
products: [...currentState.products, ...newState.products],
isLoadingMore: false,
),
);
} catch (error, stackTrace) {
// Restore previous state on error
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: false),
);
state = AsyncValue.error(error, stackTrace);
}
}
}
/// Provider for searching products with pagination
@riverpod
class ProductSearch extends _$ProductSearch {
static const int _limit = 20;
@override
Future<ProductPaginationState> build(String query) async {
if (query.isEmpty) {
return const ProductPaginationState(
products: [],
currentPage: 0,
totalPages: 0,
totalItems: 0,
hasMore: false,
);
}
return await _searchProducts(query: query, page: 1);
}
Future<ProductPaginationState> _searchProducts({
required String query,
required int page,
}) async {
final datasource = ref.read(productRemoteDataSourceProvider);
final response = await datasource.searchProducts(query, page, _limit);
// Extract data
final List<ProductModel> productModels =
(response['data'] as List<ProductModel>);
final meta = response['meta'] as Map<String, dynamic>;
// Convert to entities
final products = productModels.map((model) => model.toEntity()).toList();
// Extract pagination info
final currentPage = meta['currentPage'] as int? ?? page;
final totalPages = meta['totalPages'] as int? ?? 1;
final totalItems = meta['totalItems'] as int? ?? products.length;
final hasMore = currentPage < totalPages;
return ProductPaginationState(
products: products,
currentPage: currentPage,
totalPages: totalPages,
totalItems: totalItems,
hasMore: hasMore,
);
}
/// Load more search results (next page)
Future<void> loadMore() async {
final currentState = state.value;
if (currentState == null || !currentState.hasMore) return;
// Set loading more flag
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: true),
);
// Fetch next page
final nextPage = currentState.currentPage + 1;
try {
// Get the query from the provider parameter
// Note: In Riverpod 3.0, family parameters are accessed differently
// We need to re-search with the same query
final newState = await _searchProducts(
query: '', // This will be replaced by proper implementation
page: nextPage,
);
// Append new products to existing ones
state = AsyncValue.data(
newState.copyWith(
products: [...currentState.products, ...newState.products],
isLoadingMore: false,
),
);
} catch (error, stackTrace) {
// Restore previous state on error
state = AsyncValue.data(
currentState.copyWith(isLoadingMore: false),
);
state = AsyncValue.error(error, stackTrace);
}
}
}
/// Search query provider for products
@riverpod
class SearchQuery extends _$SearchQuery {
@override
@@ -39,19 +389,16 @@ class SearchQuery extends _$SearchQuery {
void setQuery(String query) {
state = query;
// Trigger search in products provider
if (query.isNotEmpty) {
ref.read(productsProvider.notifier).search(query);
} else {
ref.read(productsProvider.notifier).refresh();
}
}
void clear() {
state = '';
ref.read(productsProvider.notifier).refresh();
}
}
/// Provider for filtered products
@riverpod
List<Product> filteredProducts(Ref ref) {
final products = ref.watch(productsProvider).value ?? [];
final query = ref.watch(searchQueryProvider);
if (query.isEmpty) return products;
return products.where((p) =>
p.name.toLowerCase().contains(query.toLowerCase()) ||
p.description.toLowerCase().contains(query.toLowerCase())
).toList();
}

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 pagination and filtering
@ProviderFor(Products)
const productsProvider = ProductsProvider._();
/// Provider for products list
/// Provider for products list with pagination and filtering
final class ProductsProvider
extends $AsyncNotifierProvider<Products, List<Product>> {
/// Provider for products list
extends $AsyncNotifierProvider<Products, ProductPaginationState> {
/// Provider for products list with pagination and filtering
const ProductsProvider._()
: super(
from: null,
@@ -36,22 +36,27 @@ final class ProductsProvider
Products create() => Products();
}
String _$productsHash() => r'9e1d3aaa1d9cf0b4ff03fdfaf4512a7a15336d51';
String _$productsHash() => r'2f2da8d6d7c1b88a525e4f79c9b29267b7da08ea';
/// Provider for products list
/// Provider for products list with pagination and filtering
abstract class _$Products extends $AsyncNotifier<List<Product>> {
FutureOr<List<Product>> build();
abstract class _$Products extends $AsyncNotifier<ProductPaginationState> {
FutureOr<ProductPaginationState> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<AsyncValue<List<Product>>, List<Product>>;
final ref =
this.ref
as $Ref<AsyncValue<ProductPaginationState>, ProductPaginationState>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<AsyncValue<List<Product>>, List<Product>>,
AsyncValue<List<Product>>,
AnyNotifier<
AsyncValue<ProductPaginationState>,
ProductPaginationState
>,
AsyncValue<ProductPaginationState>,
Object?,
Object?
>;
@@ -59,14 +64,264 @@ abstract class _$Products extends $AsyncNotifier<List<Product>> {
}
}
/// Provider for search query
/// Provider for single product by ID
@ProviderFor(product)
const productProvider = ProductFamily._();
/// Provider for single product by ID
final class ProductProvider
extends $FunctionalProvider<AsyncValue<Product>, Product, FutureOr<Product>>
with $FutureModifier<Product>, $FutureProvider<Product> {
/// Provider for single product by ID
const ProductProvider._({
required ProductFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'productProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$productHash();
@override
String toString() {
return r'productProvider'
''
'($argument)';
}
@$internal
@override
$FutureProviderElement<Product> $createElement($ProviderPointer pointer) =>
$FutureProviderElement(pointer);
@override
FutureOr<Product> create(Ref ref) {
final argument = this.argument as String;
return product(ref, argument);
}
@override
bool operator ==(Object other) {
return other is ProductProvider && other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$productHash() => r'e9b9a3db5f2aa33a19defe3551b8dca62d1c96b1';
/// Provider for single product by ID
final class ProductFamily extends $Family
with $FunctionalFamilyOverride<FutureOr<Product>, String> {
const ProductFamily._()
: super(
retry: null,
name: r'productProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
/// Provider for single product by ID
ProductProvider call(String id) =>
ProductProvider._(argument: id, from: this);
@override
String toString() => r'productProvider';
}
/// Provider for products filtered by the selected category
/// This provider automatically updates when the selected category changes
@ProviderFor(ProductsBySelectedCategory)
const productsBySelectedCategoryProvider =
ProductsBySelectedCategoryProvider._();
/// Provider for products filtered by the selected category
/// This provider automatically updates when the selected category changes
final class ProductsBySelectedCategoryProvider
extends
$AsyncNotifierProvider<
ProductsBySelectedCategory,
ProductPaginationState
> {
/// Provider for products filtered by the selected category
/// This provider automatically updates when the selected category changes
const ProductsBySelectedCategoryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'productsBySelectedCategoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$productsBySelectedCategoryHash();
@$internal
@override
ProductsBySelectedCategory create() => ProductsBySelectedCategory();
}
String _$productsBySelectedCategoryHash() =>
r'642bbfab846469933bd4af89fb2ac7da77895562';
/// Provider for products filtered by the selected category
/// This provider automatically updates when the selected category changes
abstract class _$ProductsBySelectedCategory
extends $AsyncNotifier<ProductPaginationState> {
FutureOr<ProductPaginationState> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref =
this.ref
as $Ref<AsyncValue<ProductPaginationState>, ProductPaginationState>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<
AsyncValue<ProductPaginationState>,
ProductPaginationState
>,
AsyncValue<ProductPaginationState>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// Provider for searching products with pagination
@ProviderFor(ProductSearch)
const productSearchProvider = ProductSearchFamily._();
/// Provider for searching products with pagination
final class ProductSearchProvider
extends $AsyncNotifierProvider<ProductSearch, ProductPaginationState> {
/// Provider for searching products with pagination
const ProductSearchProvider._({
required ProductSearchFamily super.from,
required String super.argument,
}) : super(
retry: null,
name: r'productSearchProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$productSearchHash();
@override
String toString() {
return r'productSearchProvider'
''
'($argument)';
}
@$internal
@override
ProductSearch create() => ProductSearch();
@override
bool operator ==(Object other) {
return other is ProductSearchProvider && other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$productSearchHash() => r'86946a7cf6722822ed205af5d4ec2a8f5ba5ca48';
/// Provider for searching products with pagination
final class ProductSearchFamily extends $Family
with
$ClassFamilyOverride<
ProductSearch,
AsyncValue<ProductPaginationState>,
ProductPaginationState,
FutureOr<ProductPaginationState>,
String
> {
const ProductSearchFamily._()
: super(
retry: null,
name: r'productSearchProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
/// Provider for searching products with pagination
ProductSearchProvider call(String query) =>
ProductSearchProvider._(argument: query, from: this);
@override
String toString() => r'productSearchProvider';
}
/// Provider for searching products with pagination
abstract class _$ProductSearch extends $AsyncNotifier<ProductPaginationState> {
late final _$args = ref.$arg as String;
String get query => _$args;
FutureOr<ProductPaginationState> build(String query);
@$mustCallSuper
@override
void runBuild() {
final created = build(_$args);
final ref =
this.ref
as $Ref<AsyncValue<ProductPaginationState>, ProductPaginationState>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<
AsyncValue<ProductPaginationState>,
ProductPaginationState
>,
AsyncValue<ProductPaginationState>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// Search query provider for products
@ProviderFor(SearchQuery)
const searchQueryProvider = SearchQueryProvider._();
/// Provider for search query
/// Search query provider for products
final class SearchQueryProvider extends $NotifierProvider<SearchQuery, String> {
/// Provider for search query
/// Search query provider for products
const SearchQueryProvider._()
: super(
from: null,
@@ -94,9 +349,9 @@ final class SearchQueryProvider extends $NotifierProvider<SearchQuery, String> {
}
}
String _$searchQueryHash() => r'2c146927785523a0ddf51b23b777a9be4afdc092';
String _$searchQueryHash() => r'0c08fe7fe2ce47cf806a34872f5cf4912fe8c618';
/// Provider for search query
/// Search query provider for products
abstract class _$SearchQuery extends $Notifier<String> {
String build();
@@ -116,49 +371,3 @@ abstract class _$SearchQuery extends $Notifier<String> {
element.handleValue(ref, created);
}
}
/// Provider for filtered products
@ProviderFor(filteredProducts)
const filteredProductsProvider = FilteredProductsProvider._();
/// Provider for filtered products
final class FilteredProductsProvider
extends $FunctionalProvider<List<Product>, List<Product>, List<Product>>
with $Provider<List<Product>> {
/// Provider for filtered products
const FilteredProductsProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'filteredProductsProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$filteredProductsHash();
@$internal
@override
$ProviderElement<List<Product>> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
List<Product> create(Ref ref) {
return filteredProducts(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(List<Product> value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<List<Product>>(value),
);
}
}
String _$filteredProductsHash() => r'e4e0c549c454576fc599713a5237435a8dd4b277';

View File

@@ -3,13 +3,10 @@
/// Contains Riverpod providers for product state management
library;
// Export individual provider files
// Note: products_provider.dart contains multiple providers
// so we only export it to avoid ambiguous exports
export 'products_provider.dart';
// Export datasource provider
export 'product_datasource_provider.dart';
// These are also defined in products_provider.dart, so we don't export them separately
// to avoid ambiguous export errors
// export 'filtered_products_provider.dart';
// export 'search_query_provider.dart';
// export 'selected_category_provider.dart';
// Export state providers
export 'products_provider.dart';
export 'filtered_products_provider.dart';
export 'selected_category_provider.dart';

View File

@@ -1,27 +0,0 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'search_query_provider.g.dart';
/// Search query state provider
/// Manages the current search query string for product filtering
@riverpod
class SearchQuery extends _$SearchQuery {
@override
String build() {
// Initialize with empty search query
return '';
}
/// Update search query
void setQuery(String query) {
state = query.trim();
}
/// Clear search query
void clear() {
state = '';
}
/// Check if search is active
bool get isSearching => state.isNotEmpty;
}

View File

@@ -1,71 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'search_query_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Search query state provider
/// Manages the current search query string for product filtering
@ProviderFor(SearchQuery)
const searchQueryProvider = SearchQueryProvider._();
/// Search query state provider
/// Manages the current search query string for product filtering
final class SearchQueryProvider extends $NotifierProvider<SearchQuery, String> {
/// Search query state provider
/// Manages the current search query string for product filtering
const SearchQueryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'searchQueryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$searchQueryHash();
@$internal
@override
SearchQuery create() => SearchQuery();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(String value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<String>(value),
);
}
}
String _$searchQueryHash() => r'62191c640ca9424065338a26c1af5c4695a46ef5';
/// Search query state provider
/// Manages the current search query string for product filtering
abstract class _$SearchQuery extends $Notifier<String> {
String build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<String, String>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<String, String>,
String,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}