DynamicItemForm 개선: - 품목코드 자동생성 기능 추가 - 조건부 표시 로직 개선 - 불필요한 컴포넌트 정리 (DynamicField, DynamicSection 등) - 타입 시스템 단순화 새로운 기능: - Sales 페이지 마이그레이션 (견적관리, 거래처관리) - 공통 컴포넌트 추가 (atoms, molecules, organisms, templates) 문서화: - 구현 문서 및 참조 문서 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
16 KiB
16 KiB
판매관리 페이지 마이그레이션 계획
작성일: 2025-12-02 소스:
sam-design/sam-design타겟:sam-react-prod(Next.js) 예상 소요 시간: 4~6시간
0. 예상 작업 시간
| Phase | 작업 내용 | 예상 시간 |
|---|---|---|
| Phase 1 | 공통 UI 컴포넌트 (~1,400줄) | 1~2시간 |
| Phase 2 | 거래처관리 (~500줄) | 30분~1시간 |
| Phase 3 | 견적관리 + 하위 컴포넌트 (~1,500줄+) | 2~3시간 |
| 총합 | ~3,400줄+ | 4~6시간 |
참고: 테스트/디버깅 시간 포함, 예상치 못한 이슈 발생 시 추가 소요 가능
1. 마이그레이션 대상 요약
| 페이지 | 파일 | 크기 | 분할 필요 | 템플릿 |
|---|---|---|---|---|
| 견적관리 | QuoteManagement.tsx |
1,001줄 | O (경계선) | IntegratedListTemplateV2 |
| 거래처관리 | CustomerAccountManagement.tsx |
425줄 | X | ListPageTemplate |
2. 견적관리 (QuoteManagement.tsx)
2.1 파일 정보
- 경로:
sam-design/src/components/QuoteManagement.tsx - 크기: 1,001줄
- 템플릿:
IntegratedListTemplateV2
2.2 컴포넌트 구조
QuoteManagement
├── IntegratedListTemplateV2 (목록 템플릿)
│ ├── PageHeader (제목: "견적 목록")
│ ├── StatCards (4개 통계 카드)
│ │ ├── 이번 달 견적 금액
│ │ ├── 진행중 견적 금액
│ │ ├── 이번 주 신규 견적
│ │ └── 이번 달 수주 전환율
│ ├── SearchFilter (검색바)
│ ├── TabChip 탭
│ │ ├── 전체
│ │ ├── 최초작성
│ │ ├── 수정중
│ │ ├── 최종확정
│ │ └── 수주전환
│ ├── DataTable (데스크톱 테이블)
│ └── ListMobileCard (모바일 카드)
├── QuoteManagement3Write (등록/수정 화면)
├── QuoteManagement3Detail (상세 화면)
├── QuoteDetailView (상세 화면 - 샘플용)
└── StandardDialog (산출내역서/삭제 확인)
2.3 주요 기능
- 목록 조회 (페이지네이션, 검색, 필터)
- 탭 기반 상태 필터링
- 체크박스 선택 + 일괄 삭제
- 모바일 인피니티 스크롤
- CRUD (등록/조회/수정/삭제)
- 산출내역서 다이얼로그
2.4 분할 제안
src/app/[locale]/(protected)/sales/quotes/
├── page.tsx # 목록 (라우팅 + 상태 관리)
├── components/
│ ├── QuoteList.tsx # 목록 컴포넌트
│ ├── QuoteTableRow.tsx # 테이블 행
│ └── QuoteMobileCard.tsx # 모바일 카드
├── create/
│ └── page.tsx # 견적 등록
├── [id]/
│ ├── page.tsx # 견적 상세
│ └── edit/
│ └── page.tsx # 견적 수정
2.5 의존성 컴포넌트
| 컴포넌트 | 경로 | 마이그레이션 필요 |
|---|---|---|
| IntegratedListTemplateV2 | templates/ | O |
| PageHeader | organisms/ | 이미 존재 |
| PageLayout | organisms/ | 이미 존재 |
| StatCards | organisms/ | O |
| SearchFilter | organisms/ | O |
| TabChip | atoms/ | O |
| ListMobileCard | organisms/ | O |
| DataTable | organisms/ | O |
| StandardDialog | molecules/ | O |
| QuoteManagement3Write | components/ | O (별도 분석 필요) |
| QuoteManagement3Detail | components/ | O (별도 분석 필요) |
3. 거래처관리 (CustomerAccountManagement.tsx)
3.1 파일 정보
- 경로:
sam-design/src/components/CustomerAccountManagement.tsx - 크기: 425줄
- 템플릿:
ListPageTemplate
3.2 컴포넌트 구조
CustomerAccountManagement
├── ListPageTemplate (목록 템플릿)
│ ├── PageHeader (제목: "매출처 목록")
│ ├── StatCards (3개 통계 카드)
│ │ ├── 전체 거래처
│ │ ├── 활성 거래처
│ │ └── 비활성 거래처
│ ├── SearchFilter (검색바)
│ ├── DataTable (데스크톱 테이블)
│ │ └── columns: 코드, 거래처명, 사업자번호, 대표자, 전화번호, 업태, 업종, 상태, 관리
│ └── MobileCard (모바일 카드)
└── Dialog (등록/수정 모달)
└── FormFields: 거래처명, 사업자번호, 대표자, 전화번호, 주소, 이메일, 업태, 업종
3.3 주요 기능
- 거래처 목록 조회 (검색)
- CRUD (등록/수정/삭제)
- 모달 기반 폼
3.4 Next.js 구조 제안
src/app/[locale]/(protected)/sales/customers/
├── page.tsx # 목록 + 모달 (425줄이라 단일 파일 가능)
└── components/
└── CustomerForm.tsx # 폼 분리 (선택)
3.5 의존성 컴포넌트
| 컴포넌트 | 경로 | 마이그레이션 필요 |
|---|---|---|
| ListPageTemplate | templates/ | O |
| PageHeader | organisms/ | 이미 존재 |
| PageLayout | organisms/ | 이미 존재 |
| StatCards | organisms/ | O |
| SearchFilter | organisms/ | O |
| DataTable | organisms/ | O |
| MobileCard | organisms/ | O |
| Dialog | ui/ | 이미 존재 |
4. 공통 테이블 UI 기준 (중요)
4.1 최종 기준: 견적관리 페이지 테이블
공통 테이블 UI는
QuoteManagement.tsx의 테이블 형태를 최종 기준으로 적용
거래처관리를 포함한 모든 목록 페이지는 견적관리 페이지의 테이블 UI를 따릅니다.
4.2 테이블 화면 구조
┌─────────────────────────────────────────────────────────────┐
│ [PageHeader] 견적 목록 [등록 버튼] │
├─────────────────────────────────────────────────────────────┤
│ [StatCards] 4개 통계 카드 (2x2 또는 4열) │
├─────────────────────────────────────────────────────────────┤
│ [SearchFilter] 검색바 + 추가 필터 │
├─────────────────────────────────────────────────────────────┤
│ [TabChip] 전체 | 최초작성 | 수정중 | 최종확정 | 수주전환 │
├───┬───────────────────────────────────────────────────┬─────┤
│ ☐ │ 번호 | 견적번호 | 접수일 | 상태 | ... | 비고 | 작업 │
├───┼───────────────────────────────────────────────────┼─────┤
│ ☐ │ 10 | Q2024-001| 2024-01 | 진행 | ... | - | [편집]│
│ ☐ │ 9 | Q2024-002| 2024-01 | 확정 | ... | - | [편집]│
├───┴───────────────────────────────────────────────────┴─────┤
│ [Pagination] 전체 100개 중 1-20개 표시 [이전] 1 2 3 [다음]│
└─────────────────────────────────────────────────────────────┘
4.3 반응형 구조
| 화면 크기 | 뷰 타입 | 특징 |
|---|---|---|
| 데스크톱 (1280px+) | 테이블 뷰 | 체크박스 + 전체 컬럼 + 페이지네이션 |
| 태블릿 (~1279px) | 카드 뷰 | 2~3열 그리드 + 인피니티 스크롤 |
| 모바일 (~767px) | 카드 뷰 | 1열 + 인피니티 스크롤 |
반응형 전환 기준:
xl:(1280px+) → 테이블 뷰md:(768px1279px) → 카드 그리드 (23열)- 기본 → 카드 단일 열
4.4 테이블 기능 목록
필수 기능
- 체크박스 선택: 개별 선택 + 전체 선택
- 일괄 삭제: 2개 이상 선택 시 삭제 버튼 표시
- 역순 번호: totalCount 기준 역순 (최신이 1번이 아닌 N번)
- 행 클릭: 상세 페이지로 이동
- 액션 버튼: 선택된 행에만 수정/삭제 버튼 표시
페이지네이션 (데스크톱)
- 페이지당 20개 표시
- 현재 페이지 표시 (1-20 / 100개)
- 이전/다음 버튼
- 페이지 번호 (현재 ±2 범위)
인피니티 스크롤 (모바일/태블릿)
- Intersection Observer 사용
- 20개씩 추가 로드
- Sentinel 요소로 트리거
4.5 적용 대상
| 페이지 | 적용 내용 |
|---|---|
| 견적관리 | 기준 페이지 (이미 적용됨) |
| 거래처관리 | 동일한 테이블 UI 적용 필요 |
| 향후 목록 페이지 | 모두 동일한 공통 테이블 UI 사용 |
4.6 공통 테이블 컴포넌트 구조
공통 테이블 UI
├── IntegratedListTemplateV2 (템플릿)
│ ├── PageHeader
│ ├── StatCards
│ ├── SearchFilter
│ ├── TabChip (선택적)
│ ├── DataTable (데스크톱)
│ │ ├── 체크박스 컬럼
│ │ ├── 데이터 컬럼들
│ │ ├── 액션 컬럼
│ │ └── 페이지네이션
│ └── ListMobileCard (모바일/태블릿)
│ ├── 체크박스
│ ├── 헤더 뱃지
│ ├── 정보 그리드
│ └── 액션 버튼 (선택 시)
5. 공통 UI 컴포넌트 마이그레이션
5.1 마이그레이션 필요 목록
| 컴포넌트 | 소스 경로 | 타겟 경로 | 크기 | 우선순위 |
|---|---|---|---|---|
| StatCards | organisms/StatCards.tsx | organisms/ | 53줄 | P1 |
| SearchFilter | organisms/SearchFilter.tsx | organisms/ | 54줄 | P1 |
| DataTable | organisms/DataTable.tsx | organisms/ | 313줄 | P1 |
| MobileCard | organisms/MobileCard.tsx | organisms/ | 104줄 | P1 |
| ListMobileCard | organisms/ListMobileCard.tsx | organisms/ | 169줄 | P1 |
| TabChip | atoms/TabChip.tsx | atoms/ | ~50줄 | P2 |
| ListPageTemplate | templates/ListPageTemplate.tsx | templates/ | 143줄 | P2 |
| IntegratedListTemplateV2 | templates/IntegratedListTemplateV2.tsx | templates/ | 491줄 | P2 |
| StandardDialog | molecules/StandardDialog.tsx | molecules/ | ~150줄 | P3 |
| InfoField | organisms/ListMobileCard.tsx | organisms/ | 8줄 | P1 |
5.2 Next.js 타겟 구조
src/components/
├── atoms/
│ └── TabChip.tsx # NEW
├── molecules/
│ └── StandardDialog.tsx # NEW
├── organisms/
│ ├── PageHeader.tsx # 기존
│ ├── PageLayout.tsx # 기존
│ ├── StatCards.tsx # NEW
│ ├── SearchFilter.tsx # NEW
│ ├── DataTable.tsx # NEW
│ ├── MobileCard.tsx # NEW
│ └── ListMobileCard.tsx # NEW
├── templates/
│ ├── ListPageTemplate.tsx # NEW
│ └── IntegratedListTemplateV2.tsx # NEW
└── ui/ # 기존 (변경 없음)
5.3 컴포넌트 상세
StatCards (53줄)
interface StatCardData {
label: string;
value: string | number;
icon?: LucideIcon;
iconColor?: string;
trend?: { value: string; isPositive: boolean };
}
- 2x2 또는 4열 그리드
- 아이콘 + 라벨 + 값 + 트렌드
SearchFilter (54줄)
interface SearchFilterProps {
searchValue: string;
onSearchChange: (value: string) => void;
searchPlaceholder?: string;
filterButton?: boolean;
onFilterClick?: () => void;
extraActions?: ReactNode;
}
- 검색 아이콘 + Input
- 모바일 플레이스홀더 변경
DataTable (313줄)
interface Column<T> {
key: keyof T | string;
label: string;
type?: CellType; // text, number, currency, date, status, badge, actions, custom
render?: (value: any, row: T, index?: number) => ReactNode;
}
- 타입별 셀 렌더링
- 페이지네이션 지원
- 로딩/빈 상태 처리
ListMobileCard (169줄)
interface ListMobileCardProps {
id: string;
isSelected: boolean;
onToggleSelection: () => void;
onCardClick?: () => void;
headerBadges?: ReactNode;
title: string;
statusBadge?: ReactNode;
infoGrid: ReactNode;
actions?: ReactNode;
}
- 체크박스 포함
- 선택 시 스타일 변경
- InfoField 하위 컴포넌트
6. 작업 순서 (권장)
Phase 1: 공통 UI 컴포넌트 (선행) ✅ 완료
- StatCards 마이그레이션
- SearchFilter 마이그레이션
- DataTable 마이그레이션
- MobileCard 마이그레이션
- ListMobileCard + InfoField 마이그레이션
- TabChip 마이그레이션
- ListPageTemplate 마이그레이션
- IntegratedListTemplateV2 마이그레이션
- BadgeSm 마이그레이션 (추가)
- StatusBadge 마이그레이션 (추가)
- IconWithBadge 마이그레이션 (추가)
- TableActions 마이그레이션 (추가)
- EmptyState 마이그레이션 (추가)
- ScreenVersionHistory 마이그레이션 (추가)
- StandardDialog 마이그레이션 (추가)
- formatAmount 유틸리티 마이그레이션 (추가)
Phase 2: 거래처관리 (간단한 것 먼저) ✅ 완료
- 라우트 생성:
/sales/customers - CustomerAccountManagement 마이그레이션
- 테스트 및 검증 (빌드 통과)
Phase 3: 견적관리 (복잡한 것) ✅ 완료
- 라우트 생성:
/sales/quotes - QuoteManagement 목록 페이지 마이그레이션
- Separator 컴포넌트 추가 (의존성)
- 테스트 및 검증 (빌드 통과)
- QuoteManagement3Write 분석 및 마이그레이션 (향후 작업)
- QuoteManagement3Detail 분석 및 마이그레이션 (향후 작업)
7. 주의사항
7.1 React → Next.js 마이그레이션 체크리스트
'use client'디렉티브 추가 (상태/이벤트 사용 시)localStorage접근 시typeof window !== 'undefined'체크useRouter→next/navigation으로 변경- 이미지 →
next/image사용 - 링크 →
next/link사용
6.2 스타일 호환성
- sam-design: Tailwind CSS + shadcn/ui
- sam-react-prod: Tailwind CSS + shadcn/ui (동일)
- cn() 유틸리티 경로 확인 필요
6.3 의존성 확인
# sam-design에서 사용하는 라이브러리
- lucide-react
- sonner (toast)
- react-hook-form (폼)
- zod (validation)
7. 예상 작업량
| 항목 | 예상 크기 |
|---|---|
| 공통 UI 컴포넌트 | ~1,400줄 |
| 거래처관리 | ~500줄 |
| 견적관리 (분할 포함) | ~1,500줄+ |
| 총합 | ~3,400줄+ |
8. 관련 파일 참조
sam-design 소스 파일
sam-design/sam-design/src/components/
├── QuoteManagement.tsx
├── CustomerAccountManagement.tsx
├── atoms/
│ └── TabChip.tsx
├── molecules/
│ └── StandardDialog.tsx
├── organisms/
│ ├── StatCards.tsx
│ ├── SearchFilter.tsx
│ ├── DataTable.tsx
│ ├── MobileCard.tsx
│ └── ListMobileCard.tsx
└── templates/
├── ListPageTemplate.tsx
└── IntegratedListTemplateV2.tsx
Next.js 타겟 경로
sam-react-prod/src/
├── app/[locale]/(protected)/sales/
│ ├── quotes/
│ │ └── page.tsx
│ └── customers/
│ └── page.tsx
└── components/
├── atoms/
├── molecules/
├── organisms/
└── templates/