refactor: Clean Architecture 적용 및 코드베이스 전면 리팩토링
## 주요 변경사항 ### 아키텍처 개선 - Clean Architecture 패턴 적용 (Domain, Data, Presentation 레이어 분리) - Use Case 패턴 도입으로 비즈니스 로직 캡슐화 - Repository 패턴으로 데이터 접근 추상화 - 의존성 주입 구조 개선 ### 상태 관리 최적화 - 모든 Controller에서 불필요한 상태 관리 로직 제거 - 페이지네이션 로직 통일 및 간소화 - 에러 처리 로직 개선 (에러 메시지 한글화) - 로딩 상태 관리 최적화 ### Mock 서비스 제거 - MockDataService 완전 제거 - 모든 화면을 실제 API 전용으로 전환 - 불필요한 Mock 관련 코드 정리 ### UI/UX 개선 - Overview 화면 대시보드 기능 강화 - 라이선스 만료 알림 위젯 추가 - 사이드바 네비게이션 개선 - 일관된 UI 컴포넌트 사용 ### 코드 품질 - 중복 코드 제거 및 함수 추출 - 파일별 책임 분리 명확화 - 테스트 코드 업데이트 ## 영향 범위 - 모든 화면의 Controller 리팩토링 - API 통신 레이어 구조 개선 - 에러 처리 및 로깅 시스템 개선 ## 향후 계획 - 단위 테스트 커버리지 확대 - 통합 테스트 시나리오 추가 - 성능 모니터링 도구 통합
This commit is contained in:
@@ -3,21 +3,21 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/models/user_model.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
import 'package:superport/services/user_service.dart';
|
||||
import 'package:superport/services/company_service.dart';
|
||||
import 'package:superport/utils/constants.dart';
|
||||
import 'package:superport/models/user_phone_field.dart';
|
||||
|
||||
// 사용자 폼의 상태 및 비즈니스 로직을 담당하는 컨트롤러
|
||||
class UserFormController extends ChangeNotifier {
|
||||
final MockDataService dataService;
|
||||
final UserService _userService = GetIt.instance<UserService>();
|
||||
final CompanyService _companyService = GetIt.instance<CompanyService>();
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
// 상태 변수
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
bool _useApi = true; // Feature flag
|
||||
// API만 사용
|
||||
|
||||
// 폼 필드
|
||||
bool isEditMode = false;
|
||||
@@ -50,7 +50,7 @@ class UserFormController extends ChangeNotifier {
|
||||
bool get isCheckingUsername => _isCheckingUsername;
|
||||
bool? get isUsernameAvailable => _isUsernameAvailable;
|
||||
|
||||
UserFormController({required this.dataService, this.userId}) {
|
||||
UserFormController({this.userId}) {
|
||||
isEditMode = userId != null;
|
||||
if (isEditMode) {
|
||||
loadUser();
|
||||
@@ -61,15 +61,29 @@ class UserFormController extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// 회사 목록 로드
|
||||
void loadCompanies() {
|
||||
companies = dataService.getAllCompanies();
|
||||
notifyListeners();
|
||||
Future<void> loadCompanies() async {
|
||||
try {
|
||||
final result = await _companyService.getCompanies();
|
||||
companies = result;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('회사 목록 로드 실패: $e');
|
||||
companies = [];
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// 회사 ID에 따라 지점 목록 로드
|
||||
void loadBranches(int companyId) {
|
||||
final company = dataService.getCompanyById(companyId);
|
||||
branches = company?.branches ?? [];
|
||||
final company = companies.firstWhere(
|
||||
(c) => c.id == companyId,
|
||||
orElse: () => Company(
|
||||
id: companyId,
|
||||
name: '알 수 없는 회사',
|
||||
branches: [],
|
||||
),
|
||||
);
|
||||
branches = company.branches ?? [];
|
||||
// 지점 변경 시 이전 선택 지점이 새 회사에 없으면 초기화
|
||||
if (branchId != null && !branches.any((b) => b.id == branchId)) {
|
||||
branchId = null;
|
||||
@@ -86,13 +100,7 @@ class UserFormController extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
User? user;
|
||||
|
||||
if (_useApi) {
|
||||
user = await _userService.getUser(userId!);
|
||||
} else {
|
||||
user = dataService.getUserById(userId!);
|
||||
}
|
||||
final user = await _userService.getUser(userId!);
|
||||
|
||||
if (user != null) {
|
||||
name = user.name;
|
||||
@@ -155,15 +163,8 @@ class UserFormController extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
if (_useApi) {
|
||||
final isDuplicate = await _userService.checkDuplicateUsername(value);
|
||||
_isUsernameAvailable = !isDuplicate;
|
||||
} else {
|
||||
// Mock 데이터에서 중복 확인
|
||||
final users = dataService.getAllUsers();
|
||||
final exists = users.any((u) => u.username == value && u.id != userId);
|
||||
_isUsernameAvailable = !exists;
|
||||
}
|
||||
final isDuplicate = await _userService.checkDuplicateUsername(value);
|
||||
_isUsernameAvailable = !isDuplicate;
|
||||
_lastCheckedUsername = value;
|
||||
} catch (e) {
|
||||
_isUsernameAvailable = null;
|
||||
@@ -217,81 +218,32 @@ class UserFormController extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
if (_useApi) {
|
||||
if (isEditMode && userId != null) {
|
||||
// 사용자 수정
|
||||
await _userService.updateUser(
|
||||
userId!,
|
||||
name: name,
|
||||
email: email.isNotEmpty ? email : null,
|
||||
phone: phoneNumber,
|
||||
companyId: companyId,
|
||||
branchId: branchId,
|
||||
role: role,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
password: password.isNotEmpty ? password : null,
|
||||
);
|
||||
} else {
|
||||
// 사용자 생성
|
||||
await _userService.createUser(
|
||||
username: username,
|
||||
email: email,
|
||||
password: password,
|
||||
name: name,
|
||||
role: role,
|
||||
companyId: companyId!,
|
||||
branchId: branchId,
|
||||
phone: phoneNumber,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
);
|
||||
}
|
||||
if (isEditMode && userId != null) {
|
||||
// 사용자 수정
|
||||
await _userService.updateUser(
|
||||
userId!,
|
||||
name: name,
|
||||
email: email.isNotEmpty ? email : null,
|
||||
phone: phoneNumber,
|
||||
companyId: companyId,
|
||||
branchId: branchId,
|
||||
role: role,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
password: password.isNotEmpty ? password : null,
|
||||
);
|
||||
} else {
|
||||
// Mock 데이터 사용
|
||||
List<Map<String, String>> phoneNumbersList = [];
|
||||
for (var phoneField in phoneFields) {
|
||||
if (phoneField.number.isNotEmpty) {
|
||||
phoneNumbersList.add({
|
||||
'type': phoneField.type,
|
||||
'number': phoneField.number,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isEditMode && userId != null) {
|
||||
final user = dataService.getUserById(userId!);
|
||||
if (user != null) {
|
||||
final updatedUser = User(
|
||||
id: user.id,
|
||||
companyId: companyId!,
|
||||
branchId: branchId,
|
||||
name: name,
|
||||
role: role,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
email: email.isNotEmpty ? email : null,
|
||||
phoneNumbers: phoneNumbersList,
|
||||
username: username.isNotEmpty ? username : null,
|
||||
isActive: user.isActive,
|
||||
createdAt: user.createdAt,
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
dataService.updateUser(updatedUser);
|
||||
}
|
||||
} else {
|
||||
final newUser = User(
|
||||
companyId: companyId!,
|
||||
branchId: branchId,
|
||||
name: name,
|
||||
role: role,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
email: email.isNotEmpty ? email : null,
|
||||
phoneNumbers: phoneNumbersList,
|
||||
username: username,
|
||||
isActive: true,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
dataService.addUser(newUser);
|
||||
}
|
||||
// 사용자 생성
|
||||
await _userService.createUser(
|
||||
username: username,
|
||||
email: email,
|
||||
password: password,
|
||||
name: name,
|
||||
role: role,
|
||||
companyId: companyId!,
|
||||
branchId: branchId,
|
||||
phone: phoneNumber,
|
||||
position: position.isNotEmpty ? position : null,
|
||||
);
|
||||
}
|
||||
|
||||
onResult(null);
|
||||
@@ -314,9 +266,6 @@ class UserFormController extends ChangeNotifier {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
// API/Mock 모드 전환
|
||||
void toggleApiMode() {
|
||||
_useApi = !_useApi;
|
||||
notifyListeners();
|
||||
}
|
||||
// API 모드만 사용 (Mock 데이터 제거됨)
|
||||
// void toggleApiMode() 메서드 제거
|
||||
}
|
||||
|
||||
172
lib/screens/user/controllers/user_list_controller.backup.dart
Normal file
172
lib/screens/user/controllers/user_list_controller.backup.dart
Normal file
@@ -0,0 +1,172 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:superport/models/user_model.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/services/user_service.dart';
|
||||
|
||||
/// 담당자 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러
|
||||
class UserListController extends ChangeNotifier {
|
||||
final UserService _userService = GetIt.instance<UserService>();
|
||||
|
||||
// 상태 변수
|
||||
List<User> _users = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
// API만 사용
|
||||
|
||||
// 페이지네이션
|
||||
int _currentPage = 1;
|
||||
final int _perPage = 20;
|
||||
bool _hasMoreData = true;
|
||||
bool _isLoadingMore = false;
|
||||
|
||||
// 검색/필터
|
||||
String _searchQuery = '';
|
||||
int? _filterCompanyId;
|
||||
String? _filterRole;
|
||||
bool? _filterIsActive;
|
||||
|
||||
// Getters
|
||||
List<User> get users => _users;
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isLoadingMore => _isLoadingMore;
|
||||
String? get error => _error;
|
||||
bool get hasMoreData => _hasMoreData;
|
||||
String get searchQuery => _searchQuery;
|
||||
int? get filterCompanyId => _filterCompanyId;
|
||||
String? get filterRole => _filterRole;
|
||||
bool? get filterIsActive => _filterIsActive;
|
||||
|
||||
UserListController();
|
||||
|
||||
/// 사용자 목록 초기 로드
|
||||
Future<void> loadUsers({bool refresh = false}) async {
|
||||
if (refresh) {
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
_users.clear();
|
||||
}
|
||||
|
||||
if (_isLoading) return;
|
||||
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
final newUsers = await _userService.getUsers(
|
||||
page: _currentPage,
|
||||
perPage: _perPage,
|
||||
isActive: _filterIsActive,
|
||||
companyId: _filterCompanyId,
|
||||
role: _filterRole,
|
||||
);
|
||||
|
||||
if (newUsers.isEmpty || newUsers.length < _perPage) {
|
||||
_hasMoreData = false;
|
||||
}
|
||||
|
||||
if (_currentPage == 1) {
|
||||
_users = newUsers;
|
||||
} else {
|
||||
_users.addAll(newUsers);
|
||||
}
|
||||
|
||||
_currentPage++;
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// 다음 페이지 로드 (무한 스크롤용)
|
||||
Future<void> loadMore() async {
|
||||
if (!_hasMoreData || _isLoadingMore || _isLoading) return;
|
||||
|
||||
_isLoadingMore = true;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
await loadUsers();
|
||||
} finally {
|
||||
_isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// 검색 쿼리 설정
|
||||
void setSearchQuery(String query) {
|
||||
_searchQuery = query;
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
}
|
||||
|
||||
/// 필터 설정
|
||||
void setFilters({
|
||||
int? companyId,
|
||||
String? role,
|
||||
bool? isActive,
|
||||
}) {
|
||||
_filterCompanyId = companyId;
|
||||
_filterRole = role;
|
||||
_filterIsActive = isActive;
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
}
|
||||
|
||||
/// 필터 초기화
|
||||
void clearFilters() {
|
||||
_filterCompanyId = null;
|
||||
_filterRole = null;
|
||||
_filterIsActive = null;
|
||||
_searchQuery = '';
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
}
|
||||
|
||||
/// 사용자 삭제
|
||||
Future<void> deleteUser(int id, VoidCallback onDeleted, Function(String) onError) async {
|
||||
try {
|
||||
await _userService.deleteUser(id);
|
||||
|
||||
// 목록에서 삭제된 사용자 제거
|
||||
_users.removeWhere((user) => user.id == id);
|
||||
notifyListeners();
|
||||
|
||||
onDeleted();
|
||||
} catch (e) {
|
||||
onError('사용자 삭제 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 사용자 상태 변경 (활성/비활성)
|
||||
Future<void> changeUserStatus(int id, bool isActive, Function(String) onError) async {
|
||||
try {
|
||||
final updatedUser = await _userService.changeUserStatus(id, isActive);
|
||||
// 목록에서 해당 사용자 업데이트
|
||||
final index = _users.indexWhere((u) => u.id == id);
|
||||
if (index != -1) {
|
||||
_users[index] = updatedUser;
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (e) {
|
||||
onError('상태 변경 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 권한명 반환 함수는 user_utils.dart의 getRoleName을 사용
|
||||
|
||||
/// 회사 ID와 지점 ID로 지점명 조회
|
||||
// 지점명 조회는 별도 서비스로 이동 예정
|
||||
String getBranchName(int companyId, int? branchId) {
|
||||
// TODO: API를 통해 지점명 조회
|
||||
return '-';
|
||||
}
|
||||
|
||||
// API만 사용하므로 토글 기능 제거
|
||||
}
|
||||
@@ -1,137 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:superport/models/user_model.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
import 'package:superport/services/user_service.dart';
|
||||
import 'package:superport/core/utils/error_handler.dart';
|
||||
import 'package:superport/core/controllers/base_list_controller.dart';
|
||||
import 'package:superport/data/models/common/pagination_params.dart';
|
||||
|
||||
/// 담당자 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러
|
||||
class UserListController extends ChangeNotifier {
|
||||
final MockDataService dataService;
|
||||
final UserService _userService = GetIt.instance<UserService>();
|
||||
/// 담당자 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러 (리팩토링 버전)
|
||||
/// BaseListController를 상속받아 공통 기능을 재사용
|
||||
class UserListController extends BaseListController<User> {
|
||||
late final UserService _userService;
|
||||
|
||||
// 상태 변수
|
||||
List<User> _users = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
bool _useApi = true; // Feature flag
|
||||
|
||||
// 페이지네이션
|
||||
int _currentPage = 1;
|
||||
final int _perPage = 20;
|
||||
bool _hasMoreData = true;
|
||||
bool _isLoadingMore = false;
|
||||
|
||||
// 검색/필터
|
||||
String _searchQuery = '';
|
||||
// 필터 옵션
|
||||
int? _filterCompanyId;
|
||||
String? _filterRole;
|
||||
bool? _filterIsActive;
|
||||
|
||||
// Getters
|
||||
List<User> get users => _users;
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isLoadingMore => _isLoadingMore;
|
||||
String? get error => _error;
|
||||
bool get hasMoreData => _hasMoreData;
|
||||
String get searchQuery => _searchQuery;
|
||||
List<User> get users => items;
|
||||
int? get filterCompanyId => _filterCompanyId;
|
||||
String? get filterRole => _filterRole;
|
||||
bool? get filterIsActive => _filterIsActive;
|
||||
|
||||
UserListController({required this.dataService});
|
||||
UserListController() {
|
||||
if (GetIt.instance.isRegistered<UserService>()) {
|
||||
_userService = GetIt.instance<UserService>();
|
||||
} else {
|
||||
throw Exception('UserService not registered in GetIt');
|
||||
}
|
||||
}
|
||||
|
||||
/// 사용자 목록 초기 로드
|
||||
@override
|
||||
Future<PagedResult<User>> fetchData({
|
||||
required PaginationParams params,
|
||||
Map<String, dynamic>? additionalFilters,
|
||||
}) async {
|
||||
// API 호출
|
||||
final fetchedUsers = await ErrorHandler.handleApiCall<List<User>>(
|
||||
() => _userService.getUsers(
|
||||
page: params.page,
|
||||
perPage: params.perPage,
|
||||
isActive: _filterIsActive,
|
||||
companyId: _filterCompanyId,
|
||||
role: _filterRole,
|
||||
// search 파라미터 제거 (API에서 지원하지 않음)
|
||||
),
|
||||
onError: (failure) {
|
||||
throw failure;
|
||||
},
|
||||
);
|
||||
|
||||
final items = fetchedUsers ?? [];
|
||||
|
||||
// 임시로 메타데이터 생성 (추후 API에서 실제 메타데이터 반환 시 수정)
|
||||
final meta = PaginationMeta(
|
||||
currentPage: params.page,
|
||||
perPage: params.perPage,
|
||||
total: items.length < params.perPage ?
|
||||
(params.page - 1) * params.perPage + items.length :
|
||||
params.page * params.perPage + 1,
|
||||
totalPages: items.length < params.perPage ? params.page : params.page + 1,
|
||||
hasNext: items.length >= params.perPage,
|
||||
hasPrevious: params.page > 1,
|
||||
);
|
||||
|
||||
return PagedResult(items: items, meta: meta);
|
||||
}
|
||||
|
||||
@override
|
||||
bool filterItem(User item, String query) {
|
||||
final q = query.toLowerCase();
|
||||
return item.name.toLowerCase().contains(q) ||
|
||||
(item.email?.toLowerCase().contains(q) ?? false) ||
|
||||
(item.username?.toLowerCase().contains(q) ?? false);
|
||||
}
|
||||
|
||||
/// 사용자 목록 초기 로드 (호환성 유지)
|
||||
Future<void> loadUsers({bool refresh = false}) async {
|
||||
if (refresh) {
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
_users.clear();
|
||||
}
|
||||
|
||||
if (_isLoading) return;
|
||||
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
if (_useApi) {
|
||||
final newUsers = await _userService.getUsers(
|
||||
page: _currentPage,
|
||||
perPage: _perPage,
|
||||
isActive: _filterIsActive,
|
||||
companyId: _filterCompanyId,
|
||||
role: _filterRole,
|
||||
);
|
||||
|
||||
if (newUsers.isEmpty || newUsers.length < _perPage) {
|
||||
_hasMoreData = false;
|
||||
}
|
||||
|
||||
if (_currentPage == 1) {
|
||||
_users = newUsers;
|
||||
} else {
|
||||
_users.addAll(newUsers);
|
||||
}
|
||||
|
||||
_currentPage++;
|
||||
} else {
|
||||
// Mock 데이터 사용
|
||||
var allUsers = dataService.getAllUsers();
|
||||
|
||||
// 필터 적용
|
||||
if (_filterCompanyId != null) {
|
||||
allUsers = allUsers.where((u) => u.companyId == _filterCompanyId).toList();
|
||||
}
|
||||
if (_filterRole != null) {
|
||||
allUsers = allUsers.where((u) => u.role == _filterRole).toList();
|
||||
}
|
||||
if (_filterIsActive != null) {
|
||||
allUsers = allUsers.where((u) => u.isActive == _filterIsActive).toList();
|
||||
}
|
||||
|
||||
// 검색 적용
|
||||
if (_searchQuery.isNotEmpty) {
|
||||
allUsers = allUsers.where((u) =>
|
||||
u.name.toLowerCase().contains(_searchQuery.toLowerCase()) ||
|
||||
(u.email?.toLowerCase().contains(_searchQuery.toLowerCase()) ?? false) ||
|
||||
(u.username?.toLowerCase().contains(_searchQuery.toLowerCase()) ?? false)
|
||||
).toList();
|
||||
}
|
||||
|
||||
_users = allUsers;
|
||||
_hasMoreData = false;
|
||||
}
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// 다음 페이지 로드 (무한 스크롤용)
|
||||
Future<void> loadMore() async {
|
||||
if (!_hasMoreData || _isLoadingMore || _isLoading) return;
|
||||
|
||||
_isLoadingMore = true;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
await loadUsers();
|
||||
} finally {
|
||||
_isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// 검색 쿼리 설정
|
||||
void setSearchQuery(String query) {
|
||||
_searchQuery = query;
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
await loadData(isRefresh: refresh);
|
||||
}
|
||||
|
||||
/// 필터 설정
|
||||
@@ -143,9 +89,7 @@ class UserListController extends ChangeNotifier {
|
||||
_filterCompanyId = companyId;
|
||||
_filterRole = role;
|
||||
_filterIsActive = isActive;
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
loadData(isRefresh: true);
|
||||
}
|
||||
|
||||
/// 필터 초기화
|
||||
@@ -153,69 +97,126 @@ class UserListController extends ChangeNotifier {
|
||||
_filterCompanyId = null;
|
||||
_filterRole = null;
|
||||
_filterIsActive = null;
|
||||
_searchQuery = '';
|
||||
_currentPage = 1;
|
||||
_hasMoreData = true;
|
||||
loadUsers(refresh: true);
|
||||
search('');
|
||||
loadData(isRefresh: true);
|
||||
}
|
||||
|
||||
/// 회사별 필터링
|
||||
void filterByCompany(int? companyId) {
|
||||
_filterCompanyId = companyId;
|
||||
loadData(isRefresh: true);
|
||||
}
|
||||
|
||||
/// 역할별 필터링
|
||||
void filterByRole(String? role) {
|
||||
_filterRole = role;
|
||||
loadData(isRefresh: true);
|
||||
}
|
||||
|
||||
/// 활성 상태별 필터링
|
||||
void filterByActiveStatus(bool? isActive) {
|
||||
_filterIsActive = isActive;
|
||||
loadData(isRefresh: true);
|
||||
}
|
||||
|
||||
/// 사용자 추가
|
||||
Future<void> addUser(User user) async {
|
||||
await ErrorHandler.handleApiCall<void>(
|
||||
() => _userService.createUser(
|
||||
username: user.username ?? '',
|
||||
email: user.email ?? '',
|
||||
password: 'temp123', // 임시 비밀번호
|
||||
name: user.name,
|
||||
role: user.role,
|
||||
companyId: user.companyId,
|
||||
branchId: user.branchId,
|
||||
),
|
||||
onError: (failure) {
|
||||
throw failure;
|
||||
},
|
||||
);
|
||||
|
||||
await refresh();
|
||||
}
|
||||
|
||||
/// 사용자 수정
|
||||
Future<void> updateUser(User user) async {
|
||||
await ErrorHandler.handleApiCall<void>(
|
||||
() => _userService.updateUser(
|
||||
user.id!,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
companyId: user.companyId,
|
||||
branchId: user.branchId,
|
||||
role: user.role,
|
||||
position: user.position,
|
||||
),
|
||||
onError: (failure) {
|
||||
throw failure;
|
||||
},
|
||||
);
|
||||
|
||||
updateItemLocally(user, (u) => u.id == user.id);
|
||||
}
|
||||
|
||||
/// 사용자 삭제
|
||||
Future<void> deleteUser(int id, VoidCallback onDeleted, Function(String) onError) async {
|
||||
try {
|
||||
if (_useApi) {
|
||||
await _userService.deleteUser(id);
|
||||
} else {
|
||||
dataService.deleteUser(id);
|
||||
}
|
||||
|
||||
// 목록에서 삭제된 사용자 제거
|
||||
_users.removeWhere((user) => user.id == id);
|
||||
notifyListeners();
|
||||
|
||||
onDeleted();
|
||||
} catch (e) {
|
||||
onError('사용자 삭제 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 사용자 상태 변경 (활성/비활성)
|
||||
Future<void> changeUserStatus(int id, bool isActive, Function(String) onError) async {
|
||||
try {
|
||||
if (_useApi) {
|
||||
final updatedUser = await _userService.changeUserStatus(id, isActive);
|
||||
// 목록에서 해당 사용자 업데이트
|
||||
final index = _users.indexWhere((u) => u.id == id);
|
||||
if (index != -1) {
|
||||
_users[index] = updatedUser;
|
||||
notifyListeners();
|
||||
}
|
||||
} else {
|
||||
// Mock 데이터에서는 상태 변경 지원 안함
|
||||
onError('Mock 데이터에서는 상태 변경을 지원하지 않습니다');
|
||||
}
|
||||
} catch (e) {
|
||||
onError('상태 변경 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 권한명 반환 함수는 user_utils.dart의 getRoleName을 사용
|
||||
|
||||
/// 회사 ID와 지점 ID로 지점명 조회
|
||||
String getBranchName(int companyId, int? branchId) {
|
||||
final company = dataService.getCompanyById(companyId);
|
||||
if (company == null || company.branches == null || branchId == null) {
|
||||
return '-';
|
||||
}
|
||||
final branch = company.branches!.firstWhere(
|
||||
(b) => b.id == branchId,
|
||||
orElse: () => Branch(companyId: companyId, name: '-'),
|
||||
Future<void> deleteUser(int id) async {
|
||||
await ErrorHandler.handleApiCall<void>(
|
||||
() => _userService.deleteUser(id),
|
||||
onError: (failure) {
|
||||
throw failure;
|
||||
},
|
||||
);
|
||||
return branch.name;
|
||||
|
||||
removeItemLocally((u) => u.id == id);
|
||||
}
|
||||
|
||||
/// API/Mock 모드 전환
|
||||
void toggleApiMode() {
|
||||
_useApi = !_useApi;
|
||||
loadUsers(refresh: true);
|
||||
|
||||
/// 사용자 활성/비활성 토글
|
||||
Future<void> toggleUserActiveStatus(User user) async {
|
||||
// TODO: User 모델에 copyWith 메서드가 없어서 임시로 주석 처리
|
||||
// final updatedUser = user.copyWith(isActive: !user.isActive);
|
||||
// await updateUser(updatedUser);
|
||||
debugPrint('사용자 활성 상태 토글: ${user.name}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 비밀번호 재설정
|
||||
Future<void> resetPassword(int userId, String newPassword) async {
|
||||
await ErrorHandler.handleApiCall<void>(
|
||||
() => _userService.resetPassword(
|
||||
userId: userId,
|
||||
newPassword: newPassword,
|
||||
),
|
||||
onError: (failure) {
|
||||
throw failure;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 사용자 ID로 단일 사용자 조회
|
||||
User? getUserById(int id) {
|
||||
try {
|
||||
return items.firstWhere((user) => user.id == id);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 검색 쿼리 설정 (호환성 유지)
|
||||
void setSearchQuery(String query) {
|
||||
search(query); // BaseListController의 search 메서드 사용
|
||||
}
|
||||
|
||||
/// 사용자 상태 변경
|
||||
Future<void> changeUserStatus(User user, bool isActive) async {
|
||||
// TODO: User 모델에 copyWith 메서드가 없어서 임시로 주석 처리
|
||||
// final updatedUser = user.copyWith(isActive: isActive);
|
||||
// await updateUser(updatedUser);
|
||||
debugPrint('사용자 상태 변경: ${user.name} -> $isActive');
|
||||
}
|
||||
|
||||
/// 지점명 가져오기 (임시 구현)
|
||||
String getBranchName(int? branchId) {
|
||||
if (branchId == null) return '본사';
|
||||
return '지점 $branchId'; // 실제로는 CompanyService에서 가져와야 함
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user