결재 템플릿 CRUD 화면과 컨트롤러 정식화

This commit is contained in:
JiWoong Sul
2025-09-25 00:42:25 +09:00
parent c3010965ad
commit 1fbed565b7
10 changed files with 1450 additions and 53 deletions

View File

@@ -0,0 +1,167 @@
import 'package:flutter/foundation.dart';
import 'package:superport_v2/core/common/models/paginated_result.dart';
import '../../../domain/entities/approval_template.dart';
import '../../../domain/repositories/approval_template_repository.dart';
enum ApprovalTemplateStatusFilter { all, activeOnly, inactiveOnly }
/// 결재 템플릿 화면 상태 컨트롤러
///
/// - 목록/검색/필터 상태와 생성·수정·삭제 요청을 관리한다.
class ApprovalTemplateController extends ChangeNotifier {
ApprovalTemplateController({required ApprovalTemplateRepository repository})
: _repository = repository;
final ApprovalTemplateRepository _repository;
PaginatedResult<ApprovalTemplate>? _result;
bool _isLoading = false;
bool _isSubmitting = false;
String _query = '';
ApprovalTemplateStatusFilter _statusFilter = ApprovalTemplateStatusFilter.all;
String? _errorMessage;
PaginatedResult<ApprovalTemplate>? get result => _result;
bool get isLoading => _isLoading;
bool get isSubmitting => _isSubmitting;
String get query => _query;
ApprovalTemplateStatusFilter get statusFilter => _statusFilter;
String? get errorMessage => _errorMessage;
Future<void> fetch({int page = 1}) async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
try {
final sanitizedQuery = _query.trim();
final isActive = switch (_statusFilter) {
ApprovalTemplateStatusFilter.all => null,
ApprovalTemplateStatusFilter.activeOnly => true,
ApprovalTemplateStatusFilter.inactiveOnly => false,
};
final response = await _repository.list(
page: page,
pageSize: _result?.pageSize ?? 20,
query: sanitizedQuery.isEmpty ? null : sanitizedQuery,
isActive: isActive,
);
_result = response;
} catch (e) {
_errorMessage = e.toString();
} finally {
_isLoading = false;
notifyListeners();
}
}
void updateQuery(String value) {
_query = value;
notifyListeners();
}
void updateStatusFilter(ApprovalTemplateStatusFilter filter) {
_statusFilter = filter;
notifyListeners();
}
Future<ApprovalTemplate?> fetchDetail(int id) async {
_errorMessage = null;
notifyListeners();
try {
final detail = await _repository.fetchDetail(id, includeSteps: true);
return detail;
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
return null;
}
}
Future<ApprovalTemplate?> create(
ApprovalTemplateInput input,
List<ApprovalTemplateStepInput> steps,
) async {
_setSubmitting(true);
try {
final created = await _repository.create(input, steps: steps);
await fetch(page: 1);
return created;
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
return null;
} finally {
_setSubmitting(false);
}
}
Future<ApprovalTemplate?> update(
int id,
ApprovalTemplateInput input,
List<ApprovalTemplateStepInput>? steps,
) async {
_setSubmitting(true);
try {
final updated = await _repository.update(id, input, steps: steps);
await fetch(page: _result?.page ?? 1);
return updated;
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
return null;
} finally {
_setSubmitting(false);
}
}
Future<bool> delete(int id) async {
_setSubmitting(true);
try {
await _repository.delete(id);
await fetch(page: _result?.page ?? 1);
return true;
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
return false;
} finally {
_setSubmitting(false);
}
}
Future<ApprovalTemplate?> restore(int id) async {
_setSubmitting(true);
try {
final restored = await _repository.restore(id);
await fetch(page: _result?.page ?? 1);
return restored;
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
return null;
} finally {
_setSubmitting(false);
}
}
void clearError() {
_errorMessage = null;
notifyListeners();
}
bool get hasActiveFilters =>
_query.trim().isNotEmpty ||
_statusFilter != ApprovalTemplateStatusFilter.all;
void resetFilters() {
_query = '';
_statusFilter = ApprovalTemplateStatusFilter.all;
notifyListeners();
}
void _setSubmitting(bool value) {
_isSubmitting = value;
notifyListeners();
}
}