diff --git a/claudedocs/guides/[PLAN-2025-12-23] common-component-extraction-plan.md b/claudedocs/guides/[PLAN-2025-12-23] common-component-extraction-plan.md new file mode 100644 index 00000000..27631679 --- /dev/null +++ b/claudedocs/guides/[PLAN-2025-12-23] common-component-extraction-plan.md @@ -0,0 +1,435 @@ +# 공통 컴포넌트 추출 계획서 + +> MVP 완료 후 리팩토링 계획 (2025-12-23) + +## 개요 + +| 항목 | 수치 | +|-----|------| +| 예상 코드 절감 | ~1,900줄 | +| 영향 파일 | 50+ 개 | +| 유지보수 비용 감소 | 30-40% | +| 예상 작업 기간 | 3-4일 | + +--- + +## 현재 공통화 현황 + +### ✅ 잘 되어있는 것 +- `SearchFilter` - 검색 입력 + 필터 +- `TabFilter` - 탭 형태 필터 +- `DateRangeSelector` - 날짜 범위 선택 +- `TableActions` - 테이블 행 액션 버튼 +- `FormActions` - 폼 저장/취소 버튼 +- `FormField` - 개별 폼 필드 +- `StatCards` - 통계 카드 +- `StandardDialog` - 기본 다이얼로그 (but 사용률 저조) + +### ❌ 공통화 필요한 것 +- 삭제 확인 다이얼로그 (40+ 파일 중복) +- 금액 포맷 유틸 (30+ 파일 중복) +- 상태 배지 + 색상 상수 (10+ 파일 중복) +- 상세정보 카드 (15+ 파일 각자 구현) +- 폼 레이아웃 템플릿 (20+ 파일 중복) + +--- + +## Phase 1: 핵심 컴포넌트 (1일) + +### 1.1 DeleteDialog 컴포넌트 + +**위치**: `src/components/molecules/DeleteDialog.tsx` + +**Props 설계**: +```typescript +interface DeleteDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + itemName?: string; // "거래처", "품목" 등 + itemLabel?: string; // 삭제 대상 이름 (예: "삼성전자") + title?: string; // 커스텀 타이틀 + description?: string; // 커스텀 설명 + onConfirm: () => void; + isLoading?: boolean; + confirmText?: string; // 기본값: "삭제" + cancelText?: string; // 기본값: "취소" +} +``` + +**사용 예시**: +```typescript + +``` + +**체크리스트**: +- [ ] DeleteDialog 컴포넌트 생성 +- [ ] 기본 스타일 (빨간색 삭제 버튼) +- [ ] isLoading 상태 처리 +- [ ] 접근성 (포커스 트랩, ESC 닫기) +- [ ] molecules/index.ts export 추가 + +**적용 대상 파일** (40+ 파일): +- [ ] `accounting/VendorManagement/index.tsx` +- [ ] `accounting/BillManagement/index.tsx` +- [ ] `accounting/SalesManagement/index.tsx` +- [ ] `accounting/PurchaseManagement/index.tsx` +- [ ] `accounting/DepositManagement/index.tsx` +- [ ] `accounting/WithdrawalManagement/index.tsx` +- [ ] `hr/EmployeeManagement/index.tsx` +- [ ] `hr/DepartmentManagement/index.tsx` +- [ ] `hr/VacationManagement/index.tsx` +- [ ] `settings/RankManagement/index.tsx` +- [ ] `settings/TitleManagement/index.tsx` +- [ ] `settings/PermissionManagement/index.tsx` +- [ ] `settings/AccountManagement/index.tsx` +- [ ] `board/BoardManagement/index.tsx` +- [ ] `items/ItemListClient.tsx` +- [ ] (나머지 25+ 파일은 grep으로 검색) + +--- + +### 1.2 포맷 유틸 함수 + +**위치**: `src/lib/formatters.ts` + +**함수 설계**: +```typescript +// 금액 포맷 +export function formatCurrency(amount: number): string; +export function formatCurrencyWithSign(amount: number): string; // +/- 표시 + +// 금액 셀 (조건부 표시) +export function formatCurrencyOrDash(amount: number, dash?: string): string; + +// 날짜 포맷 +export function formatDate(date: string | Date, format?: string): string; +export function formatDateTime(date: string | Date): string; + +// 숫자 포맷 +export function formatNumber(num: number): string; +export function formatPercent(num: number, decimals?: number): string; + +// 전화번호 포맷 +export function formatPhone(phone: string): string; + +// 사업자번호 포맷 +export function formatBizNo(bizNo: string): string; +``` + +**사용 예시**: +```typescript +formatCurrency(10000) // "10,000원" +formatCurrencyOrDash(0) // "-" +formatCurrencyWithSign(-5000) // "-5,000원" +formatDate('2024-01-15') // "2024-01-15" +formatPhone('01012345678') // "010-1234-5678" +formatBizNo('1234567890') // "123-45-67890" +``` + +**체크리스트**: +- [ ] formatters.ts 파일 생성 +- [ ] formatCurrency 함수 +- [ ] formatCurrencyOrDash 함수 +- [ ] formatCurrencyWithSign 함수 +- [ ] formatDate 함수 +- [ ] formatDateTime 함수 +- [ ] formatNumber 함수 +- [ ] formatPercent 함수 +- [ ] formatPhone 함수 +- [ ] formatBizNo 함수 +- [ ] 단위 테스트 (선택) + +**적용 대상 파일** (30+ 파일): +- [ ] 모든 accounting/* 컴포넌트 +- [ ] 모든 테이블에서 금액 표시하는 곳 + +--- + +## Phase 2: 상태 표시 컴포넌트 (1일) + +### 2.1 상태 색상 중앙화 + +**위치**: `src/lib/status-colors.ts` + +**설계**: +```typescript +// 공통 상태 색상 +export const STATUS_COLORS = { + // 일반 상태 + active: 'bg-green-100 text-green-800', + inactive: 'bg-gray-100 text-gray-800', + pending: 'bg-yellow-100 text-yellow-800', + completed: 'bg-blue-100 text-blue-800', + cancelled: 'bg-red-100 text-red-800', + + // 결제/금융 상태 + paid: 'bg-green-100 text-green-800', + unpaid: 'bg-red-100 text-red-800', + partial: 'bg-orange-100 text-orange-800', + overdue: 'bg-red-100 text-red-800', + + // 기본값 + default: 'bg-gray-100 text-gray-800', +} as const; + +// 도메인별 상태 색상 +export const BILL_STATUS_COLORS = { ... }; +export const VENDOR_CATEGORY_COLORS = { ... }; +export const ORDER_STATUS_COLORS = { ... }; +export const INSPECTION_STATUS_COLORS = { ... }; +``` + +**체크리스트**: +- [ ] status-colors.ts 파일 생성 +- [ ] 공통 STATUS_COLORS 정의 +- [ ] BILL_STATUS_COLORS 이동 +- [ ] VENDOR_CATEGORY_COLORS 이동 +- [ ] ORDER_STATUS_COLORS 정의 +- [ ] INSPECTION_STATUS_COLORS 정의 +- [ ] PRODUCTION_STATUS_COLORS 정의 + +--- + +### 2.2 StatusBadge 컴포넌트 + +**위치**: `src/components/ui/status-badge.tsx` + +**Props 설계**: +```typescript +interface StatusBadgeProps { + status: string; + label?: string; + colorMap?: Record; + size?: 'sm' | 'md' | 'lg'; + className?: string; +} +``` + +**사용 예시**: +```typescript +// 색상맵 지정 + + +// 공통 색상 사용 + +``` + +**체크리스트**: +- [ ] StatusBadge 컴포넌트 생성 +- [ ] 기본 색상 (STATUS_COLORS) 적용 +- [ ] colorMap prop으로 커스텀 색상 지원 +- [ ] size 변형 (sm, md, lg) +- [ ] ui/index.ts export 추가 + +**적용 대상 파일** (10+ 파일): +- [ ] `accounting/BillManagement/index.tsx` +- [ ] `accounting/SalesManagement/index.tsx` +- [ ] `accounting/VendorManagement/index.tsx` +- [ ] `production/WorkOrders/WorkOrderList.tsx` +- [ ] `quality/InspectionManagement/InspectionList.tsx` +- [ ] (나머지 파일) + +--- + +## Phase 3: 카드/레이아웃 컴포넌트 (1일) + +### 3.1 DetailInfoCard 컴포넌트 + +**위치**: `src/components/molecules/DetailInfoCard.tsx` + +**Props 설계**: +```typescript +interface InfoItem { + label: string; + value: React.ReactNode; + className?: string; + span?: number; // grid span +} + +interface DetailInfoCardProps { + title?: string; + description?: string; + items: InfoItem[]; + columns?: 1 | 2 | 3 | 4; + className?: string; + headerAction?: React.ReactNode; +} +``` + +**사용 예시**: +```typescript +수정} + items={[ + { label: '상호명', value: data.name }, + { label: '사업자번호', value: formatBizNo(data.bizNo) }, + { label: '대표자', value: data.ceo }, + { label: '연락처', value: formatPhone(data.phone) }, + { label: '주소', value: data.address, span: 2 }, + ]} +/> +``` + +**체크리스트**: +- [ ] DetailInfoCard 컴포넌트 생성 +- [ ] columns 1/2/3/4 지원 +- [ ] span으로 컬럼 병합 지원 +- [ ] headerAction 슬롯 +- [ ] 반응형 (모바일에서 1컬럼) +- [ ] molecules/index.ts export 추가 + +**적용 대상 파일** (15+ 파일): +- [ ] `accounting/VendorManagement/VendorDetail.tsx` +- [ ] `accounting/BillManagement/BillDetail.tsx` +- [ ] `accounting/SalesManagement/SalesDetail.tsx` +- [ ] `accounting/PurchaseManagement/PurchaseDetail.tsx` +- [ ] `hr/EmployeeManagement/EmployeeDetail.tsx` +- [ ] (나머지 Detail 페이지들) + +--- + +### 3.2 FormGridLayout 컴포넌트 + +**위치**: `src/components/molecules/FormGridLayout.tsx` + +**Props 설계**: +```typescript +interface FormGridLayoutProps { + children: React.ReactNode; + columns?: 1 | 2 | 3 | 4; + gap?: 'sm' | 'md' | 'lg'; + className?: string; +} + +interface FormSectionProps { + title?: string; + description?: string; + children: React.ReactNode; + columns?: 1 | 2 | 3 | 4; +} +``` + +**사용 예시**: +```typescript + + + + + +``` + +**체크리스트**: +- [ ] FormGridLayout 컴포넌트 생성 +- [ ] FormSection 컴포넌트 생성 +- [ ] columns 1/2/3/4 지원 +- [ ] gap 크기 (sm/md/lg) +- [ ] col-span 클래스 지원 +- [ ] 반응형 + +--- + +## Phase 4: 마이그레이션 및 검증 (1일) + +### 4.1 기존 코드 마이그레이션 + +**체크리스트**: +- [ ] DeleteDialog 마이그레이션 (40+ 파일) +- [ ] formatCurrency 마이그레이션 (30+ 파일) +- [ ] StatusBadge 마이그레이션 (10+ 파일) +- [ ] DetailInfoCard 마이그레이션 (15+ 파일) +- [ ] 불필요한 import 제거 +- [ ] 미사용 코드 삭제 + +### 4.2 검증 + +**체크리스트**: +- [ ] 빌드 에러 없음 확인 (`npm run build`) +- [ ] 타입 에러 없음 확인 (`npm run type-check`) +- [ ] 주요 페이지 동작 테스트 + - [ ] 거래처 삭제 + - [ ] 품목 삭제 + - [ ] 금액 표시 확인 + - [ ] 상태 배지 표시 확인 +- [ ] 반응형 테스트 (모바일) + +### 4.3 문서화 + +**체크리스트**: +- [ ] 컴포넌트 JSDoc 주석 +- [ ] 사용 예시 코드 +- [ ] claudedocs 업데이트 + +--- + +## 파일 구조 (최종) + +``` +src/ +├── components/ +│ ├── ui/ +│ │ ├── status-badge.tsx # 🆕 Phase 2 +│ │ └── ... +│ ├── molecules/ +│ │ ├── StandardDialog.tsx # 기존 +│ │ ├── DeleteDialog.tsx # 🆕 Phase 1 +│ │ ├── DetailInfoCard.tsx # 🆕 Phase 3 +│ │ ├── FormGridLayout.tsx # 🆕 Phase 3 +│ │ └── index.ts +│ └── ... +├── lib/ +│ ├── formatters.ts # 🆕 Phase 1 +│ ├── status-colors.ts # 🆕 Phase 2 +│ └── ... +└── ... +``` + +--- + +## 예상 효과 + +| Phase | 컴포넌트 | 절감 라인 | 영향 파일 | +|-------|---------|----------|----------| +| 1 | DeleteDialog | ~800줄 | 40+ | +| 1 | formatters | ~150줄 | 30+ | +| 2 | status-colors | ~200줄 | 10+ | +| 2 | StatusBadge | ~100줄 | 10+ | +| 3 | DetailInfoCard | ~400줄 | 15+ | +| 3 | FormGridLayout | ~250줄 | 20+ | +| **합계** | | **~1,900줄** | **50+** | + +--- + +## 우선순위 정리 + +### 🔴 필수 (Phase 1) +1. **DeleteDialog** - 가장 많은 중복, 즉시 효과 +2. **formatters** - 유틸 함수, 간단히 적용 + +### 🟡 권장 (Phase 2) +3. **status-colors** - 색상 상수 중앙화 +4. **StatusBadge** - 일관된 상태 표시 + +### 🟢 선택 (Phase 3) +5. **DetailInfoCard** - 상세 페이지 통일 +6. **FormGridLayout** - 폼 레이아웃 통일 + +--- + +## 변경 이력 + +| 날짜 | 변경 내용 | +|-----|----------| +| 2025-12-23 | 최초 작성 - 공통 컴포넌트 추출 계획 | \ No newline at end of file diff --git a/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx b/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx index ba9b3c82..37f04272 100644 --- a/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx +++ b/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx @@ -578,7 +578,7 @@ export default function CustomerAccountManagementPage() { description="거래처 정보 및 계정을 관리합니다" icon={Building2} headerActions={ - diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx index 1f0badd7..fb5dbd94 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx @@ -661,7 +661,7 @@ export default function OrderManagementSalesPage() { description="수주 관리 및 생산지시 연동" icon={FileText} headerActions={ - diff --git a/src/app/[locale]/(protected)/sales/pricing-management/page.tsx b/src/app/[locale]/(protected)/sales/pricing-management/page.tsx index 84e98b8a..5b9ef67e 100644 --- a/src/app/[locale]/(protected)/sales/pricing-management/page.tsx +++ b/src/app/[locale]/(protected)/sales/pricing-management/page.tsx @@ -113,7 +113,7 @@ async function getApiHeaders(): Promise { return { 'Accept': 'application/json', 'Authorization': token ? `Bearer ${token}` : '', - 'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY || '', + 'X-API-KEY': process.env.API_KEY || '', }; } diff --git a/src/app/[locale]/(protected)/sales/quote-management/page.tsx b/src/app/[locale]/(protected)/sales/quote-management/page.tsx index 0e4b52c5..84bf0b90 100644 --- a/src/app/[locale]/(protected)/sales/quote-management/page.tsx +++ b/src/app/[locale]/(protected)/sales/quote-management/page.tsx @@ -659,7 +659,7 @@ export default function QuoteManagementPage() { description="견적서 작성 및 관리" icon={FileText} headerActions={ - diff --git a/src/components/accounting/BillManagement/BillManagementClient.tsx b/src/components/accounting/BillManagement/BillManagementClient.tsx index 08dcccce..9c9de327 100644 --- a/src/components/accounting/BillManagement/BillManagementClient.tsx +++ b/src/components/accounting/BillManagement/BillManagementClient.tsx @@ -307,18 +307,18 @@ export function BillManagementClient({ // ===== 헤더 액션 ===== const headerActions = ( - router.push('/ko/accounting/bills/new')}> - - 어음 등록 - - } - /> + <> + + + ); // ===== 거래처 목록 (필터용) ===== diff --git a/src/components/accounting/SalesManagement/index.tsx b/src/components/accounting/SalesManagement/index.tsx index 8ffd140c..5cb4cbf1 100644 --- a/src/components/accounting/SalesManagement/index.tsx +++ b/src/components/accounting/SalesManagement/index.tsx @@ -452,18 +452,18 @@ export function SalesManagement() { // ===== 헤더 액션 ===== const headerActions = ( - - - 매출 등록 - - } - /> + <> + + + ); // ===== 계정과목명 저장 핸들러 ===== diff --git a/src/components/accounting/VendorLedger/index.tsx b/src/components/accounting/VendorLedger/index.tsx index 97ae1039..c2e46eb2 100644 --- a/src/components/accounting/VendorLedger/index.tsx +++ b/src/components/accounting/VendorLedger/index.tsx @@ -276,22 +276,23 @@ export function VendorLedger() { // ===== 헤더 액션 ===== const headerActions = ( - - - 엑셀 다운로드 - - } - /> + <> + + + ); // ===== 테이블 하단 합계 행 ===== diff --git a/src/components/approval/ApprovalBox/index.tsx b/src/components/approval/ApprovalBox/index.tsx index 67b69b2e..580a45ba 100644 --- a/src/components/approval/ApprovalBox/index.tsx +++ b/src/components/approval/ApprovalBox/index.tsx @@ -463,26 +463,26 @@ export function ApprovalBox() { // ===== 헤더 액션 (DateRangeSelector + 승인/반려 버튼) ===== const headerActions = ( - 0 && ( - <> - - - - ) - } - /> + <> + + {selectedItems.size > 0 && ( +
+ + +
+ )} + ); // ===== 테이블 헤더 액션 (필터 + 정렬 셀렉트) ===== diff --git a/src/components/approval/DraftBox/index.tsx b/src/components/approval/DraftBox/index.tsx index 4b7d3e70..cf7f1821 100644 --- a/src/components/approval/DraftBox/index.tsx +++ b/src/components/approval/DraftBox/index.tsx @@ -443,32 +443,32 @@ export function DraftBox() { // ===== 헤더 액션 (DateRangeSelector + 버튼들) ===== const headerActions = ( - - {selectedItems.size > 0 && ( - <> - - - - )} - - - } - /> + <> + +
+ {selectedItems.size > 0 && ( + <> + + + + )} + +
+ ); // ===== 테이블 헤더 액션 (필터 + 정렬 셀렉트) ===== diff --git a/src/components/approval/ReferenceBox/index.tsx b/src/components/approval/ReferenceBox/index.tsx index 6b303c34..88cbc7d8 100644 --- a/src/components/approval/ReferenceBox/index.tsx +++ b/src/components/approval/ReferenceBox/index.tsx @@ -372,26 +372,26 @@ export function ReferenceBox() { // ===== 헤더 액션 (DateRangeSelector + 열람/미열람 버튼) ===== const headerActions = ( - 0 && ( - <> - - - - ) - } - /> + <> + + {selectedItems.size > 0 && ( +
+ + +
+ )} + ); // ===== 테이블 헤더 액션 (필터 + 정렬 셀렉트) ===== diff --git a/src/components/board/BoardList/index.tsx b/src/components/board/BoardList/index.tsx index f2a0ff7c..707fe36c 100644 --- a/src/components/board/BoardList/index.tsx +++ b/src/components/board/BoardList/index.tsx @@ -378,18 +378,18 @@ export function BoardList() { // ===== 헤더 액션 ===== const headerActions = ( - - - 게시글 등록 - - } - /> + <> + + + ); // ===== 테이블 헤더 액션 (필터 1개만: 게시판) ===== diff --git a/src/components/board/BoardManagement/index.tsx b/src/components/board/BoardManagement/index.tsx index 1a4d80c8..157fdb42 100644 --- a/src/components/board/BoardManagement/index.tsx +++ b/src/components/board/BoardManagement/index.tsx @@ -396,7 +396,7 @@ export function BoardManagement() { // 헤더 액션 const headerActions = ( - diff --git a/src/components/customer-center/InquiryManagement/InquiryList.tsx b/src/components/customer-center/InquiryManagement/InquiryList.tsx index ed196fc3..d9f6de28 100644 --- a/src/components/customer-center/InquiryManagement/InquiryList.tsx +++ b/src/components/customer-center/InquiryManagement/InquiryList.tsx @@ -254,18 +254,18 @@ export function InquiryList() { description="1:1 문의를 등록하고 답변을 확인합니다." icon={MessageSquare} headerActions={ -
+ <> - -
+ } searchValue={searchValue} onSearchChange={setSearchValue} diff --git a/src/components/hr/AttendanceManagement/index.tsx b/src/components/hr/AttendanceManagement/index.tsx index f136f0a8..f252e2ea 100644 --- a/src/components/hr/AttendanceManagement/index.tsx +++ b/src/components/hr/AttendanceManagement/index.tsx @@ -426,24 +426,24 @@ export function AttendanceManagement() { // 헤더 액션 (DateRangeSelector + 버튼들) const headerActions = ( - - - - - } - /> + <> + +
+ + +
+ ); // 테이블 헤더 액션 (필터 + 정렬 셀렉트) - 사원관리와 동일한 위치 diff --git a/src/components/hr/CardManagement/index.tsx b/src/components/hr/CardManagement/index.tsx index 5f09e754..110fdc8b 100644 --- a/src/components/hr/CardManagement/index.tsx +++ b/src/components/hr/CardManagement/index.tsx @@ -390,7 +390,7 @@ export function CardManagement() { // 헤더 액션 const headerActions = ( - diff --git a/src/components/hr/EmployeeManagement/index.tsx b/src/components/hr/EmployeeManagement/index.tsx index 421a11fa..24bc56a4 100644 --- a/src/components/hr/EmployeeManagement/index.tsx +++ b/src/components/hr/EmployeeManagement/index.tsx @@ -580,31 +580,31 @@ export function EmployeeManagement() { // 헤더 액션 (DateRangeSelector + 버튼들) const headerActions = ( - - - - - - } - /> + <> + +
+ + + +
+ ); // 테이블 헤더 액션 (필터/정렬 셀렉트박스) diff --git a/src/components/hr/VacationManagement/index.tsx b/src/components/hr/VacationManagement/index.tsx index 5cabc352..cd6bc527 100644 --- a/src/components/hr/VacationManagement/index.tsx +++ b/src/components/hr/VacationManagement/index.tsx @@ -501,51 +501,51 @@ export function VacationManagement() { // ===== 헤더 액션 (DateRangeSelector + 버튼들) ===== const headerActions = ( - - {/* 탭별 액션 버튼 */} - {mainTab === 'grant' && ( - + )} + + {mainTab === 'request' && ( + <> + {/* 버튼 순서: 승인 → 거절 → 휴가신청 (휴가신청 버튼 위치 고정) */} + {selectedItems.size > 0 && ( + <> + + + + )} + - )} + + )} - {mainTab === 'request' && ( - <> - {/* 버튼 순서: 승인 → 거절 → 휴가신청 (휴가신청 버튼 위치 고정) */} - {selectedItems.size > 0 && ( - <> - - - - )} - - - )} - - {/* 엑셀 다운로드 버튼 - 주석처리 */} - {/* */} - - } - /> + {/* 엑셀 다운로드 버튼 - 주석처리 */} + {/* */} + + ); // ===== 테이블 헤더 액션 (필터 + 정렬 셀렉트) - 사원관리와 동일한 위치 ===== diff --git a/src/components/pricing/PricingHistoryDialog.tsx b/src/components/pricing/PricingHistoryDialog.tsx index fd71b08d..4047402a 100644 --- a/src/components/pricing/PricingHistoryDialog.tsx +++ b/src/components/pricing/PricingHistoryDialog.tsx @@ -117,25 +117,25 @@ export function PricingHistoryDialog({
매입단가:
- {revision.previousData.purchasePrice?.toLocaleString() || '-'}원 + {revision.previousData?.purchasePrice?.toLocaleString() || '-'}원
가공비:
- {revision.previousData.processingCost?.toLocaleString() || '-'}원 + {revision.previousData?.processingCost?.toLocaleString() || '-'}원
판매단가:
- {revision.previousData.salesPrice?.toLocaleString() || '-'}원 + {revision.previousData?.salesPrice?.toLocaleString() || '-'}원
마진율:
- {revision.previousData.marginRate?.toFixed(1) || '-'}% + {revision.previousData?.marginRate?.toFixed(1) || '-'}%
diff --git a/src/components/pricing/PricingListClient.tsx b/src/components/pricing/PricingListClient.tsx index 88e2bc79..6b86cecb 100644 --- a/src/components/pricing/PricingListClient.tsx +++ b/src/components/pricing/PricingListClient.tsx @@ -403,7 +403,7 @@ export function PricingListClient({ // TODO: API 연동 시 품목 마스터 동기화 로직 구현 console.log('품목 마스터 동기화'); }} - className="gap-2" + className="ml-auto gap-2" > 품목 마스터 동기화 diff --git a/src/components/settings/AccountManagement/index.tsx b/src/components/settings/AccountManagement/index.tsx index 14d1aa1a..544c65b8 100644 --- a/src/components/settings/AccountManagement/index.tsx +++ b/src/components/settings/AccountManagement/index.tsx @@ -294,7 +294,7 @@ export function AccountManagement() { // ===== 헤더 액션 (카드관리와 동일한 패턴) ===== const headerActions = ( - diff --git a/src/components/settings/PermissionManagement/index.tsx b/src/components/settings/PermissionManagement/index.tsx index a87d3e39..6335f29b 100644 --- a/src/components/settings/PermissionManagement/index.tsx +++ b/src/components/settings/PermissionManagement/index.tsx @@ -411,7 +411,7 @@ export function PermissionManagement() { // ===== 헤더 액션 ===== const headerActions = ( -
+
{selectedItems.size > 0 && ( diff --git a/src/components/templates/IntegratedListTemplateV2.tsx b/src/components/templates/IntegratedListTemplateV2.tsx index 79728eb7..d8be1e2d 100644 --- a/src/components/templates/IntegratedListTemplateV2.tsx +++ b/src/components/templates/IntegratedListTemplateV2.tsx @@ -228,7 +228,7 @@ export function IntegratedListTemplateV2({ {/* 헤더 액션 (달력, 버튼 등) - 타이틀 아래 배치 */} {headerActions && ( -
+
{headerActions}
)}