refactor: UI 화면 통합 및 불필요한 파일 정리
Some checks failed
Flutter Test & Quality Check / Build APK (push) Has been cancelled
Flutter Test & Quality Check / Test on macos-latest (push) Has been cancelled
Flutter Test & Quality Check / Test on ubuntu-latest (push) Has been cancelled

- 모든 *_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:
JiWoong Sul
2025-08-11 14:00:44 +09:00
parent 162fe08618
commit 1e6da44917
103 changed files with 1224 additions and 2976 deletions

View File

@@ -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');

View File

@@ -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만 사용하므로 토글 기능 제거
}

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}
},
),
],