import 'package:flutter/foundation.dart'; import 'package:injectable/injectable.dart'; import 'package:superport/data/models/vendor_dto.dart'; import 'package:superport/data/models/vendor_stats_dto.dart'; import 'package:superport/domain/usecases/vendor_usecase.dart'; import 'package:superport/utils/constants.dart'; @injectable class VendorController extends ChangeNotifier { final VendorUseCase _vendorUseCase; VendorController(this._vendorUseCase); // 상태 변수들 List _vendors = []; VendorDto? _selectedVendor; VendorStatsDto? _vendorStats; bool _isLoading = false; bool _isStatsLoading = false; String? _errorMessage; // 페이지네이션 int _currentPage = 1; int _totalPages = 1; int _totalCount = 0; final int _pageSize = PaginationConstants.defaultPageSize; // 필터 및 검색 String _searchQuery = ''; bool? _filterIsActive; // Getters List get vendors => _vendors; VendorDto? get selectedVendor => _selectedVendor; VendorStatsDto? get vendorStats => _vendorStats; bool get isLoading => _isLoading; bool get isStatsLoading => _isStatsLoading; String? get errorMessage => _errorMessage; int get currentPage => _currentPage; int get totalPages => _totalPages; int get totalCount => _totalCount; String get searchQuery => _searchQuery; bool? get filterIsActive => _filterIsActive; bool get hasNextPage => _currentPage < _totalPages; bool get hasPreviousPage => _currentPage > 1; // 초기 데이터 로드 Future initialize() async { // 초기 로딩 상태만 설정하고, 실제 데이터 로딩은 다음 프레임에서 실행 _isLoading = true; notifyListeners(); await Future.wait([ loadVendors(), loadVendorStats(), ]); } // 벤더 목록 로드 Future loadVendors({bool refresh = false}) async { if (refresh) { _currentPage = 1; } _setLoading(true); _clearError(); try { final response = await _vendorUseCase.getVendors( page: _currentPage, limit: _pageSize, search: _searchQuery.isNotEmpty ? _searchQuery : null, isActive: _filterIsActive, ); _vendors = List.from(response.items); _totalCount = response.totalCount; _totalPages = response.totalPages; _currentPage = response.currentPage; notifyListeners(); } catch (e) { _setError('벤더 목록을 불러오는데 실패했습니다: ${e.toString()}'); } finally { _setLoading(false); } } // 벤더 상세 조회 Future selectVendor(int id) async { _setLoading(true); _clearError(); try { _selectedVendor = await _vendorUseCase.getVendorById(id); notifyListeners(); } catch (e) { _setError('벤더 정보를 불러오는데 실패했습니다: ${e.toString()}'); } finally { _setLoading(false); } } // 벤더 생성 Future createVendor(VendorDto vendor) async { _setLoading(true); _clearError(); try { final newVendor = await _vendorUseCase.createVendor(vendor); // 목록 새로고침 await loadVendors(refresh: true); return true; } catch (e) { _setError('벤더 생성에 실패했습니다: ${e.toString()}'); return false; } finally { _setLoading(false); } } // 벤더 수정 Future updateVendor(int id, VendorDto vendor) async { _setLoading(true); _clearError(); try { final updatedVendor = await _vendorUseCase.updateVendor(id, vendor); // 목록에서 해당 벤더 업데이트 final index = _vendors.indexWhere((v) => v.id == id); if (index != -1) { _vendors = _vendors.map((vendor) => vendor.id == id ? updatedVendor : vendor ).toList(); notifyListeners(); } // 선택된 벤더도 업데이트 if (_selectedVendor?.id == id) { _selectedVendor = updatedVendor; } return true; } catch (e) { _setError('벤더 수정에 실패했습니다: ${e.toString()}'); return false; } finally { _setLoading(false); } } // 벤더 삭제 Future deleteVendor(int id) async { _setLoading(true); _clearError(); try { await _vendorUseCase.deleteVendor(id); // 목록에서 제거 _vendors = _vendors.where((v) => v.id != id).toList(); // 선택된 벤더가 삭제된 경우 초기화 if (_selectedVendor?.id == id) { _selectedVendor = null; } notifyListeners(); return true; } catch (e) { _setError('벤더 삭제에 실패했습니다: ${e.toString()}'); return false; } finally { _setLoading(false); } } // 벤더 복원 Future restoreVendor(int id) async { _setLoading(true); _clearError(); try { await _vendorUseCase.restoreVendor(id); // 목록 새로고침 await loadVendors(); return true; } catch (e) { _setError('벤더 복원에 실패했습니다: ${e.toString()}'); return false; } finally { _setLoading(false); } } // 검색 쿼리 설정 void setSearchQuery(String query) { _searchQuery = query; notifyListeners(); } // 검색 실행 (디바운스 적용 필요) Future search() async { _currentPage = 1; await loadVendors(); } // 활성 상태 필터 설정 void setFilterIsActive(bool? isActive) { _filterIsActive = isActive; notifyListeners(); } // 필터 적용 Future applyFilters() async { _currentPage = 1; await loadVendors(); } // 필터 초기화 Future clearFilters() async { _searchQuery = ''; _filterIsActive = null; _currentPage = 1; await loadVendors(); } // 페이지 이동 Future goToPage(int page) async { if (page < 1 || page > _totalPages) return; _currentPage = page; await loadVendors(); } // 다음 페이지 Future nextPage() async { if (hasNextPage) { await goToPage(_currentPage + 1); } } // 이전 페이지 Future previousPage() async { if (hasPreviousPage) { await goToPage(_currentPage - 1); } } // 벤더명 중복 체크 Future checkDuplicateName(String name, {int? excludeId}) async { try { return await _vendorUseCase.checkDuplicateName(name, excludeId: excludeId); } catch (e) { return false; } } // 벤더 데이터 검증 Future validateVendor(VendorDto vendor) async { try { return await _vendorUseCase.validateVendor(vendor); } catch (e) { _setError('검증 실패: ${e.toString()}'); return false; } } // 선택 초기화 void clearSelection() { _selectedVendor = null; notifyListeners(); } // 내부 헬퍼 메서드 void _setLoading(bool loading) { _isLoading = loading; notifyListeners(); } void _setError(String message) { _errorMessage = message; notifyListeners(); } void _clearError() { _errorMessage = null; } // 벤더 통계 로드 Future loadVendorStats() async { _isStatsLoading = true; notifyListeners(); try { _vendorStats = await _vendorUseCase.getVendorStats(); } catch (e) { _setError('벤더 통계를 불러오는데 실패했습니다: ${e.toString()}'); } finally { _isStatsLoading = false; notifyListeners(); } } @override void dispose() { _vendors = []; // clear() 대신 새로운 빈 리스트 할당 _selectedVendor = null; _vendorStats = null; super.dispose(); } }