ERP-node/frontend/lib/registry/components/text-input/TextInputConfigPanel.tsx

298 lines
12 KiB
TypeScript
Raw Normal View History

2025-09-11 18:38:28 +09:00
"use client";
2025-11-04 17:35:02 +09:00
import React, { useState, useEffect } from "react";
2025-09-11 18:38:28 +09:00
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { TextInputConfig } from "./types";
import { AutoGenerationType, AutoGenerationConfig } from "@/types/screen";
import { AutoGenerationUtils } from "@/lib/utils/autoGeneration";
import { getAvailableNumberingRules, getAvailableNumberingRulesForScreen } from "@/lib/api/numberingRule";
2025-11-04 17:35:02 +09:00
import { NumberingRuleConfig } from "@/types/numbering-rule";
2025-09-11 18:38:28 +09:00
export interface TextInputConfigPanelProps {
config: TextInputConfig;
onChange: (config: Partial<TextInputConfig>) => void;
screenTableName?: string; // 🆕 현재 화면의 테이블명
2025-09-11 18:38:28 +09:00
}
/**
* TextInput
* UI
*/
export const TextInputConfigPanel: React.FC<TextInputConfigPanelProps> = ({ config, onChange, screenTableName }) => {
2025-11-04 17:35:02 +09:00
// 채번 규칙 목록 상태
const [numberingRules, setNumberingRules] = useState<NumberingRuleConfig[]>([]);
const [loadingRules, setLoadingRules] = useState(false);
// 채번 규칙 목록 로드
useEffect(() => {
const loadRules = async () => {
setLoadingRules(true);
try {
let response;
// 🆕 테이블명이 있으면 테이블 기반 필터링, 없으면 전체 조회
if (screenTableName) {
console.log("🔍 TextInputConfigPanel: 테이블 기반 채번 규칙 로드", { screenTableName });
response = await getAvailableNumberingRulesForScreen(screenTableName);
} else {
console.log("🔍 TextInputConfigPanel: 전체 채번 규칙 로드 (테이블명 없음)");
response = await getAvailableNumberingRules();
}
2025-11-04 17:35:02 +09:00
if (response.success && response.data) {
setNumberingRules(response.data);
console.log("✅ 채번 규칙 로드 완료:", response.data.length, "개");
2025-11-04 17:35:02 +09:00
}
} catch (error) {
console.error("채번 규칙 목록 로드 실패:", error);
} finally {
setLoadingRules(false);
}
};
// autoGeneration.type이 numbering_rule일 때만 로드
if (config.autoGeneration?.type === "numbering_rule") {
loadRules();
}
}, [config.autoGeneration?.type, screenTableName]);
2025-11-04 17:35:02 +09:00
2025-09-11 18:38:28 +09:00
const handleChange = (key: keyof TextInputConfig, value: any) => {
onChange({ [key]: value });
};
return (
<div className="space-y-4">
<div className="text-sm font-medium">text-input </div>
2025-09-11 18:38:28 +09:00
{/* 텍스트 관련 설정 */}
2025-09-11 18:38:28 +09:00
<div className="space-y-2">
<Label htmlFor="placeholder"></Label>
<Input
id="placeholder"
value={config.placeholder || ""}
onChange={(e) => handleChange("placeholder", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="maxLength"> </Label>
<Input
id="maxLength"
type="number"
value={config.maxLength || ""}
onChange={(e) => handleChange("maxLength", parseInt(e.target.value) || undefined)}
/>
</div>
{/* 구분선 */}
<div className="border-t pt-4">
<div className="mb-3 text-sm font-medium"> </div>
{/* 숨김 기능 */}
<div className="space-y-2">
2025-10-23 15:06:00 +09:00
<Label htmlFor="hidden"></Label>
<Checkbox
id="hidden"
checked={config.hidden || false}
onCheckedChange={(checked) => handleChange("hidden", checked)}
/>
</div>
{/* 자동생성 기능 */}
<div className="space-y-2">
<Label htmlFor="autoGeneration"> </Label>
<Checkbox
id="autoGeneration"
checked={config.autoGeneration?.enabled || false}
onCheckedChange={(checked) => {
const currentConfig = config.autoGeneration || { type: "none", enabled: false };
handleChange("autoGeneration", {
...currentConfig,
enabled: checked as boolean,
});
}}
/>
</div>
{/* 자동생성 타입 선택 */}
{config.autoGeneration?.enabled && (
<div className="space-y-2">
<Label htmlFor="autoGenerationType"> </Label>
<Select
value={config.autoGeneration?.type || "none"}
onValueChange={(value: AutoGenerationType) => {
const currentConfig = config.autoGeneration || { type: "none", enabled: false };
handleChange("autoGeneration", {
...currentConfig,
type: value,
});
}}
>
<SelectTrigger>
<SelectValue placeholder="자동생성 타입 선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="none"> </SelectItem>
<SelectItem value="uuid">UUID </SelectItem>
<SelectItem value="current_user"> ID</SelectItem>
<SelectItem value="current_time"> </SelectItem>
<SelectItem value="sequence"> </SelectItem>
2025-11-04 17:35:02 +09:00
<SelectItem value="numbering_rule"> </SelectItem>
<SelectItem value="random_string"> </SelectItem>
<SelectItem value="random_number"> </SelectItem>
<SelectItem value="company_code"> </SelectItem>
<SelectItem value="department"> </SelectItem>
</SelectContent>
</Select>
{/* 선택된 타입 설명 */}
{config.autoGeneration?.type && config.autoGeneration.type !== "none" && (
<div className="text-xs text-gray-500">
{AutoGenerationUtils.getTypeDescription(config.autoGeneration.type)}
</div>
)}
2025-11-04 17:35:02 +09:00
{/* 채번 규칙 선택 */}
{config.autoGeneration?.type === "numbering_rule" && (
<div className="space-y-2">
<Label htmlFor="numberingRuleId">
<span className="text-destructive">*</span>
</Label>
<Select
value={config.autoGeneration?.options?.numberingRuleId || ""}
onValueChange={(value) => {
const currentConfig = config.autoGeneration!;
handleChange("autoGeneration", {
...currentConfig,
options: {
...currentConfig.options,
numberingRuleId: value,
},
});
}}
disabled={loadingRules}
>
<SelectTrigger>
<SelectValue placeholder={loadingRules ? "규칙 로딩 중..." : "채번 규칙 선택"} />
</SelectTrigger>
<SelectContent>
{numberingRules.length === 0 ? (
<SelectItem value="no-rules" disabled>
</SelectItem>
) : (
numberingRules.map((rule) => (
<SelectItem key={rule.ruleId} value={rule.ruleId}>
{rule.ruleName}
{rule.description && (
<span className="text-muted-foreground ml-2 text-xs">
- {rule.description}
</span>
)}
2025-11-04 17:35:02 +09:00
</SelectItem>
))
)}
</SelectContent>
</Select>
<p className="text-muted-foreground text-xs">
</p>
</div>
)}
</div>
)}
{/* 자동생성 옵션 */}
{config.autoGeneration?.enabled &&
config.autoGeneration?.type &&
["random_string", "random_number", "sequence"].includes(config.autoGeneration.type) && (
<div className="space-y-2">
<Label> </Label>
{/* 길이 설정 (랜덤 문자열/숫자용) */}
{["random_string", "random_number"].includes(config.autoGeneration.type) && (
<div className="space-y-1">
<Label htmlFor="autoGenLength" className="text-xs">
</Label>
<Input
id="autoGenLength"
type="number"
min="1"
max="50"
value={
config.autoGeneration?.options?.length || (config.autoGeneration.type === "random_string" ? 8 : 6)
}
onChange={(e) => {
const currentConfig = config.autoGeneration!;
handleChange("autoGeneration", {
...currentConfig,
options: {
...currentConfig.options,
length: parseInt(e.target.value) || 8,
},
});
}}
/>
</div>
)}
{/* 접두사 */}
<div className="space-y-1">
<Label htmlFor="autoGenPrefix" className="text-xs">
</Label>
<Input
id="autoGenPrefix"
value={config.autoGeneration?.options?.prefix || ""}
onChange={(e) => {
const currentConfig = config.autoGeneration!;
handleChange("autoGeneration", {
...currentConfig,
options: {
...currentConfig.options,
prefix: e.target.value,
},
});
}}
/>
</div>
{/* 접미사 */}
<div className="space-y-1">
<Label htmlFor="autoGenSuffix" className="text-xs">
</Label>
<Input
id="autoGenSuffix"
value={config.autoGeneration?.options?.suffix || ""}
onChange={(e) => {
const currentConfig = config.autoGeneration!;
handleChange("autoGeneration", {
...currentConfig,
options: {
...currentConfig.options,
suffix: e.target.value,
},
});
}}
/>
</div>
{/* 미리보기 */}
<div className="space-y-1">
<Label className="text-xs"></Label>
<div className="rounded border bg-gray-100 p-2 text-xs">
{AutoGenerationUtils.generatePreviewValue(config.autoGeneration)}
</div>
</div>
</div>
)}
</div>
2025-09-11 18:38:28 +09:00
</div>
);
};