101 lines
3.0 KiB
TypeScript
101 lines
3.0 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
import { generalverificationApiService } from '@/entities/statistics/api/general-verification-service';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@common/components";
|
|
|
|
type OperatorItem = {
|
|
opertSn: string;
|
|
opertSymbl: string;
|
|
opertKornNm: string;
|
|
};
|
|
|
|
// opertSeCd 별 operators 목록을 전역 캐싱해서, 수식 블록이 여러 개여도 중복 요청이 발생하지 않게 한다.
|
|
const operatorsCache: Map<
|
|
string,
|
|
OperatorItem[] | Promise<OperatorItem[]>
|
|
> = new Map();
|
|
|
|
interface OperatorsComponentsProps {
|
|
cmprOpert?: string | null;
|
|
onValueChange?: (value: string) => void;
|
|
placeholder?: string;
|
|
opertSeCd?: string;
|
|
}
|
|
|
|
const OperatorsComponents = ({
|
|
cmprOpert,
|
|
onValueChange,
|
|
placeholder = "연산자 없음",
|
|
opertSeCd = "opertSeCd=CMPR"
|
|
}: OperatorsComponentsProps) => {
|
|
const [operators, setOperators] = useState<OperatorItem[]>([]);
|
|
const [localValue, setLocalValue] = useState<string>(cmprOpert ?? "");
|
|
|
|
useEffect(() => {
|
|
setLocalValue(cmprOpert ?? "");
|
|
}, [cmprOpert]);
|
|
|
|
useEffect(() => {
|
|
const cached = operatorsCache.get(opertSeCd);
|
|
if (Array.isArray(cached)) {
|
|
setOperators(cached);
|
|
return;
|
|
}
|
|
|
|
const promise =
|
|
cached ??
|
|
(async (): Promise<OperatorItem[]> => {
|
|
const response =
|
|
await generalverificationApiService.getVrfcOperators(
|
|
opertSeCd,
|
|
);
|
|
if (response.status === "success" && response.data) {
|
|
return response.data as OperatorItem[];
|
|
}
|
|
return [];
|
|
})();
|
|
|
|
operatorsCache.set(opertSeCd, promise);
|
|
void promise.then((items) => {
|
|
operatorsCache.set(opertSeCd, items);
|
|
setOperators(items);
|
|
});
|
|
}, [opertSeCd]);
|
|
|
|
// onValueChange가 있으면 부모가 제어(controlled), 없으면 내부 state로 표시
|
|
const isControlled = onValueChange !== undefined;
|
|
const value = (isControlled ? (cmprOpert ?? "") : localValue) || "";
|
|
|
|
return (
|
|
<Select
|
|
value={value}
|
|
onValueChange={(v) => {
|
|
setLocalValue(v);
|
|
onValueChange?.(v);
|
|
}}
|
|
>
|
|
<SelectTrigger className="!w-[150px] min-w-[150px] max-w-[150px] h-[4rem] overflow-hidden focus:outline-none focus:ring-0">
|
|
<SelectValue placeholder={placeholder} />
|
|
</SelectTrigger>
|
|
<SelectContent className="w-[150px]">
|
|
<SelectItem value='none'>
|
|
연산자 없음
|
|
</SelectItem>
|
|
{operators.map((op) => (
|
|
<SelectItem key={op.opertSn} value={op.opertSymbl}>
|
|
{op.opertKornNm}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
);
|
|
};
|
|
|
|
export default OperatorsComponents;
|