Files
frontend/apps/sn/app/(map-layout)/map/components/sinkhole/use-sinkhole-common-codes.ts
T

140 lines
3.8 KiB
TypeScript

/** 지반침하 화면에 필요한 공통코드를 조회하고 선택 항목으로 제공한다. */
"use client";
import { useEffect, useMemo, useState } from "react";
import { getCommonCodes } from "@/entities/code/api/common-code-api";
import {
SINKHOLE_COORD_STATUS_OPTIONS,
SINKHOLE_RESTORE_STATUS_OPTIONS,
} from "./sinkhole-types";
type CodeLabelMap = Record<string, string>;
type StatusOption = { value: string; label: string };
const COMMON_CODE_GROUPS = {
restoreStatus: "SNKHLRSTRSTTS",
coordStatus: "SNKHLCRDSTTS",
} as const;
const cachedCodeLists = new Map<
string,
Array<{ lwpoCd: string; lwpoCdNm: string }>
>();
const pendingCodeLists = new Map<
string,
Promise<Array<{ lwpoCd: string; lwpoCdNm: string }>>
>();
/** 같은 브라우저 세션에서는 지반침하 상태 코드그룹별 CMS 요청을 한 번만 수행한다. */
const loadCodeList = async (upCd: string) => {
const cached = cachedCodeLists.get(upCd);
if (cached) return cached;
const pending = pendingCodeLists.get(upCd);
if (pending) return pending;
const request = getCommonCodes(upCd)
.then((codes) => {
const codeList = codes.map(({ lwpoCd, lwpoCdNm }) => ({
lwpoCd,
lwpoCdNm,
}));
cachedCodeLists.set(upCd, codeList);
return codeList;
})
.finally(() => {
pendingCodeLists.delete(upCd);
});
pendingCodeLists.set(upCd, request);
return request;
};
/** 지반침하 상태의 검색값 계약은 유지하고 선택지와 표시명만 CMS 기준으로 제공한다. */
export const useSinkholeCommonCodes = () => {
const [restoreCodes, setRestoreCodes] = useState(
cachedCodeLists.get(COMMON_CODE_GROUPS.restoreStatus) ?? [],
);
const [coordCodes, setCoordCodes] = useState(
cachedCodeLists.get(COMMON_CODE_GROUPS.coordStatus) ?? [],
);
useEffect(() => {
let cancelled = false;
loadCodeList(COMMON_CODE_GROUPS.restoreStatus)
.then((codes) => {
if (!cancelled) setRestoreCodes(codes);
})
.catch((error) => {
console.error("SNKHLRSTRSTTS 공통코드 조회에 실패했습니다.", error);
});
loadCodeList(COMMON_CODE_GROUPS.coordStatus)
.then((codes) => {
if (!cancelled) setCoordCodes(codes);
})
.catch((error) => {
console.error("SNKHLCRDSTTS 공통코드 조회에 실패했습니다.", error);
});
return () => {
cancelled = true;
};
}, []);
const restoreStatusOptions = useMemo<StatusOption[]>(
() =>
restoreCodes.length > 0
? [
{ value: "0", label: "전체" },
...restoreCodes.map((code) => ({
// 백엔드는 복구상태 한글 설명값을 검색조건으로 사용하므로 코드명을 전송한다.
value: code.lwpoCdNm,
label: code.lwpoCdNm,
})),
]
: [...SINKHOLE_RESTORE_STATUS_OPTIONS],
[restoreCodes],
);
const coordStatusOptions = useMemo<StatusOption[]>(
() =>
coordCodes.length > 0
? [
{ value: "0", label: "전체" },
...coordCodes.map((code) => ({
value: code.lwpoCd,
label: code.lwpoCdNm,
})),
]
: [...SINKHOLE_COORD_STATUS_OPTIONS],
[coordCodes],
);
const restoreStatusLabels = useMemo<CodeLabelMap>(() => {
const labels: CodeLabelMap = {};
restoreCodes.forEach((code) => {
labels[code.lwpoCd] = code.lwpoCdNm;
labels[code.lwpoCdNm] = code.lwpoCdNm;
});
return labels;
}, [restoreCodes]);
const coordStatusLabels = useMemo<CodeLabelMap>(() => {
const labels: CodeLabelMap = {};
coordCodes.forEach((code) => {
labels[code.lwpoCd] = code.lwpoCdNm;
});
return labels;
}, [coordCodes]);
return {
restoreStatusOptions,
coordStatusOptions,
restoreStatusLabels,
coordStatusLabels,
};
};