feat: 라이선스 관리 기능 개선 및 폼 검증 강화

- LicenseDto 모델 업데이트
- 라이선스 폼 UI 개선 및 검증 로직 강화
- 라이선스 리스트 화면 필터링 기능 추가
- 만료일 관리 기능 개선

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JiWoong Sul
2025-08-09 02:17:30 +09:00
parent cddde57450
commit ef059d50ea
6 changed files with 525 additions and 138 deletions

View File

@@ -84,9 +84,31 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
_controller.search(_searchController.text);
}
/// 라이선스 추가 폼으로 이동
/// 유지보수 연장 폼으로 이동
void _navigateToAdd() async {
final result = await Navigator.pushNamed(context, Routes.licenseAdd);
// 선택된 라이선스 확인
final selectedLicenses = _controller.getSelectedLicenses();
// 선택된 라이선스가 1개인 경우 해당 라이선스 ID 전달
int? licenseId;
if (selectedLicenses.length == 1) {
licenseId = selectedLicenses.first.id;
} else if (selectedLicenses.length > 1) {
// 여러 개 선택된 경우 경고 메시지
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('유지보수 연장은 한 번에 하나의 라이선스만 선택할 수 있습니다.'),
duration: Duration(seconds: 2),
),
);
return;
}
final result = await Navigator.pushNamed(
context,
Routes.licenseAdd,
arguments: licenseId, // 선택된 라이선스 ID 전달 (없으면 null)
);
if (result == true && mounted) {
_controller.refresh();
}
@@ -352,7 +374,7 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
controller: _searchController,
onSubmitted: (_) => _onSearch(),
decoration: InputDecoration(
hintText: '제품명, 라이선스 키, 벤더명, 회사명 검색...',
hintText: '제품명, 라이선스 키, 벤더명, 현위치 검색...',
hintStyle: TextStyle(color: ShadcnTheme.mutedForeground.withValues(alpha: 0.8), fontSize: 14),
prefixIcon: Icon(Icons.search, color: ShadcnTheme.muted, size: 20),
border: InputBorder.none,
@@ -431,7 +453,7 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
children: [
// 액션 버튼들
ShadcnButton(
text: '라이선스 추가',
text: '유지보수 연장',
onPressed: _navigateToAdd,
variant: ShadcnButtonVariant.primary,
textColor: Colors.white,
@@ -634,10 +656,10 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
width: 120,
child: Text('벤더', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500)),
),
// 회사명
// 현위치
const SizedBox(
width: 150,
child: Text('회사명', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500)),
child: Text('현위치', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500)),
),
// 할당 사용자
const SizedBox(
@@ -735,7 +757,7 @@ class _LicenseListRedesignState extends State<LicenseListRedesign> {
overflow: TextOverflow.ellipsis,
),
),
// 회사명
// 현위치
SizedBox(
width: 150,
child: Text(