8.1 KiB
Products Feature
This feature implements the complete products catalog browsing functionality for the Worker mobile app using clean architecture principles.
Architecture
The feature follows a clean architecture pattern with three distinct layers:
Domain Layer (domain/)
Pure business logic with no dependencies on Flutter or data sources.
-
Entities (
entities/):Product: Product business entity with price calculations, stock status, and discount logicCategory: Product category for filtering
-
Repositories (
repositories/):ProductsRepository: Abstract interface defining data operations
-
Use Cases (
usecases/):GetProducts: Retrieve products with optional category filteringSearchProducts: Search products by query stringGetCategories: Retrieve all product categories
Data Layer (data/)
Handles data persistence and retrieval.
-
Models (
models/):ProductModel: Hive-compatible product data model (Type ID: 20)CategoryModel: Hive-compatible category data model (Type ID: 21)
-
Data Sources (
datasources/):ProductsLocalDataSource: Mock data provider with 10 sample products across 6 categories
-
Repositories (
repositories/):ProductsRepositoryImpl: Concrete implementation of ProductsRepository
Presentation Layer (presentation/)
UI components and state management.
-
Providers (
providers/):ProductsProvider: Main provider for filtered products (category + search)CategoriesProvider: Categories list providerSelectedCategoryProvider: Current selected category stateSearchQueryProvider: Current search query stateAllProductsProvider: Unfiltered products provider
-
Pages (
pages/):ProductsPage: Main products browsing page with search, filters, and grid
-
Widgets (
widgets/):ProductSearchBar: Search input with clear buttonCategoryFilterChips: Horizontal scrolling category chipsProductCard: Product display card with image, price, stock status, and add to cartProductGrid: 2-column responsive grid layout
Features
Product Display
- 2-column responsive grid layout
- Product image with caching (cached_network_image)
- Product name, SKU, and price
- Price per unit display (e.g., "450.000đ/m²")
- Sale price with discount badge
- Stock status indicator
- Low stock warning badge
- Add to cart button
Filtering & Search
- Real-time search across product name, SKU, and description
- Category filtering with 6 categories:
- Tất cả (All)
- Gạch lát nền (Floor tiles)
- Gạch ốp tường (Wall tiles)
- Gạch trang trí (Decorative tiles)
- Gạch ngoài trời (Outdoor tiles)
- Phụ kiện (Accessories)
- Combined search + category filtering
UI/UX Features
- Pull-to-refresh support
- Loading states with CustomLoadingIndicator
- Error states with retry button
- Empty states with helpful messages
- Vietnamese localization
- Material 3 design system
- Responsive layout
- Optimized image caching
- Smooth scrolling performance
Mock Data
The feature includes 10 sample products:
- Gạch men cao cấp 60x60 - Premium glazed tiles (450.000đ/m²)
- Gạch granite nhập khẩu - Imported granite (680.000đ/m², sale: 620.000đ)
- Gạch mosaic trang trí - Decorative mosaic (320.000đ/m²)
- Gạch 3D họa tiết - 3D patterned tiles (750.000đ/m², sale: 680.000đ)
- Gạch ceramic chống trượt - Anti-slip ceramic (380.000đ/m²)
- Gạch terrazzo đá mài - Terrazzo tiles (890.000đ/m², sale: 820.000đ)
- Gạch ốp tường bếp - Kitchen wall tiles (280.000đ/m²)
- Gạch sân vườn chống rêu - Anti-mold garden tiles (420.000đ/m², sale: 380.000đ)
- Keo dán gạch chuyên dụng - Tile adhesive (180.000đ/bao)
- Keo chà ron màu - Colored grout (120.000đ/bao, sale: 99.000đ)
All products include:
- High-quality Unsplash images
- Detailed Vietnamese descriptions
- Brand attribution (Eurotile or Vasta Stone)
- Stock quantities
- Created timestamps
State Management
The feature uses Riverpod 3.0 with code generation:
// Watch products (filtered by category and search)
final productsAsync = ref.watch(productsProvider);
// Update search query
ref.read(searchQueryProvider.notifier).updateQuery('gạch men');
// Update selected category
ref.read(selectedCategoryProvider.notifier).updateCategory('floor_tiles');
// Refresh products
await ref.read(productsProvider.notifier).refresh();
Navigation
The products page is registered in the app router:
context.goProducts(); // Navigate to products page
context.go(RouteNames.products); // Using route name
Dependencies
flutter_riverpod: ^3.0.0 - State managementriverpod_annotation: ^3.0.0 - Code generationhive_ce: ^2.6.0 - Local databasecached_network_image: ^3.3.1 - Image cachingshimmer: ^3.0.0 - Loading placeholdersintl: ^0.20.0 - Vietnamese number formattinggo_router: ^14.6.2 - Navigation
Future Enhancements
- Product detail page
- Add to cart functionality
- Cart state management
- Product favorites/wishlist
- Advanced filters (price range, brand, etc.)
- Sort options (price, name, popularity)
- Load more / pagination
- Product comparison
- Recent viewed products
- Related products recommendations
- API integration (replace mock data)
Testing
To run tests for this feature:
# Unit tests
flutter test test/features/products/domain/
flutter test test/features/products/data/
# Widget tests
flutter test test/features/products/presentation/widgets/
# Integration tests
flutter test integration_test/products_test.dart
Code Generation
After making changes to providers or models, run:
dart run build_runner build --delete-conflicting-outputs
File Structure
lib/features/products/
├── domain/
│ ├── entities/
│ │ ├── product.dart
│ │ └── category.dart
│ ├── repositories/
│ │ └── products_repository.dart
│ └── usecases/
│ ├── get_products.dart
│ ├── search_products.dart
│ └── get_categories.dart
├── data/
│ ├── models/
│ │ ├── product_model.dart
│ │ ├── product_model.g.dart
│ │ ├── category_model.dart
│ │ └── category_model.g.dart
│ ├── datasources/
│ │ └── products_local_datasource.dart
│ └── repositories/
│ └── products_repository_impl.dart
├── presentation/
│ ├── providers/
│ │ ├── products_provider.dart
│ │ ├── products_provider.g.dart
│ │ ├── categories_provider.dart
│ │ ├── categories_provider.g.dart
│ │ ├── selected_category_provider.dart
│ │ ├── selected_category_provider.g.dart
│ │ ├── search_query_provider.dart
│ │ └── search_query_provider.g.dart
│ ├── pages/
│ │ └── products_page.dart
│ └── widgets/
│ ├── product_search_bar.dart
│ ├── category_filter_chips.dart
│ ├── product_card.dart
│ └── product_grid.dart
└── README.md
Usage Example
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:worker/features/products/presentation/pages/products_page.dart';
// Navigate to products page
void navigateToProducts(BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const ProductsPage()),
);
}
// Or using go_router
context.goProducts();
Contributing
When adding new features to this module:
- Follow the clean architecture pattern
- Add domain entities first
- Implement repository interfaces
- Create use cases for business logic
- Add data models with Hive annotations
- Implement data sources
- Create Riverpod providers
- Build UI widgets
- Update this README
- Add tests
License
This feature is part of the Worker Mobile App project.