jskim-node #396
|
|
@ -820,6 +820,42 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
loadOptions();
|
loadOptions();
|
||||||
}, [source, entityTable, entityValueColumn, entityLabelColumn, codeGroup, table, valueColumn, labelColumn, apiEndpoint, staticOptions, optionsLoaded, hierarchical, parentValue]);
|
}, [source, entityTable, entityValueColumn, entityLabelColumn, codeGroup, table, valueColumn, labelColumn, apiEndpoint, staticOptions, optionsLoaded, hierarchical, parentValue]);
|
||||||
|
|
||||||
|
// 레거시 평문값 → 카테고리 코드 자동 정규화 (한글 텍스트로 저장된 데이터 대응)
|
||||||
|
const resolvedValue = useMemo(() => {
|
||||||
|
if (!value || options.length === 0) return value;
|
||||||
|
|
||||||
|
const resolveOne = (v: string): string => {
|
||||||
|
if (options.some(o => o.value === v)) return v;
|
||||||
|
const trimmed = v.trim();
|
||||||
|
const match = options.find(o => {
|
||||||
|
const cleanLabel = o.label.replace(/^[\s└]+/, '').trim();
|
||||||
|
return cleanLabel === trimmed;
|
||||||
|
});
|
||||||
|
return match ? match.value : v;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
const resolved = value.map(resolveOne);
|
||||||
|
return resolved.every((v, i) => v === value[i]) ? value : resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 콤마 구분 복합값 처리 (e.g., "구매품,판매품,CAT_xxx")
|
||||||
|
if (typeof value === "string" && value.includes(",")) {
|
||||||
|
const parts = value.split(",");
|
||||||
|
const resolved = parts.map(p => resolveOne(p.trim()));
|
||||||
|
const result = resolved.join(",");
|
||||||
|
return result === value ? value : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolveOne(value);
|
||||||
|
}, [value, options]);
|
||||||
|
|
||||||
|
// 정규화 결과가 원본과 다르면 onChange로 자동 업데이트 (저장 시 코드 변환)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!onChange || options.length === 0 || !value || value === resolvedValue) return;
|
||||||
|
onChange(resolvedValue as string | string[]);
|
||||||
|
}, [resolvedValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
// 같은 폼에서 참조 테이블(entityTable) 컬럼을 사용하는 다른 컴포넌트 자동 감지
|
// 같은 폼에서 참조 테이블(entityTable) 컬럼을 사용하는 다른 컴포넌트 자동 감지
|
||||||
const autoFillTargets = useMemo(() => {
|
const autoFillTargets = useMemo(() => {
|
||||||
if (source !== "entity" || !entityTable || !allComponents) return [];
|
if (source !== "entity" || !entityTable || !allComponents) return [];
|
||||||
|
|
@ -945,7 +981,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<DropdownSelect
|
<DropdownSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={value}
|
value={resolvedValue}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
placeholder="선택"
|
placeholder="선택"
|
||||||
searchable={config.mode === "combobox" ? true : config.searchable}
|
searchable={config.mode === "combobox" ? true : config.searchable}
|
||||||
|
|
@ -961,7 +997,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<RadioSelect
|
<RadioSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={typeof value === "string" ? value : value?.[0]}
|
value={typeof resolvedValue === "string" ? resolvedValue : resolvedValue?.[0]}
|
||||||
onChange={(v) => handleChangeWithAutoFill(v)}
|
onChange={(v) => handleChangeWithAutoFill(v)}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
|
|
@ -972,7 +1008,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<CheckSelect
|
<CheckSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={Array.isArray(value) ? value : value ? [value] : []}
|
value={Array.isArray(resolvedValue) ? resolvedValue : resolvedValue ? [resolvedValue] : []}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
maxSelect={config.maxSelect}
|
maxSelect={config.maxSelect}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|
@ -983,7 +1019,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<TagSelect
|
<TagSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={Array.isArray(value) ? value : value ? [value] : []}
|
value={Array.isArray(resolvedValue) ? resolvedValue : resolvedValue ? [resolvedValue] : []}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
maxSelect={config.maxSelect}
|
maxSelect={config.maxSelect}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|
@ -994,7 +1030,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<TagboxSelect
|
<TagboxSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={Array.isArray(value) ? value : value ? [value] : []}
|
value={Array.isArray(resolvedValue) ? resolvedValue : resolvedValue ? [resolvedValue] : []}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
placeholder={config.placeholder || "선택하세요"}
|
placeholder={config.placeholder || "선택하세요"}
|
||||||
maxSelect={config.maxSelect}
|
maxSelect={config.maxSelect}
|
||||||
|
|
@ -1007,7 +1043,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<ToggleSelect
|
<ToggleSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={typeof value === "string" ? value : value?.[0]}
|
value={typeof resolvedValue === "string" ? resolvedValue : resolvedValue?.[0]}
|
||||||
onChange={(v) => handleChangeWithAutoFill(v)}
|
onChange={(v) => handleChangeWithAutoFill(v)}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1017,7 +1053,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<SwapSelect
|
<SwapSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={Array.isArray(value) ? value : value ? [value] : []}
|
value={Array.isArray(resolvedValue) ? resolvedValue : resolvedValue ? [resolvedValue] : []}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
maxSelect={config.maxSelect}
|
maxSelect={config.maxSelect}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|
@ -1028,7 +1064,7 @@ export const V2Select = forwardRef<HTMLDivElement, V2SelectProps>(
|
||||||
return (
|
return (
|
||||||
<DropdownSelect
|
<DropdownSelect
|
||||||
options={options}
|
options={options}
|
||||||
value={value}
|
value={resolvedValue}
|
||||||
onChange={handleChangeWithAutoFill}
|
onChange={handleChangeWithAutoFill}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
style={heightStyle}
|
style={heightStyle}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue