aaa
This commit is contained in:
@@ -58,6 +58,12 @@ class ApiEndpoints {
|
||||
/// Response: List of products
|
||||
static const String products = '/portalProduct/getAllProduct';
|
||||
|
||||
/// Get product stage in warehouse
|
||||
/// POST: /portalWareHouse/GetProductStageInWareHouse
|
||||
/// Body: { "WareHouseId": int, "ProductId": int }
|
||||
/// Response: Product details with stage information
|
||||
static const String productDetail = '/portalWareHouse/GetProductStageInWareHouse';
|
||||
|
||||
/// Get product by ID
|
||||
/// GET: (requires auth token)
|
||||
/// Parameter: productId
|
||||
|
||||
@@ -7,8 +7,11 @@ import '../../features/auth/domain/usecases/login_usecase.dart';
|
||||
import '../../features/auth/presentation/providers/auth_provider.dart';
|
||||
import '../../features/products/data/datasources/products_remote_datasource.dart';
|
||||
import '../../features/products/data/repositories/products_repository_impl.dart';
|
||||
import '../../features/products/domain/entities/product_stage_entity.dart';
|
||||
import '../../features/products/domain/repositories/products_repository.dart';
|
||||
import '../../features/products/domain/usecases/get_product_detail_usecase.dart';
|
||||
import '../../features/products/domain/usecases/get_products_usecase.dart';
|
||||
import '../../features/products/presentation/providers/product_detail_provider.dart';
|
||||
import '../../features/products/presentation/providers/products_provider.dart';
|
||||
import '../../features/warehouse/data/datasources/warehouse_remote_datasource.dart';
|
||||
import '../../features/warehouse/data/repositories/warehouse_repository_impl.dart';
|
||||
@@ -269,6 +272,13 @@ final getProductsUseCaseProvider = Provider<GetProductsUseCase>((ref) {
|
||||
return GetProductsUseCase(repository);
|
||||
});
|
||||
|
||||
/// Get product detail use case provider
|
||||
/// Encapsulates product detail fetching business logic
|
||||
final getProductDetailUseCaseProvider = Provider<GetProductDetailUseCase>((ref) {
|
||||
final repository = ref.watch(productsRepositoryProvider);
|
||||
return GetProductDetailUseCase(repository);
|
||||
});
|
||||
|
||||
// Presentation Layer
|
||||
|
||||
/// Products state notifier provider
|
||||
@@ -340,6 +350,48 @@ final productsErrorProvider = Provider<String?>((ref) {
|
||||
return productsState.error;
|
||||
});
|
||||
|
||||
/// Product detail state notifier provider
|
||||
/// Manages product detail state for a specific product in a warehouse
|
||||
/// This needs to be a family provider to support multiple product details
|
||||
final productDetailProvider =
|
||||
StateNotifierProvider.family<ProductDetailNotifier, ProductDetailState, String>(
|
||||
(ref, _) {
|
||||
final getProductDetailUseCase = ref.watch(getProductDetailUseCaseProvider);
|
||||
return ProductDetailNotifier(getProductDetailUseCase);
|
||||
},
|
||||
);
|
||||
|
||||
/// Convenient providers for product detail state
|
||||
|
||||
/// Provider to get product stages list
|
||||
/// Usage: ref.watch(productStagesProvider(key))
|
||||
final productStagesProvider = Provider.family<List<ProductStageEntity>, String>((ref, key) {
|
||||
final state = ref.watch(productDetailProvider(key));
|
||||
return state.stages;
|
||||
});
|
||||
|
||||
/// Provider to get selected product stage
|
||||
/// Usage: ref.watch(selectedProductStageProvider(key))
|
||||
final selectedProductStageProvider = Provider.family<ProductStageEntity?, String>((ref, key) {
|
||||
final state = ref.watch(productDetailProvider(key));
|
||||
return state.selectedStage;
|
||||
});
|
||||
|
||||
/// Provider to check if product detail is loading
|
||||
/// Usage: ref.watch(isProductDetailLoadingProvider(key))
|
||||
final isProductDetailLoadingProvider = Provider.family<bool, String>((ref, key) {
|
||||
final state = ref.watch(productDetailProvider(key));
|
||||
return state.isLoading;
|
||||
});
|
||||
|
||||
/// Provider to get product detail error
|
||||
/// Returns null if no error
|
||||
/// Usage: ref.watch(productDetailErrorProvider(key))
|
||||
final productDetailErrorProvider = Provider.family<String?, String>((ref, key) {
|
||||
final state = ref.watch(productDetailProvider(key));
|
||||
return state.error;
|
||||
});
|
||||
|
||||
/// ========================================================================
|
||||
/// USAGE EXAMPLES
|
||||
/// ========================================================================
|
||||
|
||||
@@ -7,6 +7,7 @@ import '../../features/auth/di/auth_dependency_injection.dart';
|
||||
import '../../features/warehouse/presentation/pages/warehouse_selection_page.dart';
|
||||
import '../../features/operation/presentation/pages/operation_selection_page.dart';
|
||||
import '../../features/products/presentation/pages/products_page.dart';
|
||||
import '../../features/products/presentation/pages/product_detail_page.dart';
|
||||
import '../../features/warehouse/domain/entities/warehouse_entity.dart';
|
||||
import '../storage/secure_storage.dart';
|
||||
|
||||
@@ -121,6 +122,49 @@ class AppRouter {
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
/// Product Detail Route
|
||||
/// Path: /product-detail
|
||||
/// Takes warehouseId, productId, and warehouseName as extra parameter
|
||||
/// Shows detailed information for a specific product
|
||||
GoRoute(
|
||||
path: '/product-detail',
|
||||
name: 'product-detail',
|
||||
builder: (context, state) {
|
||||
final params = state.extra as Map<String, dynamic>?;
|
||||
|
||||
if (params == null) {
|
||||
// If no params, redirect to warehouses
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.go('/warehouses');
|
||||
});
|
||||
return const _ErrorScreen(
|
||||
message: 'Product detail parameters are required',
|
||||
);
|
||||
}
|
||||
|
||||
// Extract required parameters
|
||||
final warehouseId = params['warehouseId'] as int?;
|
||||
final productId = params['productId'] as int?;
|
||||
final warehouseName = params['warehouseName'] as String?;
|
||||
|
||||
// Validate parameters
|
||||
if (warehouseId == null || productId == null || warehouseName == null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.go('/warehouses');
|
||||
});
|
||||
return const _ErrorScreen(
|
||||
message: 'Invalid product detail parameters',
|
||||
);
|
||||
}
|
||||
|
||||
return ProductDetailPage(
|
||||
warehouseId: warehouseId,
|
||||
productId: productId,
|
||||
warehouseName: warehouseName,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
// ==================== Error Handling ====================
|
||||
@@ -326,6 +370,26 @@ extension AppRouterExtension on BuildContext {
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigate to product detail page
|
||||
///
|
||||
/// [warehouseId] - ID of the warehouse
|
||||
/// [productId] - ID of the product to view
|
||||
/// [warehouseName] - Name of the warehouse (for display)
|
||||
void goToProductDetail({
|
||||
required int warehouseId,
|
||||
required int productId,
|
||||
required String warehouseName,
|
||||
}) {
|
||||
push(
|
||||
'/product-detail',
|
||||
extra: {
|
||||
'warehouseId': warehouseId,
|
||||
'productId': productId,
|
||||
'warehouseName': warehouseName,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Pop current route
|
||||
void goBack() => pop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user