From 634f0cae18083624cd3cd634091acbbe7e4e0471 Mon Sep 17 00:00:00 2001 From: syc0123 Date: Wed, 11 Mar 2026 14:44:34 +0900 Subject: [PATCH] docs: Add documentation for category tree modal updates with continuous registration mode - Introduced new documents detailing the modifications made to the category tree modal for continuous registration mode. - Updated the functionality to allow the modal to close after saving or remain open based on user preference via a checkbox. - Enhanced the user experience by aligning the modal behavior with existing patterns in the project. - Included a checklist to track implementation progress and ensure thorough testing. These changes aim to improve the usability and consistency of the category management feature in the application. --- .../CCA[계획]-카테고리-연속등록모드.md | 199 ++++++++++++++++++ .../CCA[맥락]-카테고리-연속등록모드.md | 84 ++++++++ .../CCA[체크]-카테고리-연속등록모드.md | 52 +++++ .../CategoryValueManagerTree.tsx | 39 +++- 4 files changed, 363 insertions(+), 11 deletions(-) create mode 100644 docs/ycshin-node/CCA[계획]-카테고리-연속등록모드.md create mode 100644 docs/ycshin-node/CCA[맥락]-카테고리-연속등록모드.md create mode 100644 docs/ycshin-node/CCA[체크]-카테고리-연속등록모드.md diff --git a/docs/ycshin-node/CCA[계획]-카테고리-연속등록모드.md b/docs/ycshin-node/CCA[계획]-카테고리-연속등록모드.md new file mode 100644 index 00000000..964c389f --- /dev/null +++ b/docs/ycshin-node/CCA[계획]-카테고리-연속등록모드.md @@ -0,0 +1,199 @@ +# [계획서] 카테고리 트리 대분류 추가 모달 - 연속 등록 모드 수정 + +> 관련 문서: [맥락노트](./CCA[맥락]-카테고리-연속등록모드.md) | [체크리스트](./CCA[체크]-카테고리-연속등록모드.md) + +## 개요 + +기준정보 - 옵션설정 화면에서 트리 구조 카테고리(예: 품목정보 > 재고단위)의 "대분류 추가" 모달이 저장 후 닫히지 않는 버그를 수정합니다. +평면 목록용 추가 모달(`CategoryValueAddDialog.tsx`)과 동일한 연속 입력 패턴을 적용합니다. + +--- + +## 현재 동작 + +- 대분류 추가 모달에서 값 입력 후 "추가" 클릭 시 **값은 정상 저장됨** +- 저장 후 **모달이 닫히지 않고** 폼만 초기화됨 (항상 연속 입력 상태) +- "연속 입력" 체크박스 UI가 **없음** → 사용자가 모드를 끌 수 없음 +- 모달을 닫으려면 "닫기" 버튼 또는 외부 클릭을 해야 함 + +### 현재 코드 (CategoryValueManagerTree.tsx - handleAdd, 512~530행) + +```tsx +if (response.success) { + toast.success("카테고리가 추가되었습니다"); + // 폼 초기화 (모달은 닫지 않고 연속 입력) + setFormData((prev) => ({ + ...prev, + valueCode: "", + valueLabel: "", + description: "", + color: "", + })); + setTimeout(() => addNameRef.current?.focus(), 50); + await loadTree(true); + if (parentValue) { + setExpandedNodes((prev) => new Set([...prev, parentValue.valueId])); + } +} +``` + +### 현재 DialogFooter (809~821행) + +```tsx + + + + +``` + +--- + +## 변경 후 동작 + +### 1. 기본 동작: 저장 후 모달 닫힘 + +- "추가" 클릭 → 저장 성공 → 모달 닫힘 + 트리 새로고침 +- `CategoryValueAddDialog.tsx`(평면 목록 추가 모달)와 동일한 기본 동작 + +### 2. 연속 입력 체크박스 추가 + +- DialogFooter 좌측에 "연속 입력" 체크박스 표시 +- 기본값: 체크 해제 (OFF) +- 체크 시: 저장 후 폼만 초기화, 모달 유지, 이름 필드에 포커스 +- 체크 해제 시: 저장 후 모달 닫힘 + +--- + +## 시각적 예시 + +| 상태 | 연속 입력 체크 | 추가 버튼 클릭 후 | +|------|---------------|-----------------| +| 기본 (체크 해제) | [ ] 연속 입력 | 저장 → 모달 닫힘 → 트리 갱신 | +| 연속 모드 (체크) | [x] 연속 입력 | 저장 → 폼 초기화 → 모달 유지 → 이름 필드 포커스 | + +### 모달 하단 레이아웃 (ScreenModal.tsx 패턴) + +``` +┌─────────────────────────────────────────┐ +│ [닫기] [추가] │ ← DialogFooter (버튼만) +├─────────────────────────────────────────┤ +│ [x] 저장 후 계속 입력 (연속 등록 모드) │ ← border-t 구분선 아래 별도 영역 +└─────────────────────────────────────────┘ +``` + +--- + +## 아키텍처 + +```mermaid +flowchart TD + A["사용자: '추가' 클릭"] --> B["handleAdd()"] + B --> C{"API 호출 성공?"} + C -- 실패 --> D["toast.error → 모달 유지"] + C -- 성공 --> E["toast.success + loadTree"] + E --> F{"continuousAdd?"} + F -- true --> G["폼 초기화 + 이름 필드 포커스\n모달 유지"] + F -- false --> H["폼 초기화 + 모달 닫힘"] +``` + +--- + +## 변경 대상 파일 + +| 파일 | 역할 | 변경 내용 | +|------|------|----------| +| `frontend/components/table-category/CategoryValueManagerTree.tsx` | 트리형 카테고리 값 관리 | 상태 추가, handleAdd 분기, DialogFooter UI | + +- **변경 규모**: 약 20줄 내외 소규모 변경 +- **참고 파일**: `frontend/components/table-category/CategoryValueAddDialog.tsx` (동일 패턴) + +--- + +## 코드 설계 + +### 1. 상태 추가 (286행 근처, 모달 상태 선언부) + +```tsx +const [continuousAdd, setContinuousAdd] = useState(false); +``` + +### 2. handleAdd 성공 분기 수정 (512~530행 대체) + +```tsx +if (response.success) { + toast.success("카테고리가 추가되었습니다"); + await loadTree(true); + if (parentValue) { + setExpandedNodes((prev) => new Set([...prev, parentValue.valueId])); + } + + if (continuousAdd) { + setFormData((prev) => ({ + ...prev, + valueCode: "", + valueLabel: "", + description: "", + color: "", + })); + setTimeout(() => addNameRef.current?.focus(), 50); + } else { + setFormData({ valueCode: "", valueLabel: "", description: "", color: "", isActive: true }); + setIsAddModalOpen(false); + } +} +``` + +### 3. DialogFooter + 연속 등록 체크박스 수정 (809~821행 대체) + +DialogFooter는 버튼만 유지하고, 그 아래에 `border-t` 구분선과 체크박스를 별도 영역으로 배치합니다. +`ScreenModal.tsx` (1287~1303행) 패턴 그대로입니다. + +```tsx + + + + + +{/* 연속 등록 모드 체크박스 - ScreenModal.tsx 패턴 */} +
+
+ setContinuousAdd(checked as boolean)} + /> + +
+
+``` + +--- + +## 예상 문제 및 대응 + +`CategoryValueAddDialog.tsx`와 동일한 패턴이므로 별도 예상 문제 없음. + +--- + +## 설계 원칙 + +- `CategoryValueAddDialog.tsx`(같은 폴더, 같은 목적)의 패턴을 그대로 따름 +- 기존 수정/삭제 모달 동작은 변경하지 않음 +- 하위 추가(중분류/소분류) 모달도 동일한 `handleAdd`를 사용하므로 자동 적용 +- `Checkbox` import는 이미 존재 (24행)하므로 추가 import 불필요 +- `Label` import는 이미 존재 (53행)하므로 추가 import 불필요 +- 체크박스 위치/라벨/className 모두 `ScreenModal.tsx` (1287~1303행)과 동일 diff --git a/docs/ycshin-node/CCA[맥락]-카테고리-연속등록모드.md b/docs/ycshin-node/CCA[맥락]-카테고리-연속등록모드.md new file mode 100644 index 00000000..1b5cb92e --- /dev/null +++ b/docs/ycshin-node/CCA[맥락]-카테고리-연속등록모드.md @@ -0,0 +1,84 @@ +# [맥락노트] 카테고리 트리 대분류 추가 모달 - 연속 등록 모드 수정 + +> 관련 문서: [계획서](./CCA[계획]-카테고리-연속등록모드.md) | [체크리스트](./CCA[체크]-카테고리-연속등록모드.md) + +--- + +## 왜 이 작업을 하는가 + +- 기준정보 - 옵션설정에서 트리 구조 카테고리(품목정보 > 재고단위 등)의 "대분류 추가" 모달이 저장 후 닫히지 않음 +- 연속 등록 모드가 하드코딩되어 항상 ON 상태이고, 끌 수 있는 UI가 없음 +- 같은 폴더의 평면 목록 모달(`CategoryValueAddDialog.tsx`)은 이미 올바르게 구현되어 있음 +- 동일 패턴을 적용하여 일관성 확보 + +--- + +## 핵심 결정 사항과 근거 + +### 1. 기본값: 연속 등록 OFF (모달 닫힘) + +- **결정**: `continuousAdd` 초기값을 `false`로 설정 +- **근거**: 대부분의 사용자는 한 건 추가 후 결과를 확인하려 함. 연속 입력은 선택적 기능 + +### 2. 체크박스 위치: DialogFooter 아래, border-t 구분선 별도 영역 + +- **결정**: `ScreenModal.tsx` (1287~1303행) 패턴 그대로 적용 +- **근거**: "기준정보 - 부서관리" 추가 모달과 동일한 디자인. 프로젝트 관행 준수 +- **대안 검토**: `CategoryValueAddDialog.tsx`는 DialogFooter 안에 체크박스 배치 → 부서 모달과 다른 디자인이므로 기각 + +### 3. 라벨: "저장 후 계속 입력 (연속 등록 모드)" + +- **결정**: `ScreenModal.tsx`와 동일한 라벨 텍스트 사용 +- **근거**: 부서 추가 모달과 동일한 문구로 사용자 혼란 방지 + +### 4. localStorage 미사용 + +- **결정**: 컴포넌트 state만 사용, localStorage 영속화 안 함 +- **근거**: `CategoryValueAddDialog.tsx`(같은 폴더 형제 컴포넌트)가 localStorage를 쓰지 않음. `ScreenModal.tsx`는 사용하지만 동적 화면 모달 전용 기능이므로 범위가 다름 + +### 5. 수정 대상: handleAdd 함수만 + +- **결정**: 저장 성공 분기에서만 `continuousAdd` 체크 +- **근거**: 실패 시에는 원래대로 모달 유지 + 에러 표시. 분기가 필요한 건 성공 시뿐 + +--- + +## 관련 파일 위치 + +| 구분 | 파일 경로 | 설명 | +|------|----------|------| +| 수정 대상 | `frontend/components/table-category/CategoryValueManagerTree.tsx` | 트리형 카테고리 값 관리 (대분류/중분류/소분류) | +| 참고 패턴 (로직) | `frontend/components/table-category/CategoryValueAddDialog.tsx` | 평면 목록 추가 모달 - continuousAdd 분기 로직 | +| 참고 패턴 (UI) | `frontend/components/common/ScreenModal.tsx` | 동적 화면 모달 - 체크박스 위치/라벨/스타일 | + +--- + +## 기술 참고 + +### 현재 handleAdd 흐름 + +``` +handleAdd() → API 호출 → 성공 시: + 1. toast.success + 2. 폼 초기화 (모달 유지 - 하드코딩) + 3. addNameRef 포커스 + 4. loadTree(true) - 펼침 상태 유지 + 5. parentValue 있으면 해당 노드 펼침 +``` + +### 변경 후 handleAdd 흐름 + +``` +handleAdd() → API 호출 → 성공 시: + 1. toast.success + 2. loadTree(true) + parentValue 펼침 + 3. continuousAdd 체크: + - true: 폼 초기화 + addNameRef 포커스 (모달 유지) + - false: 폼 초기화 + setIsAddModalOpen(false) (모달 닫힘) +``` + +### import 현황 + +- `Checkbox`: 24행에서 이미 import (`@/components/ui/checkbox`) +- `Label`: 53행에서 이미 import (`@/components/ui/label`) +- 추가 import 불필요 diff --git a/docs/ycshin-node/CCA[체크]-카테고리-연속등록모드.md b/docs/ycshin-node/CCA[체크]-카테고리-연속등록모드.md new file mode 100644 index 00000000..f794e0ff --- /dev/null +++ b/docs/ycshin-node/CCA[체크]-카테고리-연속등록모드.md @@ -0,0 +1,52 @@ +# [체크리스트] 카테고리 트리 대분류 추가 모달 - 연속 등록 모드 수정 + +> 관련 문서: [계획서](./CCA[계획]-카테고리-연속등록모드.md) | [맥락노트](./CCA[맥락]-카테고리-연속등록모드.md) + +--- + +## 공정 상태 + +- 전체 진행률: **100%** (구현 완료) +- 현재 단계: 완료 + +--- + +## 구현 체크리스트 + +### 1단계: 상태 추가 + +- [x] `CategoryValueManagerTree.tsx` 모달 상태 선언부(286행 근처)에 `continuousAdd` 상태 추가 + +### 2단계: handleAdd 분기 수정 + +- [x] `handleAdd` 성공 분기(512~530행)에서 `continuousAdd` 체크 분기 추가 +- [x] `continuousAdd === true`: 폼 초기화 + addNameRef 포커스 (모달 유지) +- [x] `continuousAdd === false`: 폼 초기화 + `setIsAddModalOpen(false)` (모달 닫힘) + +### 3단계: DialogFooter UI 수정 + +- [x] DialogFooter(809~821행)는 버튼만 유지 +- [x] DialogFooter 아래에 `border-t px-4 py-3` 영역 추가 +- [x] "저장 후 계속 입력 (연속 등록 모드)" 체크박스 배치 +- [x] ScreenModal.tsx (1287~1303행) 패턴과 동일한 className/라벨 사용 + +### 4단계: 검증 + +- [ ] 대분류 추가: 체크 해제 상태에서 추가 → 모달 닫힘 확인 +- [ ] 대분류 추가: 체크 상태에서 추가 → 모달 유지 + 폼 초기화 + 포커스 확인 +- [ ] 하위 추가(중분류/소분류): 동일하게 동작하는지 확인 +- [ ] 수정/삭제 모달: 기존 동작 변화 없음 확인 + +### 5단계: 정리 + +- [x] 린트 에러 없음 확인 +- [x] 이 체크리스트 완료 표시 업데이트 + +--- + +## 변경 이력 + +| 날짜 | 내용 | +|------|------| +| 2026-03-11 | 계획서, 맥락노트, 체크리스트 작성 완료 | +| 2026-03-11 | 구현 완료 (1~3단계, 5단계 정리). 4단계 검증은 수동 테스트 필요 | diff --git a/frontend/components/table-category/CategoryValueManagerTree.tsx b/frontend/components/table-category/CategoryValueManagerTree.tsx index 88ecfb49..f6f7ff8a 100644 --- a/frontend/components/table-category/CategoryValueManagerTree.tsx +++ b/frontend/components/table-category/CategoryValueManagerTree.tsx @@ -288,6 +288,7 @@ export const CategoryValueManagerTree: React.FC = const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false); const [parentValue, setParentValue] = useState(null); + const [continuousAdd, setContinuousAdd] = useState(false); const [editingValue, setEditingValue] = useState(null); const [deletingValue, setDeletingValue] = useState(null); @@ -512,21 +513,24 @@ export const CategoryValueManagerTree: React.FC = const response = await createCategoryValue(input); if (response.success) { toast.success("카테고리가 추가되었습니다"); - // 폼 초기화 (모달은 닫지 않고 연속 입력) - setFormData((prev) => ({ - ...prev, - valueCode: "", - valueLabel: "", - description: "", - color: "", - })); - setTimeout(() => addNameRef.current?.focus(), 50); - // 기존 펼침 상태 유지하면서 데이터 새로고침 await loadTree(true); - // 부모 노드만 펼치기 (하위 추가 시) if (parentValue) { setExpandedNodes((prev) => new Set([...prev, parentValue.valueId])); } + + if (continuousAdd) { + setFormData((prev) => ({ + ...prev, + valueCode: "", + valueLabel: "", + description: "", + color: "", + })); + setTimeout(() => addNameRef.current?.focus(), 50); + } else { + setFormData({ valueCode: "", valueLabel: "", description: "", color: "", isActive: true }); + setIsAddModalOpen(false); + } } else { toast.error(response.error || "추가 실패"); } @@ -818,6 +822,19 @@ export const CategoryValueManagerTree: React.FC = 추가 + +
+
+ setContinuousAdd(checked as boolean)} + /> + +
+