Files
frontend/apps/sn/app/(with-base-layout)/oper/dredging/lib/useDredgingCommonCodes.ts
T

136 lines
3.5 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { getCommonCodes } from "@/components/lib/common/apiHelpers";
import type {
DredgingLocationSource,
DredgingRegistrationMode,
ExifStatus,
} from "./types";
type CodeLabelMap = Record<string, string>;
const COMMON_CODE_GROUPS = {
registrationMode: "DRDGNREGMODE",
locationSource: "DRDGNLOCSRC",
photoStatus: "DRDGNPHOTOSTTS",
} as const;
const DEFAULT_REGISTRATION_MODE_LABELS: Record<
DredgingRegistrationMode,
string
> = {
PHOTO: "사진 기반 등록",
MANUAL: "사진 없이 직접 등록",
};
const DEFAULT_LOCATION_SOURCE_LABELS: Record<DredgingLocationSource, string> = {
EXIF: "사진 GPS",
MANUAL: "지도 지정",
};
const DEFAULT_PHOTO_STATUS_LABELS: Record<ExifStatus, string> = {
COMPLETE: "정상",
MISSING_DATE: "촬영일 없음",
MISSING_GPS: "GPS 없음",
MISSING_BOTH: "촬영일·GPS 없음",
UNSUPPORTED: "수동 입력 필요",
};
const cachedLabelMaps = new Map<string, CodeLabelMap>();
const pendingLabelMaps = new Map<string, Promise<CodeLabelMap>>();
/** 같은 브라우저 세션에서는 준설 코드그룹별 CMS 요청을 한 번만 수행한다. */
const loadCodeLabelMap = async (
upCd: string,
fallback: CodeLabelMap,
): Promise<CodeLabelMap> => {
const cached = cachedLabelMaps.get(upCd);
if (cached) return cached;
const pending = pendingLabelMaps.get(upCd);
if (pending) return pending;
const request = getCommonCodes(upCd)
.then((codes) => {
const labels = { ...fallback };
codes.forEach((code) => {
if (code.lwpoCd && code.lwpoCdNm) {
labels[code.lwpoCd] = code.lwpoCdNm;
}
});
cachedLabelMaps.set(upCd, labels);
return labels;
})
.finally(() => {
pendingLabelMaps.delete(upCd);
});
pendingLabelMaps.set(upCd, request);
return request;
};
/** 준설 저장 코드값은 유지하고 버튼·상세·사진상태 표시명만 CMS 기준으로 제공한다. */
export const useDredgingCommonCodes = () => {
const [registrationModeLabels, setRegistrationModeLabels] =
useState<CodeLabelMap>(
cachedLabelMaps.get(COMMON_CODE_GROUPS.registrationMode) ??
DEFAULT_REGISTRATION_MODE_LABELS,
);
const [locationSourceLabels, setLocationSourceLabels] =
useState<CodeLabelMap>(
cachedLabelMaps.get(COMMON_CODE_GROUPS.locationSource) ??
DEFAULT_LOCATION_SOURCE_LABELS,
);
const [photoStatusLabels, setPhotoStatusLabels] = useState<CodeLabelMap>(
cachedLabelMaps.get(COMMON_CODE_GROUPS.photoStatus) ??
DEFAULT_PHOTO_STATUS_LABELS,
);
useEffect(() => {
let cancelled = false;
const applyLabels = (
upCd: string,
fallback: CodeLabelMap,
setter: (labels: CodeLabelMap) => void,
) => {
loadCodeLabelMap(upCd, fallback)
.then((labels) => {
if (!cancelled) setter(labels);
})
.catch((error) => {
console.error(`${upCd} 공통코드 조회에 실패했습니다.`, error);
});
};
applyLabels(
COMMON_CODE_GROUPS.registrationMode,
DEFAULT_REGISTRATION_MODE_LABELS,
setRegistrationModeLabels,
);
applyLabels(
COMMON_CODE_GROUPS.locationSource,
DEFAULT_LOCATION_SOURCE_LABELS,
setLocationSourceLabels,
);
applyLabels(
COMMON_CODE_GROUPS.photoStatus,
DEFAULT_PHOTO_STATUS_LABELS,
setPhotoStatusLabels,
);
return () => {
cancelled = true;
};
}, []);
return {
registrationModeLabels,
locationSourceLabels,
photoStatusLabels,
};
};