136 lines
3.5 KiB
TypeScript
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,
|
|
};
|
|
};
|