fix
This commit is contained in:
@@ -72,7 +72,7 @@ class AppRouter {
|
|||||||
context.go('/warehouses');
|
context.go('/warehouses');
|
||||||
});
|
});
|
||||||
return const _ErrorScreen(
|
return const _ErrorScreen(
|
||||||
message: 'Warehouse data is required',
|
message: 'Yêu cầu dữ liệu kho',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ class AppRouter {
|
|||||||
context.go('/warehouses');
|
context.go('/warehouses');
|
||||||
});
|
});
|
||||||
return const _ErrorScreen(
|
return const _ErrorScreen(
|
||||||
message: 'Invalid product parameters',
|
message: 'Tham số sản phẩm không hợp lệ',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ class AppRouter {
|
|||||||
context.go('/warehouses');
|
context.go('/warehouses');
|
||||||
});
|
});
|
||||||
return const _ErrorScreen(
|
return const _ErrorScreen(
|
||||||
message: 'Invalid product detail parameters',
|
message: 'Tham số chi tiết sản phẩm không hợp lệ',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ class AppRouter {
|
|||||||
errorBuilder: (context, state) {
|
errorBuilder: (context, state) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Page Not Found'),
|
title: const Text('Không tìm thấy trang'),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -176,12 +176,12 @@ class AppRouter {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'Page Not Found',
|
'Không tìm thấy trang',
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'The page "${state.uri.path}" does not exist.',
|
'Trang "${state.uri.path}" không tồn tại.',
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
@@ -190,7 +190,7 @@ class AppRouter {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => context.go('/login'),
|
onPressed: () => context.go('/login'),
|
||||||
child: const Text('Go to Login'),
|
child: const Text('Về trang đăng nhập'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -283,7 +283,7 @@ class _ErrorScreen extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Error'),
|
title: const Text('Lỗi'),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -296,7 +296,7 @@ class _ErrorScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'Navigation Error',
|
'Lỗi điều hướng',
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -313,7 +313,7 @@ class _ErrorScreen extends StatelessWidget {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => context.go('/warehouses'),
|
onPressed: () => context.go('/warehouses'),
|
||||||
child: const Text('Go to Warehouses'),
|
child: const Text('Về trang kho'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class ProductStageEntity extends Equatable {
|
|||||||
|
|
||||||
/// Get display name for the stage
|
/// Get display name for the stage
|
||||||
/// Returns "No Stage" if stageName is null
|
/// Returns "No Stage" if stageName is null
|
||||||
String get displayName => stageName ?? 'No Stage';
|
String get displayName => stageName ?? 'Không tên';
|
||||||
|
|
||||||
/// Check if this is a valid stage (has a stage name)
|
/// Check if this is a valid stage (has a stage name)
|
||||||
bool get hasStage => stageName != null && stageName!.isNotEmpty;
|
bool get hasStage => stageName != null && stageName!.isNotEmpty;
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onRefresh() async {
|
Future<void> _onRefresh() async {
|
||||||
await ref.read(productDetailProvider(_providerKey).notifier).refreshProductDetail(
|
// await ref.read(productDetailProvider(_providerKey).notifier).refreshProductDetail(
|
||||||
widget.warehouseId,
|
// widget.warehouseId,
|
||||||
widget.productId,
|
// widget.productId,
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
void _clearControllers() {
|
void _clearControllers() {
|
||||||
@@ -114,7 +114,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
final productName = stages.isNotEmpty ? stages.first.productName : 'Product';
|
final productName = stages.isNotEmpty ? stages.first.productName : 'Product';
|
||||||
|
|
||||||
// Capitalize first letter of operation type
|
// Capitalize first letter of operation type
|
||||||
final operationTitle = widget.operationType == 'import' ? 'Import' : 'Export';
|
final operationTitle = widget.operationType == 'import' ? 'Nhập' : 'Xuất';
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -137,7 +137,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
onPressed: _onRefresh,
|
onPressed: _onRefresh,
|
||||||
tooltip: 'Refresh',
|
tooltip: 'Làm mới',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -215,7 +215,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'No stages found',
|
'Không tìm thấy công đoạn',
|
||||||
style: theme.textTheme.titleLarge,
|
style: theme.textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -244,14 +244,14 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'Stage Not Found',
|
'Không tìm thấy công đoạn',
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
color: theme.colorScheme.error,
|
color: theme.colorScheme.error,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'Stage with ID ${widget.stageId} was not found in this product.',
|
'Công đoạn với ID ${widget.stageId} không được tìm thấy trong sản phẩm này.',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: theme.textTheme.bodyMedium,
|
style: theme.textTheme.bodyMedium,
|
||||||
),
|
),
|
||||||
@@ -293,8 +293,8 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.stageId != null
|
widget.stageId != null
|
||||||
? 'Selected Stage'
|
? 'Công đoạn'
|
||||||
: 'Production Stages (${displayStages.length})',
|
: 'Công đoạn (${displayStages.length})',
|
||||||
style: theme.textTheme.titleSmall?.copyWith(
|
style: theme.textTheme.titleSmall?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -383,32 +383,32 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
|
|
||||||
_buildSectionCard(
|
_buildSectionCard(
|
||||||
theme: theme,
|
theme: theme,
|
||||||
title: 'Stage Information',
|
title: 'Thông tin công đoạn',
|
||||||
icon: Icons.info_outlined,
|
icon: Icons.info_outlined,
|
||||||
children: [
|
children: [
|
||||||
_buildInfoRow('Product ID', '${stageToShow.productId}'),
|
_buildInfoRow('Mã sản phẩm', '${stageToShow.productId}'),
|
||||||
if (stageToShow.productStageId != null)
|
if (stageToShow.productStageId != null)
|
||||||
_buildInfoRow('Stage ID', '${stageToShow.productStageId}'),
|
_buildInfoRow('Mã công đoạn', '${stageToShow.productStageId}'),
|
||||||
if (stageToShow.actionTypeId != null)
|
if (stageToShow.actionTypeId != null)
|
||||||
_buildInfoRow('Action Type ID', '${stageToShow.actionTypeId}'),
|
_buildInfoRow('Mã loại thao tác', '${stageToShow.actionTypeId}'),
|
||||||
_buildInfoRow('Stage Name', stageToShow.displayName),
|
_buildInfoRow('Tên công đoạn', stageToShow.displayName),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
// Current Quantity information
|
// Current Quantity information
|
||||||
_buildSectionCard(
|
_buildSectionCard(
|
||||||
theme: theme,
|
theme: theme,
|
||||||
title: 'Current Quantities',
|
title: 'Số lượng hiện tại',
|
||||||
icon: Icons.info_outlined,
|
icon: Icons.info_outlined,
|
||||||
children: [
|
children: [
|
||||||
_buildInfoRow('Passed Quantity', '${stageToShow.passedQuantity}'),
|
_buildInfoRow('Số lượng đạt', '${stageToShow.passedQuantity}'),
|
||||||
_buildInfoRow(
|
_buildInfoRow(
|
||||||
'Passed Weight',
|
'Khối lượng đạt',
|
||||||
'${stageToShow.passedQuantityWeight.toStringAsFixed(2)} kg',
|
'${stageToShow.passedQuantityWeight.toStringAsFixed(2)} kg',
|
||||||
),
|
),
|
||||||
_buildInfoRow('Issued Quantity', '${stageToShow.issuedQuantity}'),
|
_buildInfoRow('Số lượng lỗi', '${stageToShow.issuedQuantity}'),
|
||||||
_buildInfoRow(
|
_buildInfoRow(
|
||||||
'Issued Weight',
|
'Khối lượng lỗi',
|
||||||
'${stageToShow.issuedQuantityWeight.toStringAsFixed(2)} kg',
|
'${stageToShow.issuedQuantityWeight.toStringAsFixed(2)} kg',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -417,29 +417,29 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
// Add New Quantities section
|
// Add New Quantities section
|
||||||
_buildSectionCard(
|
_buildSectionCard(
|
||||||
theme: theme,
|
theme: theme,
|
||||||
title: 'Add New Quantities',
|
title: 'Thêm số lượng mới',
|
||||||
icon: Icons.add_circle_outline,
|
icon: Icons.add_circle_outline,
|
||||||
children: [
|
children: [
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Passed Quantity',
|
label: 'Số lượng đạt',
|
||||||
controller: _passedQuantityController,
|
controller: _passedQuantityController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Passed Weight (kg)',
|
label: 'Khối lượng đạt (kg)',
|
||||||
controller: _passedWeightController,
|
controller: _passedWeightController,
|
||||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Issued Quantity',
|
label: 'Số lượng lỗi',
|
||||||
controller: _issuedQuantityController,
|
controller: _issuedQuantityController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Issued Weight (kg)',
|
label: 'Khối lượng lỗi (kg)',
|
||||||
controller: _issuedWeightController,
|
controller: _issuedWeightController,
|
||||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||||
theme: theme,
|
theme: theme,
|
||||||
@@ -450,7 +450,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
_buildSectionCard(theme: theme, title: "Nhân viên", icon: Icons.people, children: [
|
_buildSectionCard(theme: theme, title: "Nhân viên", icon: Icons.people, children: [
|
||||||
// Warehouse User Dropdown
|
// Warehouse User Dropdown
|
||||||
_buildUserDropdown(
|
_buildUserDropdown(
|
||||||
label: 'Warehouse User',
|
label: 'Người dùng kho',
|
||||||
value: _selectedWarehouseUser,
|
value: _selectedWarehouseUser,
|
||||||
users: ref.watch(usersListProvider)
|
users: ref.watch(usersListProvider)
|
||||||
.where((user) => user.isWareHouseUser)
|
.where((user) => user.isWareHouseUser)
|
||||||
@@ -464,7 +464,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
),
|
),
|
||||||
// All Employees Dropdown
|
// All Employees Dropdown
|
||||||
_buildUserDropdown(
|
_buildUserDropdown(
|
||||||
label: 'Employee',
|
label: 'Nhân viên',
|
||||||
value: _selectedEmployee,
|
value: _selectedEmployee,
|
||||||
users: ref.watch(usersListProvider),
|
users: ref.watch(usersListProvider),
|
||||||
onChanged: (user) {
|
onChanged: (user) {
|
||||||
@@ -686,7 +686,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
'Product ID: ${stage.productId}',
|
'Sản phẩm ID: ${stage.productId}',
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
'Code: ${product.code}',
|
'Mã: ${product.code}',
|
||||||
style: textTheme.bodySmall?.copyWith(
|
style: textTheme.bodySmall?.copyWith(
|
||||||
color: theme.colorScheme.primary,
|
color: theme.colorScheme.primary,
|
||||||
),
|
),
|
||||||
@@ -65,7 +65,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Active',
|
'Hoạt động',
|
||||||
style: textTheme.labelSmall?.copyWith(
|
style: textTheme.labelSmall?.copyWith(
|
||||||
color: Colors.green,
|
color: Colors.green,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -84,7 +84,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _InfoItem(
|
child: _InfoItem(
|
||||||
label: 'Weight',
|
label: 'Khối lượng',
|
||||||
value: '${product.weight.toStringAsFixed(2)} kg',
|
value: '${product.weight.toStringAsFixed(2)} kg',
|
||||||
icon: Icons.fitness_center,
|
icon: Icons.fitness_center,
|
||||||
),
|
),
|
||||||
@@ -92,7 +92,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _InfoItem(
|
child: _InfoItem(
|
||||||
label: 'Pieces',
|
label: 'Số lượng',
|
||||||
value: product.pieces.toString(),
|
value: product.pieces.toString(),
|
||||||
icon: Icons.inventory_2,
|
icon: Icons.inventory_2,
|
||||||
),
|
),
|
||||||
@@ -107,7 +107,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _InfoItem(
|
child: _InfoItem(
|
||||||
label: 'In Stock (Pieces)',
|
label: 'Tồn kho (SL)',
|
||||||
value: product.piecesInStock.toString(),
|
value: product.piecesInStock.toString(),
|
||||||
icon: Icons.warehouse,
|
icon: Icons.warehouse,
|
||||||
color: product.piecesInStock > 0
|
color: product.piecesInStock > 0
|
||||||
@@ -118,7 +118,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _InfoItem(
|
child: _InfoItem(
|
||||||
label: 'In Stock (Weight)',
|
label: 'Tồn kho (KL)',
|
||||||
value: '${product.weightInStock.toStringAsFixed(2)} kg',
|
value: '${product.weightInStock.toStringAsFixed(2)} kg',
|
||||||
icon: Icons.scale,
|
icon: Icons.scale,
|
||||||
color: product.weightInStock > 0
|
color: product.weightInStock > 0
|
||||||
@@ -142,7 +142,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Conversion Rate',
|
'Tỷ lệ chuyển đổi',
|
||||||
style: textTheme.bodyMedium?.copyWith(
|
style: textTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -170,7 +170,7 @@ class ProductListItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
'Barcode: ${product.barcode}',
|
'Mã vạch: ${product.barcode}',
|
||||||
style: textTheme.bodySmall?.copyWith(
|
style: textTheme.bodySmall?.copyWith(
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class WarehouseCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
'Code: ${warehouse.code}',
|
'Mã: ${warehouse.code}',
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
color: colorScheme.onSurfaceVariant,
|
color: colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
@@ -68,7 +68,7 @@ class WarehouseCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
'Items: ${warehouse.totalCount}',
|
'Sản phẩm: ${warehouse.totalCount}',
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
color: colorScheme.onSurfaceVariant,
|
color: colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
@@ -104,7 +104,7 @@ class WarehouseCard extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'NG Warehouse',
|
'Kho NG',
|
||||||
style: theme.textTheme.labelSmall?.copyWith(
|
style: theme.textTheme.labelSmall?.copyWith(
|
||||||
color: colorScheme.onErrorContainer,
|
color: colorScheme.onErrorContainer,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|||||||
Reference in New Issue
Block a user