fix
This commit is contained in:
@@ -19,6 +19,7 @@ class PrintService {
|
||||
required double issuedKg,
|
||||
required int issuedPcs,
|
||||
String? responsibleName,
|
||||
String? receiverName,
|
||||
String? barcodeData,
|
||||
}) async {
|
||||
// Load Vietnamese-compatible fonts using PdfGoogleFonts
|
||||
@@ -323,6 +324,35 @@ class PrintService {
|
||||
|
||||
pw.SizedBox(height: 12),
|
||||
|
||||
|
||||
pw.Container(
|
||||
decoration: pw.BoxDecoration(
|
||||
border: pw.Border.all(color: PdfColors.black, width: 0.5),
|
||||
borderRadius: pw.BorderRadius.circular(8),
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(8),
|
||||
child: pw.Row(
|
||||
children: [
|
||||
pw.Text(
|
||||
'Nhân viên tiếp nhận: ',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10,
|
||||
color: PdfColors.grey700,
|
||||
),
|
||||
),
|
||||
pw.Text(
|
||||
receiverName ?? '-',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
pw.SizedBox(height: 12),
|
||||
|
||||
// Barcode section
|
||||
if (barcodeData != null && barcodeData.isNotEmpty)
|
||||
pw.Center(
|
||||
|
||||
@@ -52,6 +52,9 @@ class SecureStorage {
|
||||
/// Key for storing username
|
||||
static const String _usernameKey = 'username';
|
||||
|
||||
/// Key for storing email
|
||||
static const String _emailKey = 'email';
|
||||
|
||||
// ==================== Token Management ====================
|
||||
|
||||
/// Save access token securely
|
||||
@@ -126,6 +129,24 @@ class SecureStorage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Save email
|
||||
Future<void> saveEmail(String email) async {
|
||||
try {
|
||||
await _storage.write(key: _emailKey, value: email);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to save email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Get email
|
||||
Future<String?> getEmail() async {
|
||||
try {
|
||||
return await _storage.read(key: _emailKey);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to read email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if user is authenticated (has valid access token)
|
||||
Future<bool> isAuthenticated() async {
|
||||
final token = await getAccessToken();
|
||||
|
||||
@@ -31,6 +31,8 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
await secureStorage.saveAccessToken(userModel.accessToken);
|
||||
await secureStorage.saveUserId(userModel.userId);
|
||||
await secureStorage.saveUsername(userModel.username);
|
||||
// Save email (username is the email from login)
|
||||
await secureStorage.saveEmail(request.username);
|
||||
|
||||
if (userModel.refreshToken != null) {
|
||||
await secureStorage.saveRefreshToken(userModel.refreshToken!);
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../../core/di/providers.dart';
|
||||
import '../../../../core/services/print_service.dart';
|
||||
import '../../../../core/storage/secure_storage.dart';
|
||||
import '../../../../core/utils/text_utils.dart';
|
||||
import '../../../users/domain/entities/user_entity.dart';
|
||||
import '../../data/models/create_product_warehouse_request.dart';
|
||||
@@ -55,6 +56,9 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
// Load users from Hive (no API call)
|
||||
await ref.read(usersProvider.notifier).getUsers();
|
||||
|
||||
// Auto-select warehouse user based on stored email
|
||||
await _autoSelectWarehouseUser();
|
||||
|
||||
await ref.read(productDetailProvider(_providerKey).notifier).loadProductDetail(
|
||||
widget.warehouseId,
|
||||
widget.productId,
|
||||
@@ -82,6 +86,43 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// Auto-select warehouse user based on stored email from login
|
||||
Future<void> _autoSelectWarehouseUser() async {
|
||||
try {
|
||||
// Get stored email from secure storage
|
||||
final secureStorage = SecureStorage();
|
||||
final storedEmail = await secureStorage.getEmail();
|
||||
|
||||
if (storedEmail == null || storedEmail.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
print(storedEmail);
|
||||
|
||||
// Get all warehouse users
|
||||
final warehouseUsers = ref.read(usersListProvider)
|
||||
.where((user) => user.isWareHouseUser)
|
||||
.toList();
|
||||
|
||||
// Find user with matching email
|
||||
final matchingUsers = warehouseUsers
|
||||
.where((user) => user.email.toLowerCase() == storedEmail.toLowerCase())
|
||||
.toList();
|
||||
|
||||
final matchingUser = matchingUsers.isNotEmpty ? matchingUsers.first : null;
|
||||
|
||||
// Set selected warehouse user only if a match is found
|
||||
if (matchingUser != null && mounted) {
|
||||
setState(() {
|
||||
_selectedWarehouseUser = matchingUser;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// Silently fail - user can still manually select
|
||||
debugPrint('Error auto-selecting warehouse user: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onRefresh() async {
|
||||
// await ref.read(productDetailProvider(_providerKey).notifier).refreshProductDetail(
|
||||
// widget.warehouseId,
|
||||
@@ -476,7 +517,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
|
||||
// Get responsible user name
|
||||
final responsibleName = '${_selectedWarehouseUser!.name} ${_selectedWarehouseUser!.firstName}';
|
||||
|
||||
final receiverName = '${_selectedEmployee!.name} ${_selectedEmployee!.firstName}';
|
||||
// Generate barcode data (using product code or product ID)
|
||||
final barcodeData = stage.productCode.isNotEmpty
|
||||
? stage.productCode
|
||||
@@ -495,6 +536,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
issuedKg: finalIssuedKg,
|
||||
issuedPcs: finalIssuedPcs,
|
||||
responsibleName: responsibleName,
|
||||
receiverName: receiverName,
|
||||
barcodeData: barcodeData,
|
||||
);
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user