update perf

This commit is contained in:
Phuoc Nguyen
2025-12-02 17:32:20 +07:00
parent 211ebdf1d8
commit fc9b5e967f
13 changed files with 254 additions and 200 deletions

View File

@@ -11,7 +11,6 @@ import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/router/app_router.dart';
import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/cart/presentation/providers/cart_provider.dart';
import 'package:worker/features/products/presentation/providers/product_filter_options_provider.dart';
import 'package:worker/features/products/presentation/providers/products_provider.dart';
import 'package:worker/features/products/presentation/widgets/brand_filter_chips.dart';
import 'package:worker/features/products/presentation/widgets/product_filter_drawer.dart';
@@ -36,8 +35,7 @@ class ProductsPage extends ConsumerWidget {
final l10n = AppLocalizations.of(context);
final productsAsync = ref.watch(productsProvider);
// Preload filter options for better UX when opening filter drawer
ref.watch(productFilterOptionsProvider);
// Filter options loaded lazily when filter drawer is opened (not here)
return Scaffold(
backgroundColor: colorScheme.surfaceContainerLowest,
@@ -105,8 +103,10 @@ class ProductsPage extends ConsumerWidget {
),
),
// Brand Filter Chips
const BrandFilterChips(),
// Brand Filter Chips - only show after products are loaded
productsAsync.hasValue
? const BrandFilterChips()
: const SizedBox(height: 48.0),
// Products Grid
Expanded(

View File

@@ -86,49 +86,56 @@ class Products extends _$Products {
// Get repository with injected data sources
final repository = await ref.watch(productsRepositoryProvider.future);
// Fetch first page of products using unified API
// Fetch first page of products
List<Product> products;
// Build filter parameters from filter drawer
final List<String>? itemGroups = filters.productLines.isNotEmpty
? filters.productLines.toList()
: null;
// Check if any filters or search are active
final hasFilters = filters.hasActiveFilters;
final hasSearch = searchQuery.isNotEmpty;
// Use brands from productFiltersProvider (shared by chips and drawer)
final List<String>? brands = filters.brands.isNotEmpty
? filters.brands.toList()
: null;
if (!hasFilters && !hasSearch) {
// No filters/search: Use simple getAllProducts for faster initial load
products = await repository.getAllProducts(
limitStart: 0,
limitPageLength: pageSize,
);
} else {
// Filters/search active: Use getProductsWithFilters
final List<String>? itemGroups = filters.productLines.isNotEmpty
? filters.productLines.toList()
: null;
// Build item attributes from filter drawer (sizes, surfaces, colors)
final List<Map<String, String>> itemAttributes = [];
final List<String>? brands = filters.brands.isNotEmpty
? filters.brands.toList()
: null;
// Add size attributes
for (final size in filters.sizes) {
itemAttributes.add({'attribute': 'Kích thước', 'attribute_value': size});
// Build item attributes from filter drawer (sizes, surfaces, colors)
final List<Map<String, String>> itemAttributes = [];
for (final size in filters.sizes) {
itemAttributes.add({'attribute': 'Kích thước', 'attribute_value': size});
}
for (final surface in filters.surfaces) {
itemAttributes.add({'attribute': 'Bề mặt', 'attribute_value': surface});
}
for (final color in filters.colors) {
itemAttributes.add({'attribute': 'Màu sắc', 'attribute_value': color});
}
final String? keyword = hasSearch ? searchQuery : null;
products = await repository.getProductsWithFilters(
limitStart: 0,
limitPageLength: pageSize,
itemGroups: itemGroups,
brands: brands,
itemAttributes: itemAttributes.isNotEmpty ? itemAttributes : null,
searchKeyword: keyword,
);
}
// Add surface attributes
for (final surface in filters.surfaces) {
itemAttributes.add({'attribute': 'Bề mặt', 'attribute_value': surface});
}
// Add color attributes
for (final color in filters.colors) {
itemAttributes.add({'attribute': 'Màu sắc', 'attribute_value': color});
}
final String? keyword = searchQuery.isNotEmpty ? searchQuery : null;
// Use the comprehensive getProductsWithFilters method
products = await repository.getProductsWithFilters(
limitStart: 0,
limitPageLength: pageSize,
itemGroups: itemGroups,
brands: brands,
itemAttributes: itemAttributes.isNotEmpty ? itemAttributes : null,
searchKeyword: keyword,
);
// If we got less than pageSize, there are no more products
_hasMore = products.length >= pageSize;
_currentPage = 1;
@@ -149,46 +156,54 @@ class Products extends _$Products {
// Calculate pagination parameters
final limitStart = _currentPage * pageSize;
// Build filter parameters (same logic as build() method)
final List<String>? itemGroups = filters.productLines.isNotEmpty
? filters.productLines.toList()
: null;
// Check if any filters or search are active
final hasFilters = filters.hasActiveFilters;
final hasSearch = searchQuery.isNotEmpty;
// Use brands from productFiltersProvider (shared by chips and drawer)
final List<String>? brands = filters.brands.isNotEmpty
? filters.brands.toList()
: null;
List<Product> newProducts;
// Build item attributes from filter drawer (sizes, surfaces, colors)
final List<Map<String, String>> itemAttributes = [];
if (!hasFilters && !hasSearch) {
// No filters/search: Use simple getAllProducts
newProducts = await repository.getAllProducts(
limitStart: limitStart,
limitPageLength: pageSize,
);
} else {
// Filters/search active: Use getProductsWithFilters
final List<String>? itemGroups = filters.productLines.isNotEmpty
? filters.productLines.toList()
: null;
// Add size attributes
for (final size in filters.sizes) {
itemAttributes.add({'attribute': 'Kích thước', 'attribute_value': size});
final List<String>? brands = filters.brands.isNotEmpty
? filters.brands.toList()
: null;
final List<Map<String, String>> itemAttributes = [];
for (final size in filters.sizes) {
itemAttributes.add({'attribute': 'Kích thước', 'attribute_value': size});
}
for (final surface in filters.surfaces) {
itemAttributes.add({'attribute': 'Bề mặt', 'attribute_value': surface});
}
for (final color in filters.colors) {
itemAttributes.add({'attribute': 'Màu sắc', 'attribute_value': color});
}
final String? keyword = hasSearch ? searchQuery : null;
newProducts = await repository.getProductsWithFilters(
limitStart: limitStart,
limitPageLength: pageSize,
itemGroups: itemGroups,
brands: brands,
itemAttributes: itemAttributes.isNotEmpty ? itemAttributes : null,
searchKeyword: keyword,
);
}
// Add surface attributes
for (final surface in filters.surfaces) {
itemAttributes.add({'attribute': 'Bề mặt', 'attribute_value': surface});
}
// Add color attributes
for (final color in filters.colors) {
itemAttributes.add({'attribute': 'Màu sắc', 'attribute_value': color});
}
final String? keyword = searchQuery.isNotEmpty ? searchQuery : null;
// Fetch next page using unified API
final newProducts = await repository.getProductsWithFilters(
limitStart: limitStart,
limitPageLength: pageSize,
itemGroups: itemGroups,
brands: brands,
itemAttributes: itemAttributes.isNotEmpty ? itemAttributes : null,
searchKeyword: keyword,
);
// If we got less than pageSize, there are no more products
_hasMore = newProducts.length >= pageSize;

View File

@@ -228,7 +228,7 @@ final class ProductsProvider
Products create() => Products();
}
String _$productsHash() => r'6c55b22e75b912281feff3a68f84e488ccb7ab79';
String _$productsHash() => r'a4f416712cdbf2e633622c65b1fdc95686e31fa4';
/// Products Provider
///