feat(frontend): 승인 템플릿 API 통합 및 디버그 로그인 확장

- docs 폴더 문서를 최신 API 계약으로 갱신하고 가이드를 다듬었다\n- approvals data/presentation 레이어를 API v4 스펙에 맞춰 리팩터링했다\n- approver 자동완성 위젯을 신규 공유 레포지토리에 맞춰 교체하고 UX를 보강했다\n- inventory/rental 페이지 테이블 초기화 시 승인 기준 연동을 정비했다\n- 로그인 페이지 디버그 버튼을 tera/exa 계정으로 분리해 QA 로그인을 단순화했다\n- get_it 등록과 테스트 케이스를 신규 공유 리포지토리에 맞춰 업데이트했다
This commit is contained in:
JiWoong Sul
2025-11-05 17:05:38 +09:00
parent 3e83408aa7
commit fa0bda5ea4
28 changed files with 1102 additions and 545 deletions

View File

@@ -42,6 +42,7 @@ class ProductController extends ChangeNotifier {
List<Vendor> _vendorOptions = const [];
List<Uom> _uomOptions = const [];
bool _isDisposed = false;
PaginatedResult<Product>? get result => _result;
bool get isLoading => _isLoading;
@@ -60,7 +61,7 @@ class ProductController extends ChangeNotifier {
Future<void> fetch({int page = 1}) async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
_notifySafely();
try {
final previous = _result;
final int resolvedPage;
@@ -95,14 +96,14 @@ class ProductController extends ChangeNotifier {
_errorMessage = failure.describe();
} finally {
_isLoading = false;
notifyListeners();
_notifySafely();
}
}
/// 필터/폼에서 사용할 공급업체와 단위 목록을 로드한다.
Future<void> loadLookups() async {
_isLoadingLookups = true;
notifyListeners();
_notifySafely();
try {
debugPrint('[ProductController] 드롭다운 데이터 조회 시작');
final vendors = await fetchAllPaginatedItems<Vendor>(
@@ -127,7 +128,7 @@ class ProductController extends ChangeNotifier {
);
} finally {
_isLoadingLookups = false;
notifyListeners();
_notifySafely();
}
}
@@ -137,7 +138,7 @@ class ProductController extends ChangeNotifier {
return;
}
_query = value;
notifyListeners();
_notifySafely();
}
/// 공급업체 필터를 변경한다.
@@ -146,7 +147,7 @@ class ProductController extends ChangeNotifier {
return;
}
_vendorFilter = vendorId;
notifyListeners();
_notifySafely();
}
/// 단위(UOM) 필터를 변경한다.
@@ -155,7 +156,7 @@ class ProductController extends ChangeNotifier {
return;
}
_uomFilter = uomId;
notifyListeners();
_notifySafely();
}
/// 사용 여부 필터를 변경한다.
@@ -164,7 +165,7 @@ class ProductController extends ChangeNotifier {
return;
}
_statusFilter = filter;
notifyListeners();
_notifySafely();
}
/// 페이지 크기를 변경한다.
@@ -173,7 +174,7 @@ class ProductController extends ChangeNotifier {
return;
}
_pageSize = size;
notifyListeners();
_notifySafely();
}
/// 제품을 생성한다.
@@ -186,7 +187,7 @@ class ProductController extends ChangeNotifier {
} catch (error) {
final failure = Failure.from(error);
_errorMessage = failure.describe();
notifyListeners();
_notifySafely();
return null;
} finally {
_setSubmitting(false);
@@ -203,7 +204,7 @@ class ProductController extends ChangeNotifier {
} catch (error) {
final failure = Failure.from(error);
_errorMessage = failure.describe();
notifyListeners();
_notifySafely();
return null;
} finally {
_setSubmitting(false);
@@ -220,7 +221,7 @@ class ProductController extends ChangeNotifier {
} catch (error) {
final failure = Failure.from(error);
_errorMessage = failure.describe();
notifyListeners();
_notifySafely();
return false;
} finally {
_setSubmitting(false);
@@ -237,7 +238,7 @@ class ProductController extends ChangeNotifier {
} catch (error) {
final failure = Failure.from(error);
_errorMessage = failure.describe();
notifyListeners();
_notifySafely();
return null;
} finally {
_setSubmitting(false);
@@ -247,12 +248,26 @@ class ProductController extends ChangeNotifier {
/// 에러 메시지를 초기화한다.
void clearError() {
_errorMessage = null;
notifyListeners();
_notifySafely();
}
/// 제출 상태 플래그를 갱신하고 리스너에 알린다.
void _setSubmitting(bool value) {
_isSubmitting = value;
notifyListeners();
_notifySafely();
}
/// dispose 이후에는 알림을 중단하여 디버그 에러를 방지한다.
void _notifySafely() {
if (_isDisposed) {
return;
}
super.notifyListeners();
}
@override
void dispose() {
_isDisposed = true;
super.dispose();
}
}