ERP-node/docs/ycshin-node/CCA[계획]-카테고리-연속등록모드.md

200 lines
6.4 KiB
Markdown
Raw Normal View History

# [계획서] 카테고리 트리 대분류 추가 모달 - 연속 등록 모드 수정
> 관련 문서: [맥락노트](./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
<DialogFooter className="gap-2 sm:gap-0">
<Button variant="outline" onClick={() => setIsAddModalOpen(false)} ...>
닫기
</Button>
<Button onClick={handleAdd} ...>
추가
</Button>
</DialogFooter>
```
---
## 변경 후 동작
### 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
<DialogFooter className="gap-2 sm:gap-0">
<Button
variant="outline"
onClick={() => setIsAddModalOpen(false)}
className="h-9 flex-1 text-sm sm:flex-none"
>
닫기
</Button>
<Button onClick={handleAdd} className="h-9 flex-1 text-sm sm:flex-none">
추가
</Button>
</DialogFooter>
{/* 연속 등록 모드 체크박스 - ScreenModal.tsx 패턴 */}
<div className="border-t px-4 py-3">
<div className="flex items-center gap-2">
<Checkbox
id="tree-continuous-add"
checked={continuousAdd}
onCheckedChange={(checked) => setContinuousAdd(checked as boolean)}
/>
<Label htmlFor="tree-continuous-add" className="cursor-pointer text-sm font-normal select-none">
저장 후 계속 입력 (연속 등록 모드)
</Label>
</div>
</div>
```
---
## 예상 문제 및 대응
`CategoryValueAddDialog.tsx`와 동일한 패턴이므로 별도 예상 문제 없음.
---
## 설계 원칙
- `CategoryValueAddDialog.tsx`(같은 폴더, 같은 목적)의 패턴을 그대로 따름
- 기존 수정/삭제 모달 동작은 변경하지 않음
- 하위 추가(중분류/소분류) 모달도 동일한 `handleAdd`를 사용하므로 자동 적용
- `Checkbox` import는 이미 존재 (24행)하므로 추가 import 불필요
- `Label` import는 이미 존재 (53행)하므로 추가 import 불필요
- 체크박스 위치/라벨/className 모두 `ScreenModal.tsx` (1287~1303행)과 동일