feat(numbering-rule): 채번규칙 구분자 설정 기능 추가
- SeparatorType 타입 및 SEPARATOR_OPTIONS 상수 추가 - 구분자 선택 UI 추가 (없음, -, _, ., /, 직접입력) - 직접 입력 시 최대 2자 제한 - 새 규칙 생성 시 기본값 하이픈(-) - Select 빈 문자열 에러 해결 (value: "" -> "none")
This commit is contained in:
parent
de8b643277
commit
40c43bab16
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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: "" },
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue