feat(numbering-rule): 채번규칙 구분자 설정 기능 추가

- SeparatorType 타입 및 SEPARATOR_OPTIONS 상수 추가
- 구분자 선택 UI 추가 (없음, -, _, ., /, 직접입력)
- 직접 입력 시 최대 2자 제한
- 새 규칙 생성 시 기본값 하이픈(-)
- Select 빈 문자열 에러 해결 (value: "" -> "none")
This commit is contained in:
SeongHyun Kim 2025-12-04 13:28:13 +09:00
parent de8b643277
commit 40c43bab16
2 changed files with 108 additions and 2 deletions

View File

@ -8,7 +8,7 @@ import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Plus, Save, Edit2, Trash2 } from "lucide-react";
import { toast } from "sonner";
import { NumberingRuleConfig, NumberingRulePart } from "@/types/numbering-rule";
import { NumberingRuleConfig, NumberingRulePart, SEPARATOR_OPTIONS, SeparatorType } from "@/types/numbering-rule";
import { NumberingRuleCard } from "./NumberingRuleCard";
import { NumberingRulePreview } from "./NumberingRulePreview";
import {
@ -48,6 +48,10 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
const [editingLeftTitle, setEditingLeftTitle] = useState(false);
const [editingRightTitle, setEditingRightTitle] = useState(false);
// 구분자 관련 상태
const [separatorType, setSeparatorType] = useState<SeparatorType>("-");
const [customSeparator, setCustomSeparator] = useState("");
useEffect(() => {
loadRules();
}, []);
@ -87,6 +91,50 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
}
}, [currentRule, onChange]);
// currentRule이 변경될 때 구분자 상태 동기화
useEffect(() => {
if (currentRule) {
const sep = currentRule.separator ?? "-";
// 빈 문자열이면 "none"
if (sep === "") {
setSeparatorType("none");
setCustomSeparator("");
return;
}
// 미리 정의된 구분자인지 확인 (none, custom 제외)
const predefinedOption = SEPARATOR_OPTIONS.find(
opt => opt.value !== "custom" && opt.value !== "none" && opt.displayValue === sep
);
if (predefinedOption) {
setSeparatorType(predefinedOption.value);
setCustomSeparator("");
} else {
// 직접 입력된 구분자
setSeparatorType("custom");
setCustomSeparator(sep);
}
}
}, [currentRule?.ruleId]); // ruleId가 변경될 때만 실행 (규칙 선택/생성 시)
// 구분자 변경 핸들러
const handleSeparatorChange = useCallback((type: SeparatorType) => {
setSeparatorType(type);
if (type !== "custom") {
const option = SEPARATOR_OPTIONS.find(opt => opt.value === type);
const newSeparator = option?.displayValue ?? "";
setCurrentRule((prev) => prev ? { ...prev, separator: newSeparator } : null);
setCustomSeparator("");
}
}, []);
// 직접 입력 구분자 변경 핸들러
const handleCustomSeparatorChange = useCallback((value: string) => {
// 최대 2자 제한
const trimmedValue = value.slice(0, 2);
setCustomSeparator(trimmedValue);
setCurrentRule((prev) => prev ? { ...prev, separator: trimmedValue } : null);
}, []);
const handleAddPart = useCallback(() => {
if (!currentRule) return;
@ -372,7 +420,44 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
</div>
</div>
{/* 두 번째 줄: 자동 감지된 테이블 정보 표시 */}
{/* 두 번째 줄: 구분자 설정 */}
<div className="flex items-end gap-3">
<div className="w-48 space-y-2">
<Label className="text-sm font-medium"></Label>
<Select
value={separatorType}
onValueChange={(value) => handleSeparatorChange(value as SeparatorType)}
>
<SelectTrigger className="h-9">
<SelectValue placeholder="구분자 선택" />
</SelectTrigger>
<SelectContent>
{SEPARATOR_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{separatorType === "custom" && (
<div className="w-32 space-y-2">
<Label className="text-sm font-medium"> </Label>
<Input
value={customSeparator}
onChange={(e) => handleCustomSeparatorChange(e.target.value)}
className="h-9"
placeholder="최대 2자"
maxLength={2}
/>
</div>
)}
<p className="text-muted-foreground pb-2 text-xs">
</p>
</div>
{/* 세 번째 줄: 자동 감지된 테이블 정보 표시 */}
{currentTableName && (
<div className="space-y-2">
<Label className="text-sm font-medium"> </Label>

View File

@ -123,3 +123,24 @@ export const RESET_PERIOD_OPTIONS: Array<{
{ value: "monthly", label: "월별 초기화" },
{ value: "yearly", label: "연별 초기화" },
];
/**
*
* -
* - "none"
* - "custom" ( 2)
*/
export type SeparatorType = "none" | "-" | "_" | "." | "/" | "custom";
export const SEPARATOR_OPTIONS: Array<{
value: SeparatorType;
label: string;
displayValue: string;
}> = [
{ value: "none", label: "없음", displayValue: "" },
{ value: "-", label: "하이픈 (-)", displayValue: "-" },
{ value: "_", label: "언더스코어 (_)", displayValue: "_" },
{ value: ".", label: "점 (.)", displayValue: "." },
{ value: "/", label: "슬래시 (/)", displayValue: "/" },
{ value: "custom", label: "직접입력", displayValue: "" },
];