UI 전체 리디자인 및 개선사항 적용
## 주요 변경사항: ### UI/UX 개선 - shadcn/ui 스타일 기반의 새로운 디자인 시스템 도입 - 모든 주요 화면에 대한 리디자인 구현 완료 - 로그인 화면: 모던한 카드 스타일 적용 - 대시보드: 통계 카드와 차트를 활용한 개요 화면 - 리스트 화면들: 일관된 테이블 디자인과 검색/필터 기능 - 다크모드 지원을 위한 테마 시스템 구축 ### 기능 개선 - Equipment List: 고급 필터링 (상태, 담당자별) - Company List: 검색 및 정렬 기능 강화 - User List: 역할별 필터링 추가 - License List: 만료일 기반 상태 표시 - Warehouse Location: 재고 수준 시각화 ### 기술적 개선 - 재사용 가능한 컴포넌트 라이브러리 구축 - 일관된 코드 패턴 가이드라인 작성 - 프로젝트 구조 분석 및 문서화 ### 문서화 - 프로젝트 분석 문서 추가 - UI 리디자인 진행 상황 문서 - 코드 패턴 가이드 작성 - Equipment 기능 격차 분석 및 구현 계획 ### 삭제/리팩토링 - goods_list.dart 제거 (equipment_list로 통합) - 불필요한 import 및 코드 정리 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
297
.claude/equipment_implementation_plan.md
Normal file
297
.claude/equipment_implementation_plan.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Equipment List 마이그레이션 상세 구현 계획
|
||||
|
||||
## 아키텍처 통합 전략
|
||||
|
||||
### 상태 관리 패턴
|
||||
- **기존 패턴 유지**: `EquipmentListController` 사용
|
||||
- **선택 상태 관리**: `selectedEquipmentIds` Map 구조 유지
|
||||
- **데이터 로딩**: `MockDataService` 싱글톤 패턴 유지
|
||||
- **라이프사이클**: initState, dispose 패턴 준수
|
||||
|
||||
### 의존성 구조
|
||||
```dart
|
||||
equipment_list_redesign.dart
|
||||
├── EquipmentListController (기존 컨트롤러 재사용)
|
||||
├── MockDataService (기존 서비스 재사용)
|
||||
├── UnifiedEquipment 모델 (기존 모델 재사용)
|
||||
├── ShadcnTheme (새로운 테마 시스템)
|
||||
└── ShadcnComponents (새로운 UI 컴포넌트)
|
||||
```
|
||||
|
||||
### 이벤트 처리
|
||||
- **선택 이벤트**: 기존 `_onEquipmentSelected` 메서드 구조 유지
|
||||
- **액션 이벤트**: 기존 핸들러 메서드 구조 유지
|
||||
- **네비게이션**: Named Route 방식 유지
|
||||
|
||||
## 기능별 마이그레이션 계획
|
||||
|
||||
### 우선순위 1: 핵심 기능 (Days 1-3)
|
||||
|
||||
#### 1.1 체크박스 선택 기능
|
||||
**수용 기준**:
|
||||
- 각 행에 체크박스 표시
|
||||
- 선택된 항목 개수 실시간 표시
|
||||
- 상태별 선택 개수 구분 표시
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
// 테이블 헤더에 체크박스 컬럼 추가
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Checkbox(
|
||||
value: _isAllSelected(),
|
||||
onChanged: _onSelectAll,
|
||||
),
|
||||
),
|
||||
|
||||
// 각 행에 체크박스 추가
|
||||
Checkbox(
|
||||
value: _controller.selectedEquipmentIds.containsKey('${equipment.status}_${equipment.id}'),
|
||||
onChanged: (value) => _onEquipmentSelected(equipment.id, equipment.status, value),
|
||||
),
|
||||
```
|
||||
|
||||
#### 1.2 편집/삭제 버튼
|
||||
**수용 기준**:
|
||||
- 각 행 끝에 편집/삭제 아이콘 버튼
|
||||
- 삭제 시 확인 다이얼로그
|
||||
- 편집 시 해당 폼으로 네비게이션
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
// 액션 버튼 컬럼 추가
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.edit_outlined, size: 16),
|
||||
onPressed: () => _handleEdit(equipment),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.delete_outline, size: 16),
|
||||
onPressed: () => _handleDelete(equipment),
|
||||
),
|
||||
],
|
||||
),
|
||||
```
|
||||
|
||||
#### 1.3 상세 정보 표시
|
||||
**수용 기준**:
|
||||
- 시리얼번호, 바코드 컬럼 추가
|
||||
- 출고/대여 상태일 때 회사, 담당자, 라이센스 정보 표시
|
||||
- 간소화 모드에서는 주요 정보만 표시
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
// 상세 정보 컬럼 조건부 표시
|
||||
if (_showDetailedColumns) ...[
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(equipment.equipment.serialNumber ?? '-'),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(equipment.equipment.barcode ?? '-'),
|
||||
),
|
||||
],
|
||||
|
||||
// 출고 정보 표시
|
||||
if (equipment.status == EquipmentStatus.out) ...[
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(_controller.getOutEquipmentInfo(equipment.id, 'company')),
|
||||
),
|
||||
],
|
||||
```
|
||||
|
||||
### 우선순위 2: 라우트별 기능 (Days 4-6)
|
||||
|
||||
#### 2.1 라우트별 액션 버튼
|
||||
**수용 기준**:
|
||||
- 입고 목록: 입고/출고/대여/폐기 버튼
|
||||
- 출고 목록: 재입고/수리요청 버튼
|
||||
- 대여 목록: 반납/연장 버튼
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
Widget _buildRouteSpecificActions() {
|
||||
switch (widget.currentRoute) {
|
||||
case Routes.equipmentInList:
|
||||
return Row(
|
||||
children: [
|
||||
ShadcnButton(
|
||||
text: '출고',
|
||||
onPressed: _selectedInCount > 0 ? _handleOutEquipment : null,
|
||||
icon: Icon(Icons.exit_to_app, size: 16),
|
||||
),
|
||||
// ... 다른 버튼들
|
||||
],
|
||||
);
|
||||
case Routes.equipmentOutList:
|
||||
// ... 출고 목록 전용 버튼들
|
||||
default:
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 검색 기능 확장
|
||||
**수용 기준**:
|
||||
- 시리얼번호, 바코드, 비고 필드 검색
|
||||
- Enter 키로 검색 실행
|
||||
- 검색어 하이라이트 (선택사항)
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
// 확장된 검색 로직
|
||||
equipments.where((e) {
|
||||
final keyword = _appliedSearchKeyword.toLowerCase();
|
||||
return [
|
||||
e.equipment.manufacturer,
|
||||
e.equipment.name,
|
||||
e.equipment.category,
|
||||
e.equipment.subCategory,
|
||||
e.equipment.subSubCategory,
|
||||
e.equipment.serialNumber ?? '',
|
||||
e.equipment.barcode ?? '',
|
||||
e.equipment.remark ?? '',
|
||||
e.notes ?? '',
|
||||
].any((field) => field.toLowerCase().contains(keyword));
|
||||
}).toList();
|
||||
```
|
||||
|
||||
### 우선순위 3: UX 개선 (Days 7-10)
|
||||
|
||||
#### 3.1 상세/간소화 뷰 전환
|
||||
**수용 기준**:
|
||||
- 토글 버튼으로 뷰 모드 전환
|
||||
- 화면 크기에 따른 자동 조정
|
||||
- 사용자 선택 기억
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
// 헤더에 토글 버튼 추가
|
||||
IconButton(
|
||||
icon: Icon(_showDetailedColumns ? Icons.view_column : Icons.view_compact),
|
||||
onPressed: () => setState(() => _showDetailedColumns = !_showDetailedColumns),
|
||||
),
|
||||
|
||||
// 화면 크기 감지
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
_showDetailedColumns = width > 900;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 가로 스크롤 지원
|
||||
**수용 기준**:
|
||||
- 좁은 화면에서 테이블 가로 스크롤
|
||||
- 스크롤바 표시
|
||||
- 최소 너비 보장
|
||||
|
||||
**구현 방법**:
|
||||
```dart
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: 1200),
|
||||
child: _buildTable(),
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
## 성능 최적화 전략
|
||||
|
||||
### 렌더링 최적화
|
||||
```dart
|
||||
// const 생성자 활용
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.edit),
|
||||
|
||||
// 조건부 렌더링 최적화
|
||||
if (_showDetailedColumns) _buildDetailedColumns(),
|
||||
|
||||
// ListView.builder 사용 검토 (대량 데이터)
|
||||
```
|
||||
|
||||
### 상태 관리 최적화
|
||||
```dart
|
||||
// 불필요한 setState 방지
|
||||
if (_selectedStatus != newStatus) {
|
||||
setState(() => _selectedStatus = newStatus);
|
||||
}
|
||||
|
||||
// 컨트롤러 재사용
|
||||
late final EquipmentListController _controller;
|
||||
```
|
||||
|
||||
## 테스트 전략
|
||||
|
||||
### 단위 테스트
|
||||
```dart
|
||||
// 선택 기능 테스트
|
||||
test('equipment selection works correctly', () {
|
||||
controller.selectEquipment(1, 'I', true);
|
||||
expect(controller.getSelectedInStockCount(), 1);
|
||||
});
|
||||
|
||||
// 검색 기능 테스트
|
||||
test('search filters equipment correctly', () {
|
||||
final filtered = controller.searchEquipments('Dell');
|
||||
expect(filtered.length, greaterThan(0));
|
||||
});
|
||||
```
|
||||
|
||||
### 위젯 테스트
|
||||
```dart
|
||||
// UI 렌더링 테스트
|
||||
testWidgets('equipment table renders correctly', (tester) async {
|
||||
await tester.pumpWidget(EquipmentListRedesign());
|
||||
expect(find.byType(DataTable), findsOneWidget);
|
||||
});
|
||||
|
||||
// 상호작용 테스트
|
||||
testWidgets('checkbox selection updates UI', (tester) async {
|
||||
await tester.tap(find.byType(Checkbox).first);
|
||||
await tester.pump();
|
||||
expect(find.text('1개 선택됨'), findsOneWidget);
|
||||
});
|
||||
```
|
||||
|
||||
## 마이그레이션 체크리스트
|
||||
|
||||
### Phase 1 완료 기준
|
||||
- [ ] 체크박스 선택 기능 구현 및 테스트
|
||||
- [ ] 편집/삭제 버튼 구현 및 테스트
|
||||
- [ ] 상세 정보 표시 구현 및 테스트
|
||||
- [ ] 기존 equipment_list와 기능 동일성 확인
|
||||
|
||||
### Phase 2 완료 기준
|
||||
- [ ] 라우트별 액션 버튼 구현
|
||||
- [ ] 검색 기능 확장 구현
|
||||
- [ ] 출고 정보 표시 구현
|
||||
- [ ] 모든 액션 핸들러 작동 확인
|
||||
|
||||
### Phase 3 완료 기준
|
||||
- [ ] 상세/간소화 뷰 전환 구현
|
||||
- [ ] 반응형 레이아웃 구현
|
||||
- [ ] 성능 최적화 완료
|
||||
- [ ] 전체 기능 통합 테스트 통과
|
||||
|
||||
## 리스크 및 대응 방안
|
||||
|
||||
### 잠재 리스크
|
||||
1. **상태 관리 복잡도**: 선택 상태와 필터 상태의 동기화
|
||||
- 대응: 명확한 상태 플로우 문서화
|
||||
|
||||
2. **UI 일관성**: shadcn 스타일과 기존 기능의 조화
|
||||
- 대응: 디자인 시스템 엄격 준수
|
||||
|
||||
3. **성능 이슈**: 대량 데이터 처리 시 렌더링 지연
|
||||
- 대응: 가상 스크롤링 도입 검토
|
||||
|
||||
---
|
||||
|
||||
*작성일: 2025-07-07*
|
||||
Reference in New Issue
Block a user