[as frontend] 체크리스트 조회시 cklstResultList로 리스트로 처리 하도록 수정
This commit is contained in:
@@ -103,7 +103,6 @@ export interface InstlSncnApplySaveRequestDto {
|
||||
bzScaleList: InstlSncnBzScaleSaveDto[];
|
||||
bizCstList: InstlSncnBizCstSaveRequestDto[];
|
||||
cklstResultList: InstlSncnCklstResultSaveDto[];
|
||||
cklstResultMap?: Record<string, InstlSncnCklstResultSaveDto[]>;
|
||||
esntlAtchFileList: InstlSncnEsntlAtchFileSaveDto[];
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ export interface InstlSncnMngDetResponse {
|
||||
detDto: InstlSncnMng;
|
||||
bizSclList: any[];
|
||||
bizCstList: any[];
|
||||
cklstResultMap?: Record<ReviewStepCode, any[]>;
|
||||
cklstResultList?: any[];
|
||||
esntlFileList: any[];
|
||||
etcFileList: any[];
|
||||
}
|
||||
|
||||
@@ -112,13 +112,9 @@ const getRoleStepCount = (dtlInstCd?: string): number => {
|
||||
};
|
||||
|
||||
const normalizeChecklistResultRows = (payload: any): any[] => {
|
||||
// support new API field `cklstResultMap` while keeping backward-compatibility
|
||||
const raw = payload?.cklstResultMap ?? payload?.cklstResultList;
|
||||
if (Array.isArray(raw)) return raw;
|
||||
if (raw && typeof raw === "object") {
|
||||
return Object.values(raw).flatMap((rows) => (Array.isArray(rows) ? rows : []));
|
||||
}
|
||||
return [];
|
||||
// expect flat `cklstResultList` only
|
||||
const raw = payload?.cklstResultList ?? [];
|
||||
return Array.isArray(raw) ? raw : [];
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -156,7 +152,7 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
|
||||
// userInfo?.dtlInstCd 테스트 코드 ENV.ROLE_USER03 , KECO 권한 테스트용 (실제 권한에 맞게 변경 필요)
|
||||
const userInfo = {
|
||||
...userInfo2,
|
||||
dtlInstCd: "ROLE_USER02", //ROLE_USER03, ROLE_USER02, ROLE_USER01 KECO 권한 테스트용 (실제 권한에 맞게 변경 필요)
|
||||
dtlInstCd: "ROLE_USER05", //ROLE_USER03, ROLE_USER02, ROLE_USER01 KECO 권한 테스트용 (실제 권한에 맞게 변경 필요)
|
||||
};
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const qc = useQueryClient();
|
||||
@@ -798,32 +794,7 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
|
||||
);
|
||||
};
|
||||
|
||||
// 맵 형식으로 저장할 경우(업서트 처리용) - 키는 검토단계 코드(LOCAL/ENV/KECO) 사용
|
||||
const toCklstSaveDtoMap = () => {
|
||||
const persistedStepCodeSet = new Set<ReviewStepCode>();
|
||||
normalizeChecklistResultRows(initialData).forEach((r: any) => {
|
||||
const code = r?.rvwStpComCd as ReviewStepCode | undefined;
|
||||
if (code && REVIEW_STEP_CODES.includes(code)) persistedStepCodeSet.add(code);
|
||||
});
|
||||
visibleReviewStepCodes.forEach((code) => persistedStepCodeSet.add(code));
|
||||
|
||||
const result: Record<string, any[]> = {};
|
||||
// only persist rows that are enabled for checkbox
|
||||
const relevantRows = cklstRows.filter((row) => row.bchckUseYn === "Y");
|
||||
Array.from(persistedStepCodeSet).forEach((rvwStpComCd) => {
|
||||
// use code as key (e.g., "LOCAL") and set rvwStpComCd to the same code
|
||||
result[rvwStpComCd] = relevantRows.map((row) => ({
|
||||
cklstSn: row.cklstSn,
|
||||
cklstArtclSn: row.cklstArtclSn,
|
||||
cklstRvwSn: row.cklstRvwSn,
|
||||
rvwStpComCd: rvwStpComCd,
|
||||
selected: checkResults[cklstKey(row, rvwStpComCd)] ?? null,
|
||||
picRvwCn: checkComments[cklstKey(row, rvwStpComCd)] ?? null,
|
||||
}));
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
// removed map-shaped payload generation — server now expects `cklstResultList` only
|
||||
|
||||
const toEsntlAtchFileSaveDtoList = () =>
|
||||
Object.values(requiredFiles)
|
||||
@@ -1014,20 +985,19 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 저장 시: 사용 항목(Y)은 검토 결과가 반드시 예(Y)여야 함
|
||||
// 저장 시: bchckUseYn =="Y" 일경우 검토 결과 라디오 박스가 반드시 선택되어야 함
|
||||
const invalidYesRow = cklstRows.find(
|
||||
(row) => row.bchckUseYn === "Y" && checkResults[cklstKey(row, editableReviewStep)] !== "Y",
|
||||
(row) => row.bchckUseYn === "Y" && !checkResults[cklstKey(row, editableReviewStep)],
|
||||
);
|
||||
if (invalidYesRow) {
|
||||
const invalidKey = cklstKey(invalidYesRow, editableReviewStep);
|
||||
// console.warn("검토 결과가 예(Y)가 아닌 항목 발견:", invalidKey, invalidYesRow);
|
||||
console.warn("검토 결과 미선택 항목 발견:", invalidKey, invalidYesRow);
|
||||
const invalidRowEl = cklstRowRefs.current[invalidKey];
|
||||
invalidRowEl?.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||
const yesRadio = invalidRowEl?.querySelector<HTMLInputElement>(
|
||||
`input[name="chk_${invalidKey}"][value="Y"]`,
|
||||
);
|
||||
yesRadio?.focus();
|
||||
alert(`${invalidYesRow.rvwCn} 검토내용은 예(Y)여야 합니다.`);
|
||||
// 라디오 그룹의 첫 입력에 포커스(예:Y 또는 아니오:N)
|
||||
const firstRadio = invalidRowEl?.querySelector<HTMLInputElement>(`input[name="chk_${invalidKey}"]`);
|
||||
firstRadio?.focus();
|
||||
alert(`체크리스트 항목 "${invalidYesRow.rvwCn} 검토결과를 선택하세요.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1071,15 +1041,13 @@ function CnfmRegistPage({ initialData }: { initialData?: any } = {}) {
|
||||
|
||||
async function handleSave() {
|
||||
if (!fnValidation("SAVE")) return;
|
||||
// 저장 시에는 하위 호환성을 위해 기존 배열 필드도 함께 전송하되,
|
||||
// 추가로 서버에서 upsert 처리할 수 있도록 `cklstResultMap` 형태로도 전송합니다.
|
||||
const payload: InstlSncnApplySaveRequestDto & { cklstResultMap?: Record<string, any[]> } = {
|
||||
// 저장 시에는 `cklstResultList`만 전송합니다 (map 필드 제거)
|
||||
const payload: InstlSncnApplySaveRequestDto = {
|
||||
instlSncnMng: toInstlSncnMngPayload("SV"), // 저장 시 진행상태는 SV (임시저장)
|
||||
bzScaleList: toBzScaleSaveDtoList(),
|
||||
bizCstList: toBizCstSaveDtoList(),
|
||||
cklstResultList: toCklstSaveDtoList(),
|
||||
esntlAtchFileList: toEsntlAtchFileSaveDtoList(),
|
||||
cklstResultMap: toCklstSaveDtoMap(),
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
@@ -96,11 +96,21 @@ function CnfmViewPage({ id }: { id: string }) {
|
||||
const det = data.detDto ?? data;
|
||||
const bizSclList = data.bizSclList ?? [];
|
||||
const bizCstList = data.bizCstList ?? [];
|
||||
// prefer new API field `cklstResultMap`, fallback to legacy `cklstResultList`
|
||||
const cklstResultMap = useMemo(
|
||||
() => normalizeChecklistResultMap(data.cklstResultMap ?? data.cklstResultList),
|
||||
[data.cklstResultMap, data.cklstResultList],
|
||||
);
|
||||
// API now provides a flat checklist result list: `cklstResultList`
|
||||
const rawCklst = useMemo(() => data.cklstResultList ?? [], [data.cklstResultList]);
|
||||
|
||||
// ensure we have a flat array
|
||||
const cklstAll = useMemo(() => (Array.isArray(rawCklst) ? (rawCklst as any[]) : []), [rawCklst]);
|
||||
|
||||
// build a step-keyed map from the flat list so the rest of the view can use same access pattern
|
||||
const cklstResultMap = useMemo(() => {
|
||||
const base: Record<ReviewStepCode, any[]> = { LOCAL: [], ENV: [], KECO: [] };
|
||||
(cklstAll ?? []).forEach((row: any) => {
|
||||
const step = (row?.rvwStpComCd ?? "LOCAL") as ReviewStepCode;
|
||||
if (REVIEW_STEP_CODES.includes(step)) base[step].push(row);
|
||||
});
|
||||
return base;
|
||||
}, [cklstAll]);
|
||||
const esntlFileList = data.esntlFileList ?? [];
|
||||
const etcFileList = data.etcFileList ?? [];
|
||||
const currentPrgrsSttsComCd = (det.prgrsSttsComCd as string | undefined) ?? "ST";
|
||||
|
||||
Reference in New Issue
Block a user