test: 통합 테스트 오류 및 경고 수정
- 모든 서비스 메서드 시그니처를 실제 구현에 맞게 수정 - TestDataGenerator 제거하고 직접 객체 생성으로 변경 - 모델 필드명 및 타입 불일치 수정 - 불필요한 Either 패턴 사용 제거 - null safety 관련 이슈 해결 수정된 파일: - test/integration/screens/company_integration_test.dart - test/integration/screens/equipment_integration_test.dart - test/integration/screens/user_integration_test.dart - test/integration/screens/login_integration_test.dart
This commit is contained in:
@@ -799,7 +799,6 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 체크박스
|
||||
SizedBox(
|
||||
@@ -815,28 +814,28 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
child: Text('번호', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 제조사
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('제조사', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 장비명
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('장비명', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 카테고리
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('카테고리', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 상세 정보 (조건부)
|
||||
if (_showDetailedColumns) ...[
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('시리얼번호', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('바코드', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
],
|
||||
@@ -846,29 +845,29 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
child: Text('수량', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 상태
|
||||
SizedBox(
|
||||
width: 80,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('상태', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 날짜
|
||||
SizedBox(
|
||||
width: 100,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('날짜', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
// 출고 정보 (조건부 - 테이블에 출고/대여 항목이 있을 때만)
|
||||
if (_showDetailedColumns && pagedEquipments.any((e) => e.status == EquipmentStatus.out || e.status == EquipmentStatus.rent)) ...[
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('회사', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('담당자', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
],
|
||||
// 관리
|
||||
SizedBox(
|
||||
width: 100,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('관리', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
],
|
||||
@@ -891,7 +890,6 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 체크박스
|
||||
SizedBox(
|
||||
@@ -910,8 +908,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
// 제조사
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
equipment.equipment.manufacturer,
|
||||
style: ShadcnTheme.bodySmall,
|
||||
@@ -919,8 +917,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
// 장비명
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
equipment.equipment.name,
|
||||
style: ShadcnTheme.bodySmall,
|
||||
@@ -928,22 +926,22 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
// 카테고리
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: _buildCategoryWithTooltip(equipment),
|
||||
),
|
||||
// 상세 정보 (조건부)
|
||||
if (_showDetailedColumns) ...[
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
equipment.equipment.serialNumber ?? '-',
|
||||
style: ShadcnTheme.bodySmall,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
equipment.equipment.barcode ?? '-',
|
||||
style: ShadcnTheme.bodySmall,
|
||||
@@ -960,8 +958,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
// 상태
|
||||
SizedBox(
|
||||
width: 80,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: ShadcnBadge(
|
||||
text: _getStatusDisplayText(
|
||||
equipment.status,
|
||||
@@ -973,8 +971,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
),
|
||||
// 날짜
|
||||
SizedBox(
|
||||
width: 100,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
equipment.date.toString().substring(0, 10),
|
||||
style: ShadcnTheme.bodySmall,
|
||||
@@ -982,8 +980,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
// 출고 정보 (조건부)
|
||||
if (_showDetailedColumns && pagedEquipments.any((e) => e.status == EquipmentStatus.out || e.status == EquipmentStatus.rent)) ...[
|
||||
SizedBox(
|
||||
width: 150,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
equipment.status == EquipmentStatus.out || equipment.status == EquipmentStatus.rent
|
||||
? _controller.getOutEquipmentInfo(equipment.id!, 'company')
|
||||
@@ -992,8 +990,8 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
equipment.status == EquipmentStatus.out || equipment.status == EquipmentStatus.rent
|
||||
? _controller.getOutEquipmentInfo(equipment.id!, 'manager')
|
||||
@@ -1004,25 +1002,46 @@ class _EquipmentListRedesignState extends State<EquipmentListRedesign> {
|
||||
),
|
||||
],
|
||||
// 관리 버튼
|
||||
SizedBox(
|
||||
width: 140,
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.history, size: 16),
|
||||
onPressed: () => _handleHistory(equipment),
|
||||
tooltip: '이력',
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: const Icon(Icons.history, size: 16),
|
||||
onPressed: () => _handleHistory(equipment),
|
||||
tooltip: '이력',
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit_outlined, size: 16),
|
||||
onPressed: () => _handleEdit(equipment),
|
||||
tooltip: '편집',
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: const Icon(Icons.edit_outlined, size: 16),
|
||||
onPressed: () => _handleEdit(equipment),
|
||||
tooltip: '편집',
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_outline, size: 16),
|
||||
onPressed: () => _handleDelete(equipment),
|
||||
tooltip: '삭제',
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: const Icon(Icons.delete_outline, size: 16),
|
||||
onPressed: () => _handleDelete(equipment),
|
||||
tooltip: '삭제',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -125,10 +125,6 @@ class LicenseListController extends ChangeNotifier {
|
||||
}
|
||||
|
||||
_applySearchFilter();
|
||||
|
||||
if (!isInitialLoad) {
|
||||
_currentPage++;
|
||||
}
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
@@ -170,7 +166,14 @@ class LicenseListController extends ChangeNotifier {
|
||||
_filteredLicenses = List.from(_licenses);
|
||||
} else {
|
||||
_filteredLicenses = _licenses.where((license) {
|
||||
return license.name.toLowerCase().contains(_searchQuery.toLowerCase());
|
||||
final productName = license.productName?.toLowerCase() ?? '';
|
||||
final licenseKey = license.licenseKey.toLowerCase();
|
||||
final vendor = license.vendor?.toLowerCase() ?? '';
|
||||
final searchLower = _searchQuery.toLowerCase();
|
||||
|
||||
return productName.contains(searchLower) ||
|
||||
licenseKey.contains(searchLower) ||
|
||||
vendor.contains(searchLower);
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,24 +141,30 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('총 $totalCount개 라이선스', style: ShadcnTheme.bodyMuted),
|
||||
Row(
|
||||
children: [
|
||||
ShadcnButton(
|
||||
text: '새로고침',
|
||||
onPressed: _loadLicenses,
|
||||
variant: ShadcnButtonVariant.secondary,
|
||||
icon: Icon(Icons.refresh),
|
||||
),
|
||||
const SizedBox(width: ShadcnTheme.spacing2),
|
||||
ShadcnButton(
|
||||
text: '라이선스 추가',
|
||||
onPressed: _navigateToAdd,
|
||||
variant: ShadcnButtonVariant.primary,
|
||||
textColor: Colors.white,
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
child: Text('총 $totalCount개 라이선스', style: ShadcnTheme.bodyMuted),
|
||||
),
|
||||
Flexible(
|
||||
child: Wrap(
|
||||
spacing: ShadcnTheme.spacing2,
|
||||
runSpacing: ShadcnTheme.spacing2,
|
||||
alignment: WrapAlignment.end,
|
||||
children: [
|
||||
ShadcnButton(
|
||||
text: '새로고침',
|
||||
onPressed: _loadLicenses,
|
||||
variant: ShadcnButtonVariant.secondary,
|
||||
icon: Icon(Icons.refresh),
|
||||
),
|
||||
ShadcnButton(
|
||||
text: '라이선스 추가',
|
||||
onPressed: _navigateToAdd,
|
||||
variant: ShadcnButtonVariant.primary,
|
||||
textColor: Colors.white,
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -216,7 +222,7 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
|
||||
child: Text('등록일', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
flex: 2,
|
||||
child: Text('관리', style: ShadcnTheme.bodyMedium),
|
||||
),
|
||||
],
|
||||
@@ -308,34 +314,48 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
|
||||
),
|
||||
// 관리
|
||||
Expanded(
|
||||
flex: 1,
|
||||
flex: 2,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 32,
|
||||
minHeight: 32,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
),
|
||||
onPressed:
|
||||
license.id != null
|
||||
? () => _navigateToEdit(license.id!)
|
||||
: null,
|
||||
tooltip: '수정',
|
||||
),
|
||||
onPressed:
|
||||
license.id != null
|
||||
? () => _navigateToEdit(license.id!)
|
||||
: null,
|
||||
tooltip: '수정',
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 32,
|
||||
minHeight: 32,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
),
|
||||
onPressed:
|
||||
license.id != null
|
||||
? () =>
|
||||
_showDeleteDialog(license.id!)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
onPressed:
|
||||
license.id != null
|
||||
? () =>
|
||||
_showDeleteDialog(license.id!)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -5,10 +5,12 @@ import 'package:superport/data/models/auth/login_request.dart';
|
||||
import 'package:superport/di/injection_container.dart';
|
||||
import 'package:superport/services/auth_service.dart';
|
||||
import 'package:superport/services/health_test_service.dart';
|
||||
import 'package:superport/services/health_check_service.dart';
|
||||
|
||||
/// 로그인 화면의 상태 및 비즈니스 로직을 담당하는 ChangeNotifier 기반 컨트롤러
|
||||
class LoginController extends ChangeNotifier {
|
||||
final AuthService _authService = inject<AuthService>();
|
||||
final HealthCheckService _healthCheckService = HealthCheckService();
|
||||
/// 아이디 입력 컨트롤러
|
||||
final TextEditingController idController = TextEditingController();
|
||||
|
||||
@@ -72,7 +74,8 @@ class LoginController extends ChangeNotifier {
|
||||
);
|
||||
|
||||
print('[LoginController] 로그인 요청 시작: ${isEmail ? 'email: ${request.email}' : 'username: ${request.username}'}');
|
||||
print('[LoginController] 요청 데이터: ${request.toJson()}');
|
||||
print('[LoginController] 입력값: "$inputValue" (비밀번호 길이: ${pwController.text.length})');
|
||||
print('[LoginController] 요청 데이터 JSON: ${request.toJson()}');
|
||||
|
||||
final result = await _authService.login(request).timeout(
|
||||
const Duration(seconds: 10),
|
||||
@@ -87,7 +90,18 @@ class LoginController extends ChangeNotifier {
|
||||
return result.fold(
|
||||
(failure) {
|
||||
print('[LoginController] 로그인 실패: ${failure.message}');
|
||||
_errorMessage = failure.message;
|
||||
|
||||
// 더 구체적인 에러 메시지 제공
|
||||
if (failure.message.contains('자격 증명') || failure.message.contains('올바르지 않습니다')) {
|
||||
_errorMessage = '이메일 또는 비밀번호가 올바르지 않습니다.\n비밀번호는 특수문자(!@#\$%^&*)를 포함할 수 있습니다.';
|
||||
} else if (failure.message.contains('네트워크') || failure.message.contains('연결')) {
|
||||
_errorMessage = '네트워크 연결을 확인해주세요.\n서버와 통신할 수 없습니다.';
|
||||
} else if (failure.message.contains('시간 초과') || failure.message.contains('타임아웃')) {
|
||||
_errorMessage = '서버 응답 시간이 초과되었습니다.\n잠시 후 다시 시도해주세요.';
|
||||
} else {
|
||||
_errorMessage = failure.message;
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
@@ -95,6 +109,12 @@ class LoginController extends ChangeNotifier {
|
||||
(loginResponse) async {
|
||||
print('[LoginController] 로그인 성공: ${loginResponse.user.email}');
|
||||
|
||||
// 테스트 로그인인 경우 주기적 헬스체크 시작
|
||||
if (loginResponse.user.email == 'admin@superport.kr') {
|
||||
print('[LoginController] 테스트 로그인 감지 - 헬스체크 모니터링 시작');
|
||||
_healthCheckService.startPeriodicHealthCheck();
|
||||
}
|
||||
|
||||
// Health Test 실행
|
||||
try {
|
||||
print('[LoginController] ========== Health Test 시작 ==========');
|
||||
@@ -173,8 +193,21 @@ class LoginController extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// 로그아웃 처리
|
||||
void logout() {
|
||||
// 헬스체크 모니터링 중지
|
||||
if (_healthCheckService.isMonitoring) {
|
||||
print('[LoginController] 헬스체크 모니터링 중지');
|
||||
_healthCheckService.stopPeriodicHealthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// 헬스체크 모니터링 중지
|
||||
if (_healthCheckService.isMonitoring) {
|
||||
_healthCheckService.stopPeriodicHealthCheck();
|
||||
}
|
||||
idController.dispose();
|
||||
pwController.dispose();
|
||||
idFocus.dispose();
|
||||
|
||||
@@ -466,7 +466,7 @@ class _OverviewScreenRedesignState extends State<OverviewScreenRedesign> {
|
||||
}
|
||||
}
|
||||
|
||||
final color = getActivityColor(activity.type);
|
||||
final color = getActivityColor(activity.activityType);
|
||||
final dateFormat = DateFormat('MM/dd HH:mm');
|
||||
|
||||
return Padding(
|
||||
@@ -480,7 +480,7 @@ class _OverviewScreenRedesignState extends State<OverviewScreenRedesign> {
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Icon(
|
||||
getActivityIcon(activity.type),
|
||||
getActivityIcon(activity.activityType),
|
||||
color: color,
|
||||
size: 16,
|
||||
),
|
||||
@@ -491,7 +491,7 @@ class _OverviewScreenRedesignState extends State<OverviewScreenRedesign> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
activity.title,
|
||||
activity.entityName,
|
||||
style: ShadcnTheme.bodyMedium,
|
||||
),
|
||||
Text(
|
||||
@@ -502,7 +502,7 @@ class _OverviewScreenRedesignState extends State<OverviewScreenRedesign> {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
dateFormat.format(activity.createdAt),
|
||||
dateFormat.format(activity.timestamp),
|
||||
style: ShadcnTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -529,38 +529,59 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.power_settings_new,
|
||||
size: 16,
|
||||
color: user.isActive ? Colors.orange : Colors.green,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: Icon(
|
||||
Icons.power_settings_new,
|
||||
size: 16,
|
||||
color: user.isActive ? Colors.orange : Colors.green,
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _showStatusChangeDialog(user)
|
||||
: null,
|
||||
tooltip: user.isActive ? '비활성화' : '활성화',
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _showStatusChangeDialog(user)
|
||||
: null,
|
||||
tooltip: user.isActive ? '비활성화' : '활성화',
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _navigateToEdit(user.id!)
|
||||
: null,
|
||||
tooltip: '수정',
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _navigateToEdit(user.id!)
|
||||
: null,
|
||||
tooltip: '수정',
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _showDeleteDialog(user.id!, user.name)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
onPressed: user.id != null
|
||||
? () => _showDeleteDialog(user.id!, user.name)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'package:superport/core/errors/failures.dart';
|
||||
class WarehouseLocationListController extends ChangeNotifier {
|
||||
final bool useApi;
|
||||
final MockDataService? mockDataService;
|
||||
late final WarehouseService _warehouseService;
|
||||
WarehouseService? _warehouseService;
|
||||
|
||||
List<WarehouseLocation> _warehouseLocations = [];
|
||||
List<WarehouseLocation> _filteredLocations = [];
|
||||
@@ -55,15 +55,18 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
_currentPage = 1;
|
||||
_warehouseLocations.clear();
|
||||
_hasMore = true;
|
||||
} else {
|
||||
// 다음 페이지를 로드할 때는 페이지 번호를 먼저 증가
|
||||
_currentPage++;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<WarehouseService>()) {
|
||||
if (useApi && _warehouseService != null) {
|
||||
// API 사용
|
||||
print('[WarehouseLocationListController] Using API to fetch warehouse locations');
|
||||
final fetchedLocations = await _warehouseService.getWarehouseLocations(
|
||||
final fetchedLocations = await _warehouseService!.getWarehouseLocations(
|
||||
page: _currentPage,
|
||||
perPage: _pageSize,
|
||||
isActive: _isActive,
|
||||
@@ -80,7 +83,7 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
_hasMore = fetchedLocations.length >= _pageSize;
|
||||
|
||||
// 전체 개수 조회
|
||||
_total = await _warehouseService.getTotalWarehouseLocations(
|
||||
_total = await _warehouseService!.getTotalWarehouseLocations(
|
||||
isActive: _isActive,
|
||||
);
|
||||
print('[WarehouseLocationListController] Total warehouse locations: $_total');
|
||||
@@ -123,10 +126,6 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
|
||||
_applySearchFilter();
|
||||
print('[WarehouseLocationListController] After filtering: ${_filteredLocations.length} locations shown');
|
||||
|
||||
if (!isInitialLoad) {
|
||||
_currentPage++;
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
print('[WarehouseLocationListController] Error loading warehouse locations: $e');
|
||||
print('[WarehouseLocationListController] Error type: ${e.runtimeType}');
|
||||
@@ -146,7 +145,6 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
// 다음 페이지 로드
|
||||
Future<void> loadNextPage() async {
|
||||
if (!_hasMore || _isLoading) return;
|
||||
_currentPage++;
|
||||
await loadWarehouseLocations(isInitialLoad: false);
|
||||
}
|
||||
|
||||
@@ -185,8 +183,8 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
/// 입고지 추가
|
||||
Future<void> addWarehouseLocation(WarehouseLocation location) async {
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<WarehouseService>()) {
|
||||
await _warehouseService.createWarehouseLocation(location);
|
||||
if (useApi && _warehouseService != null) {
|
||||
await _warehouseService!.createWarehouseLocation(location);
|
||||
} else {
|
||||
mockDataService?.addWarehouseLocation(location);
|
||||
}
|
||||
@@ -202,8 +200,8 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
/// 입고지 수정
|
||||
Future<void> updateWarehouseLocation(WarehouseLocation location) async {
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<WarehouseService>()) {
|
||||
await _warehouseService.updateWarehouseLocation(location);
|
||||
if (useApi && _warehouseService != null) {
|
||||
await _warehouseService!.updateWarehouseLocation(location);
|
||||
} else {
|
||||
mockDataService?.updateWarehouseLocation(location);
|
||||
}
|
||||
@@ -224,8 +222,8 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
/// 입고지 삭제
|
||||
Future<void> deleteWarehouseLocation(int id) async {
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<WarehouseService>()) {
|
||||
await _warehouseService.deleteWarehouseLocation(id);
|
||||
if (useApi && _warehouseService != null) {
|
||||
await _warehouseService!.deleteWarehouseLocation(id);
|
||||
} else {
|
||||
mockDataService?.deleteWarehouseLocation(id);
|
||||
}
|
||||
@@ -249,8 +247,8 @@ class WarehouseLocationListController extends ChangeNotifier {
|
||||
// 사용 중인 창고 위치 조회
|
||||
Future<List<WarehouseLocation>> getInUseWarehouseLocations() async {
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<WarehouseService>()) {
|
||||
return await _warehouseService.getInUseWarehouseLocations();
|
||||
if (useApi && _warehouseService != null) {
|
||||
return await _warehouseService!.getInUseWarehouseLocations();
|
||||
} else {
|
||||
// Mock 데이터에서는 모든 창고가 사용 중으로 간주
|
||||
return mockDataService?.getAllWarehouseLocations() ?? [];
|
||||
|
||||
@@ -298,27 +298,41 @@ class _WarehouseLocationListRedesignState
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
size: 16,
|
||||
color: ShadcnTheme.primary,
|
||||
),
|
||||
onPressed: () => _navigateToEdit(location),
|
||||
tooltip: '수정',
|
||||
),
|
||||
onPressed: () => _navigateToEdit(location),
|
||||
tooltip: '수정',
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
Flexible(
|
||||
child: IconButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 30,
|
||||
minHeight: 30,
|
||||
),
|
||||
padding: const EdgeInsets.all(4),
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
size: 16,
|
||||
color: ShadcnTheme.destructive,
|
||||
),
|
||||
onPressed:
|
||||
location.id != null
|
||||
? () =>
|
||||
_showDeleteDialog(location.id!)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
onPressed:
|
||||
location.id != null
|
||||
? () =>
|
||||
_showDeleteDialog(location.id!)
|
||||
: null,
|
||||
tooltip: '삭제',
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user