공통화: - status-config.ts 신규 추가 (상태 설정 중앙 관리) - StatusBadge 컴포넌트 개선 - 뱃지 공통화 가이드 문서 추가 상세 페이지 훅 시스템: - useDetailData, useDetailPageState, useDetailPermissions, useCRUDHandlers 훅 신규 추가 - hooks/index.ts 진입점 추가 - BillDetailV2 신규 컴포넌트 추가 리팩토링: - 회계(매입/어음/거래처), 품목, 단가, 견적, 주문 상태 뱃지 공통화 적용 - 생산(작업지시서/대시보드/작업자화면), 품질(검사관리) 상태 뱃지 적용 - 공사관리(칸반/프로젝트카드) 상태 뱃지 적용 - 고객센터(문의관리), 인사(직원CSV업로드) 개선 - 리스트 페이지 공통화 현황 분석 문서 추가 상수 정리: - lib/constants/ 디렉토리 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
277 lines
7.2 KiB
Markdown
277 lines
7.2 KiB
Markdown
# Badge 공통화 가이드
|
|
|
|
> 작성일: 2026-02-05
|
|
> 목적: 리스트 페이지에서 Badge 스타일을 공통 유틸로 통일하는 방법 안내
|
|
|
|
---
|
|
|
|
## 📦 공통 유틸 위치
|
|
|
|
```
|
|
src/lib/utils/status-config.ts ← Badge 스타일 및 상태 설정
|
|
src/lib/constants/filter-presets.ts ← 필터 프리셋
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 1. 프리셋 스타일 사용하기
|
|
|
|
### 사용 가능한 프리셋
|
|
|
|
| 프리셋 | 스타일 | 용도 |
|
|
|--------|--------|------|
|
|
| `default` | `bg-gray-100 text-gray-800` | 기본/일반 |
|
|
| `success` | `bg-green-100 text-green-800` | 완료/성공/활성 |
|
|
| `warning` | `bg-yellow-100 text-yellow-800` | 대기/주의 |
|
|
| `destructive` | `bg-red-100 text-red-800` | 오류/반려/긴급 |
|
|
| `info` | `bg-blue-100 text-blue-800` | 진행중/정보 |
|
|
| `muted` | `bg-gray-100 text-gray-500` | 비활성/무효 |
|
|
| `orange` | `bg-orange-100 text-orange-800` | 우선/경고 |
|
|
| `purple` | `bg-purple-100 text-purple-800` | 제품/특수 |
|
|
|
|
### 기본 사용법
|
|
|
|
```tsx
|
|
import { getPresetStyle } from '@/lib/utils/status-config';
|
|
|
|
// 프리셋 스타일 가져오기
|
|
const style = getPresetStyle('success'); // "bg-green-100 text-green-800"
|
|
|
|
// Badge에 적용
|
|
<Badge className={getPresetStyle('warning')}>대기</Badge>
|
|
```
|
|
|
|
---
|
|
|
|
## 🏷️ 2. 우선순위 Badge
|
|
|
|
### 공통 유틸 사용
|
|
|
|
```tsx
|
|
import { getPriorityLabel, getPriorityStyle } from '@/lib/utils/status-config';
|
|
|
|
// 우선순위 Badge 렌더링
|
|
function PriorityBadge({ priority }: { priority: string }) {
|
|
return (
|
|
<Badge variant="outline" className={getPriorityStyle(priority)}>
|
|
{getPriorityLabel(priority)}
|
|
</Badge>
|
|
);
|
|
}
|
|
|
|
// 사용
|
|
<PriorityBadge priority="urgent" /> // 긴급 (빨간색)
|
|
<PriorityBadge priority="priority" /> // 우선 (주황색)
|
|
<PriorityBadge priority="normal" /> // 일반 (회색)
|
|
```
|
|
|
|
### Before (개별 정의) ❌
|
|
|
|
```tsx
|
|
// 각 페이지마다 반복되던 코드
|
|
const PRIORITY_COLORS: Record<string, string> = {
|
|
'긴급': 'bg-red-100 text-red-700',
|
|
'우선': 'bg-orange-100 text-orange-700',
|
|
'일반': 'bg-gray-100 text-gray-700',
|
|
};
|
|
```
|
|
|
|
### After (공통 유틸) ✅
|
|
|
|
```tsx
|
|
import { getPriorityLabel, getPriorityStyle } from '@/lib/utils/status-config';
|
|
|
|
<Badge className={getPriorityStyle(item.priority)}>
|
|
{getPriorityLabel(item.priority)}
|
|
</Badge>
|
|
```
|
|
|
|
---
|
|
|
|
## 📦 3. 품목 유형 Badge
|
|
|
|
### 공통 유틸 사용
|
|
|
|
```tsx
|
|
import { getItemTypeLabel, getItemTypeStyle } from '@/lib/utils/status-config';
|
|
|
|
// 품목 유형 Badge 렌더링
|
|
function ItemTypeBadge({ itemType }: { itemType: string }) {
|
|
return (
|
|
<Badge variant="outline" className={getItemTypeStyle(itemType)}>
|
|
{getItemTypeLabel(itemType)}
|
|
</Badge>
|
|
);
|
|
}
|
|
|
|
// 사용
|
|
<ItemTypeBadge itemType="FG" /> // 제품 (보라색)
|
|
<ItemTypeBadge itemType="PT" /> // 부품 (주황색)
|
|
<ItemTypeBadge itemType="SM" /> // 부자재 (녹색)
|
|
<ItemTypeBadge itemType="RM" /> // 원자재 (파란색)
|
|
<ItemTypeBadge itemType="CS" /> // 소모품 (회색)
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 4. 커스텀 상태 설정 만들기
|
|
|
|
### createStatusConfig 사용법
|
|
|
|
```tsx
|
|
import { createStatusConfig } from '@/lib/utils/status-config';
|
|
|
|
// 도메인별 커스텀 상태 정의
|
|
const {
|
|
STATUS_OPTIONS, // Select 옵션용
|
|
STATUS_LABELS, // 라벨 맵
|
|
STATUS_STYLES, // 스타일 맵
|
|
getStatusLabel, // 라벨 헬퍼
|
|
getStatusStyle, // 스타일 헬퍼
|
|
} = createStatusConfig({
|
|
draft: { label: '임시저장', style: 'muted' },
|
|
pending: { label: '승인대기', style: 'warning' },
|
|
approved: { label: '승인완료', style: 'success' },
|
|
rejected: { label: '반려', style: 'destructive' },
|
|
}, { includeAll: true, allLabel: '전체' });
|
|
|
|
// 사용
|
|
<Badge className={getStatusStyle(item.status)}>
|
|
{getStatusLabel(item.status)}
|
|
</Badge>
|
|
|
|
// Select 옵션으로도 사용 가능
|
|
<Select>
|
|
{STATUS_OPTIONS.map(opt => (
|
|
<SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>
|
|
))}
|
|
</Select>
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ 5. 미리 정의된 공통 설정 사용하기
|
|
|
|
### 바로 사용 가능한 설정들
|
|
|
|
```tsx
|
|
import {
|
|
COMMON_STATUS_CONFIG, // 대기/진행/완료
|
|
WORK_STATUS_CONFIG, // 작업대기/진행중/작업완료
|
|
APPROVAL_STATUS_CONFIG, // 승인대기/승인완료/반려
|
|
ACTIVE_STATUS_CONFIG, // 활성/비활성
|
|
SHIPMENT_STATUS_CONFIG, // 출고예정/대기/중/완료
|
|
RECEIVING_STATUS_CONFIG, // 입고예정/대기/검사중/완료/반품
|
|
} from '@/lib/utils/status-config';
|
|
|
|
// 사용 예시
|
|
<Badge className={COMMON_STATUS_CONFIG.getStatusStyle(item.status)}>
|
|
{COMMON_STATUS_CONFIG.getStatusLabel(item.status)}
|
|
</Badge>
|
|
|
|
// 필터 옵션으로 사용
|
|
filterConfig: [
|
|
{
|
|
key: 'status',
|
|
label: '상태',
|
|
type: 'single',
|
|
options: WORK_STATUS_CONFIG.STATUS_OPTIONS.filter(opt => opt.value !== 'all'),
|
|
},
|
|
],
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 6. 마이그레이션 체크리스트
|
|
|
|
### 기존 코드에서 공통 유틸로 전환하기
|
|
|
|
1. **우선순위 색상 정의 찾기**
|
|
```bash
|
|
# 검색
|
|
grep -r "PRIORITY_COLORS" src/components/
|
|
grep -r "'긴급'" src/components/
|
|
```
|
|
|
|
2. **import 추가**
|
|
```tsx
|
|
import { getPriorityLabel, getPriorityStyle } from '@/lib/utils/status-config';
|
|
```
|
|
|
|
3. **기존 코드 교체**
|
|
```tsx
|
|
// Before
|
|
const color = PRIORITY_COLORS[item.priority] || '';
|
|
<Badge className={color}>{item.priority}</Badge>
|
|
|
|
// After
|
|
<Badge className={getPriorityStyle(item.priority)}>
|
|
{getPriorityLabel(item.priority)}
|
|
</Badge>
|
|
```
|
|
|
|
4. **기존 상수 정의 삭제**
|
|
```tsx
|
|
// 삭제
|
|
const PRIORITY_COLORS: Record<string, string> = { ... };
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 7. 필터 프리셋 함께 사용하기
|
|
|
|
### filter-presets.ts와 연계
|
|
|
|
```tsx
|
|
import { COMMON_PRIORITY_FILTER, WORK_STATUS_FILTER } from '@/lib/constants/filter-presets';
|
|
import { getPriorityStyle, WORK_STATUS_CONFIG } from '@/lib/utils/status-config';
|
|
|
|
// UniversalListPage config
|
|
const config: UniversalListConfig<MyItem> = {
|
|
// ...
|
|
|
|
// 필터 설정 (공통 프리셋 사용)
|
|
filterConfig: [
|
|
WORK_STATUS_FILTER,
|
|
COMMON_PRIORITY_FILTER,
|
|
],
|
|
|
|
// 테이블 행에서 Badge 사용 (공통 스타일 사용)
|
|
renderTableRow: (item, index, globalIndex, handlers) => (
|
|
<TableRow>
|
|
{/* ... */}
|
|
<TableCell>
|
|
<Badge className={WORK_STATUS_CONFIG.getStatusStyle(item.status)}>
|
|
{WORK_STATUS_CONFIG.getStatusLabel(item.status)}
|
|
</Badge>
|
|
</TableCell>
|
|
<TableCell>
|
|
<Badge className={getPriorityStyle(item.priority)}>
|
|
{getPriorityLabel(item.priority)}
|
|
</Badge>
|
|
</TableCell>
|
|
</TableRow>
|
|
),
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 변경 효과
|
|
|
|
| 항목 | Before | After |
|
|
|------|--------|-------|
|
|
| 우선순위 색상 정의 | 각 페이지 개별 | 1곳 (status-config.ts) |
|
|
| 품목유형 색상 정의 | 각 페이지 개별 | 1곳 (status-config.ts) |
|
|
| 색상 변경 시 | 모든 파일 수정 | 1개 파일만 수정 |
|
|
| 일관성 | 파일마다 다를 수 있음 | 항상 동일 |
|
|
| 신규 개발 시 | 기존 코드 복사 필요 | import만 하면 됨 |
|
|
|
|
---
|
|
|
|
## 🚨 주의사항
|
|
|
|
1. **기존 기능 유지**: 마이그레이션 시 동작이 동일한지 확인
|
|
2. **점진적 적용**: 한 번에 모든 파일 변경하지 말고, 수정하는 파일만 적용
|
|
3. **테스트**: Badge 색상이 기존과 동일하게 표시되는지 확인
|