refactor: UI 화면 통합 및 불필요한 파일 정리
- 모든 *_redesign.dart 파일을 기본 화면 파일로 통합 - 백업용 컨트롤러 파일들 제거 (*_controller.backup.dart) - 사용하지 않는 예제 및 테스트 파일 제거 - Clean Architecture 적용 후 남은 정리 작업 완료 - 테스트 코드 정리 및 구조 개선 준비 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,7 @@ class UserFormController extends ChangeNotifier {
|
||||
Future<void> loadCompanies() async {
|
||||
try {
|
||||
final result = await _companyService.getCompanies();
|
||||
companies = result;
|
||||
companies = result.items; // PaginatedResponse에서 items 추출
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('회사 목록 로드 실패: $e');
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
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만 사용하므로 토글 기능 제거
|
||||
}
|
||||
@@ -35,8 +35,8 @@ class UserListController extends BaseListController<User> {
|
||||
required PaginationParams params,
|
||||
Map<String, dynamic>? additionalFilters,
|
||||
}) async {
|
||||
// API 호출
|
||||
final fetchedUsers = await ErrorHandler.handleApiCall<List<User>>(
|
||||
// API 호출 (이제 PaginatedResponse 반환)
|
||||
final response = await ErrorHandler.handleApiCall<dynamic>(
|
||||
() => _userService.getUsers(
|
||||
page: params.page,
|
||||
perPage: params.perPage,
|
||||
@@ -50,21 +50,17 @@ class UserListController extends BaseListController<User> {
|
||||
},
|
||||
);
|
||||
|
||||
final items = fetchedUsers ?? [];
|
||||
|
||||
// 임시로 메타데이터 생성 (추후 API에서 실제 메타데이터 반환 시 수정)
|
||||
// PaginatedResponse를 PagedResult로 변환
|
||||
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,
|
||||
currentPage: response.page,
|
||||
perPage: response.size,
|
||||
total: response.totalElements,
|
||||
totalPages: response.totalPages,
|
||||
hasNext: !response.last,
|
||||
hasPrevious: !response.first,
|
||||
);
|
||||
|
||||
return PagedResult(items: items, meta: meta);
|
||||
return PagedResult(items: response.items, meta: meta);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:superport/screens/common/theme_tailwind.dart';
|
||||
import 'package:superport/screens/common/theme_shadcn.dart';
|
||||
import 'package:superport/utils/constants.dart';
|
||||
import 'package:superport/utils/validators.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -272,7 +272,10 @@ class _UserFormScreenState extends State<UserFormScreen> {
|
||||
onPressed: controller.isLoading
|
||||
? null
|
||||
: () => _onSaveUser(controller),
|
||||
style: AppThemeTailwind.primaryButtonStyle,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ShadcnTheme.primary,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: controller.isLoading
|
||||
|
||||
@@ -10,18 +10,16 @@ import 'package:superport/utils/constants.dart';
|
||||
import 'package:superport/utils/user_utils.dart';
|
||||
|
||||
/// shadcn/ui 스타일로 재설계된 사용자 관리 화면
|
||||
class UserListRedesign extends StatefulWidget {
|
||||
const UserListRedesign({super.key});
|
||||
class UserList extends StatefulWidget {
|
||||
const UserList({super.key});
|
||||
|
||||
@override
|
||||
State<UserListRedesign> createState() => _UserListRedesignState();
|
||||
State<UserList> createState() => _UserListState();
|
||||
}
|
||||
|
||||
class _UserListRedesignState extends State<UserListRedesign> {
|
||||
class _UserListState extends State<UserList> {
|
||||
// MockDataService 제거 - 실제 API 사용
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
int _currentPage = 1;
|
||||
final int _pageSize = 10;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -29,7 +27,9 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
|
||||
// 초기 데이터 로드
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<UserListController>().loadUsers();
|
||||
final controller = context.read<UserListController>();
|
||||
controller.pageSize = 10; // 페이지 크기 설정
|
||||
controller.loadUsers();
|
||||
});
|
||||
|
||||
// 검색 디바운싱
|
||||
@@ -50,10 +50,7 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
void _onSearchChanged(String query) {
|
||||
if (_debounce?.isActive ?? false) _debounce!.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 300), () {
|
||||
setState(() {
|
||||
_currentPage = 1;
|
||||
});
|
||||
context.read<UserListController>().setSearchQuery(query);
|
||||
context.read<UserListController>().setSearchQuery(query); // Controller가 페이지 리셋 처리
|
||||
});
|
||||
}
|
||||
|
||||
@@ -207,14 +204,9 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
);
|
||||
}
|
||||
|
||||
// 페이지네이션을 위한 데이터 처리
|
||||
final int totalUsers = controller.users.length;
|
||||
final int startIndex = (_currentPage - 1) * _pageSize;
|
||||
final int endIndex = startIndex + _pageSize;
|
||||
final List<User> pagedUsers = controller.users.sublist(
|
||||
startIndex,
|
||||
endIndex > totalUsers ? totalUsers : endIndex,
|
||||
);
|
||||
// Controller가 이미 페이징된 데이터를 제공
|
||||
final List<User> pagedUsers = controller.users; // 이미 페이징됨
|
||||
final int totalUsers = controller.total; // 실제 전체 개수
|
||||
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(ShadcnTheme.spacing6),
|
||||
@@ -415,7 +407,7 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
)
|
||||
else
|
||||
...pagedUsers.asMap().entries.map((entry) {
|
||||
final int index = startIndex + entry.key;
|
||||
final int index = ((controller.currentPage - 1) * controller.pageSize) + entry.key;
|
||||
final User user = entry.value;
|
||||
|
||||
return Container(
|
||||
@@ -576,16 +568,19 @@ class _UserListRedesignState extends State<UserListRedesign> {
|
||||
),
|
||||
),
|
||||
|
||||
// 페이지네이션 컴포넌트
|
||||
if (totalUsers > _pageSize)
|
||||
// 페이지네이션 컴포넌트 (Controller 상태 사용)
|
||||
if (controller.total > controller.pageSize)
|
||||
Pagination(
|
||||
totalCount: totalUsers,
|
||||
currentPage: _currentPage,
|
||||
pageSize: _pageSize,
|
||||
totalCount: controller.total,
|
||||
currentPage: controller.currentPage,
|
||||
pageSize: controller.pageSize,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
_currentPage = page;
|
||||
});
|
||||
// 다음 페이지 로드
|
||||
if (page > controller.currentPage) {
|
||||
controller.loadNextPage();
|
||||
} else if (page == 1) {
|
||||
controller.refresh();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
Reference in New Issue
Block a user