save
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../../core/di/providers.dart';
|
||||
import '../../../users/domain/entities/user_entity.dart';
|
||||
import '../../data/models/create_product_warehouse_request.dart';
|
||||
import '../../domain/entities/product_stage_entity.dart';
|
||||
|
||||
/// Product detail page
|
||||
@@ -13,6 +14,7 @@ class ProductDetailPage extends ConsumerStatefulWidget {
|
||||
final int productId;
|
||||
final String warehouseName;
|
||||
final int? stageId;
|
||||
final String operationType;
|
||||
|
||||
const ProductDetailPage({
|
||||
super.key,
|
||||
@@ -20,6 +22,7 @@ class ProductDetailPage extends ConsumerStatefulWidget {
|
||||
required this.productId,
|
||||
required this.warehouseName,
|
||||
this.stageId,
|
||||
this.operationType = 'import',
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -107,17 +110,23 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
final error = productDetailState.error;
|
||||
final selectedIndex = productDetailState.selectedStageIndex;
|
||||
|
||||
// Get product name from stages if available
|
||||
final productName = stages.isNotEmpty ? stages.first.productName : 'Product';
|
||||
|
||||
// Capitalize first letter of operation type
|
||||
final operationTitle = widget.operationType == 'import' ? 'Import' : 'Export';
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Product Stages',
|
||||
operationTitle,
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
widget.warehouseName,
|
||||
productName,
|
||||
style: textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -467,17 +476,32 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
),
|
||||
]),
|
||||
|
||||
// Add button
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton.icon(
|
||||
onPressed: () => _addNewQuantities(stageToShow),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Add Quantities'),
|
||||
style: FilledButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
// Action buttons
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _printQuantities(stageToShow),
|
||||
icon: const Icon(Icons.print),
|
||||
label: const Text('Print'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton.icon(
|
||||
onPressed: () => _addNewQuantities(stageToShow),
|
||||
icon: const Icon(Icons.save),
|
||||
label: const Text('Save'),
|
||||
style: FilledButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -489,7 +513,17 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
void _addNewQuantities(ProductStageEntity stage) {
|
||||
void _printQuantities(ProductStageEntity stage) {
|
||||
// TODO: Implement print functionality
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Print functionality coming soon'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _addNewQuantities(ProductStageEntity stage) async {
|
||||
// Parse the values from text fields
|
||||
final passedQuantity = int.tryParse(_passedQuantityController.text) ?? 0;
|
||||
final passedWeight = double.tryParse(_passedWeightController.text) ?? 0.0;
|
||||
@@ -508,31 +542,115 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Implement API call to add new quantities
|
||||
// For now, just show a success message
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Added: Passed Q=$passedQuantity, W=$passedWeight | Issued Q=$issuedQuantity, W=$issuedWeight',
|
||||
// Validate that both users are selected
|
||||
if (_selectedEmployee == null || _selectedWarehouseUser == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Please select both Employee and Warehouse User'),
|
||||
backgroundColor: Colors.orange,
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
duration: const Duration(seconds: 2),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading dialog
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
|
||||
// Log the values for debugging
|
||||
debugPrint('Adding new quantities for stage ${stage.productStageId}:');
|
||||
debugPrint(' Warehouse User: ${_selectedWarehouseUser?.fullName ?? "Not selected"}');
|
||||
debugPrint(' Warehouse User ID: ${_selectedWarehouseUser?.id}');
|
||||
debugPrint(' Employee: ${_selectedEmployee?.fullName ?? "Not selected"}');
|
||||
debugPrint(' Employee ID: ${_selectedEmployee?.id}');
|
||||
debugPrint(' Passed Quantity: $passedQuantity');
|
||||
debugPrint(' Passed Weight: $passedWeight');
|
||||
debugPrint(' Issued Quantity: $issuedQuantity');
|
||||
debugPrint(' Issued Weight: $issuedWeight');
|
||||
try {
|
||||
// Determine actionTypeId based on operation type
|
||||
// 4 = Import, 5 = Export
|
||||
final typeId = widget.operationType == 'import' ? 4 : 5;
|
||||
final actionTypeId = widget.operationType == 'import' ? 1 : 2;
|
||||
|
||||
// Clear the text fields after successful add
|
||||
_clearControllers();
|
||||
// Create request with all required fields
|
||||
final request = CreateProductWarehouseRequest(
|
||||
typeId: typeId, // Import type
|
||||
productId: stage.productId,
|
||||
stageId: stage.stageId ?? 0,
|
||||
orderId: null,
|
||||
recordDate: DateTime.now().toIso8601String(),
|
||||
passedQuantityWeight: passedWeight,
|
||||
passedQuantity: passedQuantity,
|
||||
issuedQuantityWeight: issuedWeight,
|
||||
issuedQuantity: issuedQuantity,
|
||||
responsibleUserId: _selectedEmployee!.id,
|
||||
description: '',
|
||||
productName: stage.productName,
|
||||
productCode: stage.productCode,
|
||||
stockPassedQuantityWeight: stage.passedQuantityWeight,
|
||||
stockPassedQuantity: stage.passedQuantity,
|
||||
stockIssuedQuantity: stage.issuedQuantity,
|
||||
stockIssuedQuantityWeight: stage.issuedQuantityWeight,
|
||||
receiverUserId: _selectedWarehouseUser!.id,
|
||||
actionTypeId: actionTypeId,
|
||||
wareHouseId: widget.warehouseId,
|
||||
productStageId: stage.productStageId ?? 0,
|
||||
isConfirm: true,
|
||||
);
|
||||
|
||||
// Call the repository to create product warehouse entry
|
||||
final repository = ref.read(productsRepositoryProvider);
|
||||
final result = await repository.createProductWarehouse(request);
|
||||
|
||||
// Dismiss loading dialog
|
||||
if (mounted) Navigator.of(context).pop();
|
||||
|
||||
result.fold(
|
||||
(failure) {
|
||||
// Show error message
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to add quantities: ${failure.message}'),
|
||||
backgroundColor: Colors.red,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
(_) {
|
||||
// Success - show success message
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Quantities added successfully!'),
|
||||
backgroundColor: Colors.green,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
// Clear the text fields after successful add
|
||||
_clearControllers();
|
||||
|
||||
// Refresh the product detail to show updated quantities
|
||||
ref.read(productDetailProvider(_providerKey).notifier).refreshProductDetail(
|
||||
widget.warehouseId,
|
||||
widget.productId,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
// Dismiss loading dialog
|
||||
if (mounted) Navigator.of(context).pop();
|
||||
|
||||
// Show error message
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Error: ${e.toString()}'),
|
||||
backgroundColor: Colors.red,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildStageHeader(ProductStageEntity stage, ThemeData theme) {
|
||||
|
||||
@@ -214,6 +214,7 @@ class _ProductsPageState extends ConsumerState<ProductsPage>
|
||||
warehouseId: widget.warehouseId,
|
||||
productId: productId,
|
||||
warehouseName: widget.warehouseName,
|
||||
operationType: widget.operationType,
|
||||
stageId: stageId,
|
||||
);
|
||||
}
|
||||
@@ -466,6 +467,7 @@ class _ProductsPageState extends ConsumerState<ProductsPage>
|
||||
warehouseId: widget.warehouseId,
|
||||
productId: product.id,
|
||||
warehouseName: widget.warehouseName,
|
||||
operationType: widget.operationType,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user