Compare commits

..
18 Commits
Author SHA1 Message Date
jcchoi 1e2be153fa Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-11-09 13:48:01 +09:00
jcchoi b90ff150e8 README.md 업데이트
FSD 관련
2026-11-05 17:41:21 +09:00
rsone001 411e490b5d [ST] - retactor: 지표 변경으로 인한 컬럼 수정 2026-11-04 10:59:48 +09:00
mind-one005 aae176ff08 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-11-03 11:13:36 +09:00
rsone001 b5f5938e51 [ST] - fix: excel 가져오기 시 코드값이 숫자로 인식되어 저장이 이루어지지 않던 문제 수정 2026-10-29 10:27:42 +09:00
rsone001 038b2d441e [ST] - refactor: 처리내역 컬럼 제거 및 표준화 누락 부분 수정 2026-10-28 17:24:12 +09:00
jcchoi 766de07c04 Merge branch 'iipbs/st/dev'
Deploy Frontend / deploy (push) Successful in 4m16s
2026-10-28 15:07:16 +09:00
rsone001 2ec58f1f5b [ST] - 기본 페이지에서 대시보드 도움말을 불러오기 위해 메뉴코드 전달 2026-10-27 15:52:00 +09:00
jcchoi f1daeed4b6 Merge branch 'deploy'
Deploy Frontend / deploy (push) Successful in 8m51s
2026-10-26 20:31:55 +09:00
jcchoi 944c6ea7c7 CVE-2026-111497 “Node2Shell” 적용 2026-10-26 19:39:41 +09:00
rsone001 3cf3617513 [ST] - 검토 & 집계 2-5 컬럼 추가 2026-10-23 14:45:14 +09:00
rsone001 b611538180 [ST] - input 2-5 맨홀 컬럼 추가 2026-10-23 13:48:17 +09:00
rsone001 1cffe06cf9 [ST] - input : 시계열 검증 오류 시 진행상황 코드 롤백 api 추가, 일반 검증 관리 interface 수정 2026-10-22 18:02:48 +09:00
rsone001 9a24e4aa23 [ST] - 입력 verificationResult - cmprCn, nowCn 값 null 일시 치환 2026-10-22 16:48:34 +09:00
rsone001 3732c9380b [ST] - doList 누락 수정 2026-10-22 11:44:35 +09:00
rsone001 9e15b23eda [ST] - fix: input 2-3 저장, 제출 request 수정 2026-10-21 17:17:54 +09:00
rsone001 6f300918cd [ST] - fix: 그리드 여러행 복사 붙여넣기 시 초과된 행 수 많큼 빈행이 추가되지 않도록 수정 2026-10-21 16:04:41 +09:00
rsone001 619878bc03 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-10-21 16:01:05 +09:00
69 changed files with 905 additions and 688 deletions
+1
View File
@@ -0,0 +1 @@
22.23.4
+2
View File
@@ -202,3 +202,5 @@ http://dev.onasys.co.kr:8000/webjars/swagger-ui/index.html?urls.primaryName=atta
- 쿠키명 : menu-code-key - 쿠키명 : menu-code-key
- 해당 메뉴 쿠키 데이터 가져와 페이지 권한 및 상당 Breadcrumb 데이터 전달 처리 - 해당 메뉴 쿠키 데이터 가져와 페이지 권한 및 상당 Breadcrumb 데이터 전달 처리
## FSD 관련
https://fsd.how/kr/docs/get-started/overview/
+34 -32
View File
@@ -33,6 +33,7 @@ import {
hasAdmdstCdColumn, hasAdmdstCdColumn,
isExcelImportAdmdstCdInvalid, isExcelImportAdmdstCdInvalid,
mergeExcelImportWithExistingRows, mergeExcelImportWithExistingRows,
parseExcelImportCellValue,
prepareGridColumnsForExcelExport, prepareGridColumnsForExcelExport,
releaseFixedOptionsForExcelExport, releaseFixedOptionsForExcelExport,
resolveColumnStyleName, resolveColumnStyleName,
@@ -289,14 +290,28 @@ type GridViewWithSetColumnProperty = {
}; };
type GridViewWithEditOptions = { type GridViewWithEditOptions = {
setEditOptions?: (options: { commitWhenLeave?: boolean }) => void; setEditOptions?: (options: {
commitWhenLeave?: boolean;
appendable?: boolean;
insertable?: boolean;
}) => void;
setPasteOptions?: (options: { enableAppend?: boolean }) => void;
}; };
/** 포커스가 그리드 밖으로 나갈 때 편집 중인 값을 자동 commit */ /** 포커스가 그리드 밖으로 나갈 때 편집 중인 값을 자동 commit */
function applyDefaultGridEditOptions( function applyDefaultGridEditOptions(
gridView: GridViewWithEditOptions | null | undefined, gridView: GridViewWithEditOptions | null | undefined,
options?: { preventRowAppend?: boolean },
) { ) {
gridView?.setEditOptions?.({ commitWhenLeave: true }); gridView?.setEditOptions?.({
commitWhenLeave: true,
...(options?.preventRowAppend
? { appendable: false, insertable: false }
: {}),
});
if (options?.preventRowAppend) {
gridView?.setPasteOptions?.({ enableAppend: false });
}
} }
function isDateEditorColumn(column: { function isDateEditorColumn(column: {
@@ -853,6 +868,7 @@ const DataGrid = ({
gridHeight = 55, // vh 단위 gridHeight = 55, // vh 단위
headerHeight = 60, headerHeight = 60,
fitStyle = GridFitStyle.EVEN, fitStyle = GridFitStyle.EVEN,
preventRowAppend = true,
}: DataGridProps) => { }: DataGridProps) => {
const { columns, columnLayout } = columnInfo; const { columns, columnLayout } = columnInfo;
const fixedColumnNameSet = useMemo( const fixedColumnNameSet = useMemo(
@@ -1331,6 +1347,11 @@ useEffect(() => {
columnLayout, columnLayout,
{ skipNonEditable: false }, { skipNonEditable: false },
); );
const valueTypeByFieldName = new Map(
columns
.filter((c) => c.fieldName)
.map((c) => [c.fieldName as string, c.valueType]),
);
// 데이터 행 읽기 // 데이터 행 읽기
const dataRows: Record<string, string | number>[] = []; const dataRows: Record<string, string | number>[] = [];
@@ -1352,36 +1373,13 @@ useEffect(() => {
]; ];
const fieldName = excelColumnFieldNames[colIndex]; const fieldName = excelColumnFieldNames[colIndex];
const allFieldName = excelColumnFieldNamesAll[colIndex]; const allFieldName = excelColumnFieldNamesAll[colIndex];
const typeFieldName = fieldName || allFieldName;
let cellValue: string | number = ""; const cellValue = parseExcelImportCellValue(
if ( cell,
cell && typeFieldName
cell.v !== undefined && ? valueTypeByFieldName.get(typeFieldName)
cell.v !== null : undefined,
) {
// 엑셀 셀 타입이 숫자이거나 값이 숫자인 경우 숫자로 변환
if (
cell.t === "n" ||
(typeof cell.v === "number" &&
!isNaN(cell.v))
) {
cellValue = cell.v as number;
} else {
const stringValue = String(cell.v);
// 문자열이지만 숫자로 변환 가능한 경우 숫자로 변환
const numericValue = Number(
stringValue.replace(/,/g, ""),
); );
if (
!isNaN(numericValue) &&
stringValue.trim() !== ""
) {
cellValue = numericValue;
} else {
cellValue = stringValue;
}
}
}
if (allFieldName === "admdstCd" && cellValue !== "") { if (allFieldName === "admdstCd" && cellValue !== "") {
rowAdmdstCd = cellValue; rowAdmdstCd = cellValue;
@@ -1467,7 +1465,9 @@ useEffect(() => {
const scheduleFooterTask = (task: () => void, delayMs: number) => { const scheduleFooterTask = (task: () => void, delayMs: number) => {
footerTimerIds.push(setTimeout(task, delayMs)); footerTimerIds.push(setTimeout(task, delayMs));
}; };
applyDefaultGridEditOptions(gridView as GridViewWithEditOptions); applyDefaultGridEditOptions(gridView as GridViewWithEditOptions, {
preventRowAppend,
});
const columnsFieldsSig = columns.map((c) => c.fieldName).join("\u0001"); const columnsFieldsSig = columns.map((c) => c.fieldName).join("\u0001");
if (columnsFieldsSig !== columnsFieldsSigRef.current) { if (columnsFieldsSig !== columnsFieldsSigRef.current) {
@@ -1990,6 +1990,7 @@ useEffect(() => {
fitStyle, fitStyle,
enableSort, enableSort,
footerVerificationResult, footerVerificationResult,
preventRowAppend,
]); ]);
// 행·셀 클릭 이벤트 (검증 오류 툴팁은 hover만 — onShowTooltip / 빈 셀 오버레이) // 행·셀 클릭 이벤트 (검증 오류 툴팁은 hover만 — onShowTooltip / 빈 셀 오버레이)
@@ -2527,6 +2528,7 @@ useEffect(() => {
const gridView = gridRef.current?.gridView ?? grid; const gridView = gridRef.current?.gridView ?? grid;
applyDefaultGridEditOptions( applyDefaultGridEditOptions(
gridView as GridViewWithEditOptions, gridView as GridViewWithEditOptions,
{ preventRowAppend },
); );
if (!gridView?.columnByName) return; if (!gridView?.columnByName) return;
setTimeout(() => { setTimeout(() => {
+13 -17
View File
@@ -53,6 +53,7 @@ import {
hasAdmdstCdColumn, hasAdmdstCdColumn,
isExcelImportAdmdstCdInvalid, isExcelImportAdmdstCdInvalid,
mergeExcelImportWithExistingRows, mergeExcelImportWithExistingRows,
parseExcelImportCellValue,
prepareGridColumnsForExcelExport, prepareGridColumnsForExcelExport,
releaseFixedOptionsForExcelExport, releaseFixedOptionsForExcelExport,
resolveColumnStyleName, resolveColumnStyleName,
@@ -611,6 +612,11 @@ const TabDataGrid = ({
columnLayout, columnLayout,
{ skipNonEditable: false }, { skipNonEditable: false },
); );
const valueTypeByFieldName = new Map(
columns
.filter((c) => c.fieldName)
.map((c) => [c.fieldName as string, c.valueType]),
);
// 데이터 행 읽기 // 데이터 행 읽기
const dataRows: Record<string, string | number>[] = []; const dataRows: Record<string, string | number>[] = [];
@@ -625,23 +631,13 @@ const TabDataGrid = ({
const cell = worksheet[XLSX.utils.encode_cell({ r: row, c: col })]; const cell = worksheet[XLSX.utils.encode_cell({ r: row, c: col })];
const fieldName = excelColumnFieldNames[colIndex]; const fieldName = excelColumnFieldNames[colIndex];
const allFieldName = excelColumnFieldNamesAll[colIndex]; const allFieldName = excelColumnFieldNamesAll[colIndex];
const typeFieldName = fieldName || allFieldName;
let cellValue: string | number = ''; const cellValue = parseExcelImportCellValue(
if (cell && cell.v !== undefined && cell.v !== null) { cell,
// 엑셀 셀 타입이 숫자이거나 값이 숫자인 경우 숫자로 변환 typeFieldName
if (cell.t === 'n' || (typeof cell.v === 'number' && !isNaN(cell.v))) { ? valueTypeByFieldName.get(typeFieldName)
cellValue = cell.v as number; : undefined,
} else { );
const stringValue = String(cell.v);
// 문자열이지만 숫자로 변환 가능한 경우 숫자로 변환
const numericValue = Number(stringValue.replace(/,/g, ''));
if (!isNaN(numericValue) && stringValue.trim() !== '') {
cellValue = numericValue;
} else {
cellValue = stringValue;
}
}
}
if (allFieldName === 'admdstCd' && cellValue !== '') { if (allFieldName === 'admdstCd' && cellValue !== '') {
rowAdmdstCd = cellValue; rowAdmdstCd = cellValue;
@@ -20,6 +20,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputExcretaTreatmentFacilityApi } from "@/entities/statistics/api/input/statistics-input-excreta-treatment-facility-service"; import { statisticsInputExcretaTreatmentFacilityApi } from "@/entities/statistics/api/input/statistics-input-excreta-treatment-facility-service";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
EXCRETA_TREATMENT_FACILITY_STATS_CD, EXCRETA_TREATMENT_FACILITY_STATS_CD,
type ExcretaTreatmentFacilityItem, type ExcretaTreatmentFacilityItem,
@@ -75,7 +76,11 @@ import { toGridRows } from "@/components/util/grid/gridFunction";
import { formatCompactYmdForGrid, toCompactYmdOrNull } from "@/components/util/grid/ymdFormat"; import { formatCompactYmdForGrid, toCompactYmdOrNull } from "@/components/util/grid/ymdFormat";
import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport"; import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport";
import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag"; import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -207,7 +212,7 @@ function mapExcretaTreatmentFacilityListToGridRows(
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -502,7 +507,9 @@ const ExcretaTreatmentFacilityInp = () => {
setStatusInfo(nextStatusInfo); setStatusInfo(nextStatusInfo);
setStatsCd(commonInfo.statsCd); setStatsCd(commonInfo.statsCd);
setIsVerificationFailed(isVerificationFailedFromCommonInfo(commonInfo)); setIsVerificationFailed(isVerificationFailedFromCommonInfo(commonInfo));
setFooterVerificationResult(commonInfo.verificationResult ?? null); setFooterVerificationResult(
normalizeVerificationResultMap(commonInfo.verificationResult) ?? null,
);
if (overrides?.mode !== "PRE") { if (overrides?.mode !== "PRE") {
setIsNotApplicable(gridRows.length === 0); setIsNotApplicable(gridRows.length === 0);
} else if (gridRows.length > 0) { } else if (gridRows.length > 0) {
@@ -813,7 +820,13 @@ const ExcretaTreatmentFacilityInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForSubmit,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: statusInfo?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -952,19 +965,7 @@ const ExcretaTreatmentFacilityInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 -";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -9,6 +9,7 @@ import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { statisticsInputPrivateSewageFacilityApi } from "@/entities/statistics/api/input/statistics-input-private-sewage-facility-service"; import { statisticsInputPrivateSewageFacilityApi } from "@/entities/statistics/api/input/statistics-input-private-sewage-facility-service";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
PrivateSewageDesigStatusItem, PrivateSewageDesigStatusItem,
PrivateSewageDesigStatusSaveItem, PrivateSewageDesigStatusSaveItem,
@@ -68,7 +69,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -175,7 +180,9 @@ function mapRegionalListToGridRows<
return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => { return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => {
const { verificationResult, ...rest } = item; const { verificationResult, ...rest } = item;
const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification; const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -888,7 +895,13 @@ const PrivateSewageFacilityInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1144,18 +1157,7 @@ const PrivateSewageFacilityInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -8,6 +8,7 @@ import { useStatisticsInputPendingNavigation } from '@/shared/lib/use-statistics
import { statisticsInputSewSupplyRateApi } from '@/entities/statistics/api/input/statistics-input-sew-supply-rate-service'; import { statisticsInputSewSupplyRateApi } from '@/entities/statistics/api/input/statistics-input-sew-supply-rate-service';
import { statisticsInputPublicSewageFacilityApiService } from '@/entities/statistics/api/input/statistics-public-sewage-facility-input-service'; import { statisticsInputPublicSewageFacilityApiService } from '@/entities/statistics/api/input/statistics-public-sewage-facility-input-service';
import { statisticsApi } from '@/entities/statistics/api/statistics-service'; import { statisticsApi } from '@/entities/statistics/api/statistics-service';
import { callImrServiceWithRollbackOnFailure } from '@/components/util/input/call-imr-with-rollback';
import type { import type {
PublicSewageFacilityRequestParams, PublicSewageFacilityRequestParams,
PublicSewageFacilitySaveItem, PublicSewageFacilitySaveItem,
@@ -52,7 +53,11 @@ import { fetchColumnGuidesRecord } from '@/components/util/grid/columnGuides';
import { toGridRows } from '@/components/util/grid/gridFunction'; import { toGridRows } from '@/components/util/grid/gridFunction';
import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport"; import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport";
import { patchFooterVerificationByTab,patchVerificationFailedByTab } from '@/components/util/input/verification-failed-flag'; import { patchFooterVerificationByTab,patchVerificationFailedByTab } from '@/components/util/input/verification-failed-flag';
import type { VerificationResultLikeMap } from '@/components/util/input/verification-result-display'; import {
formatVerificationTooltip,
withNormalizedVerificationResult,
type VerificationResultLikeMap,
} from '@/components/util/input/verification-result-display';
import { nullableTrimmedString } from '@/components/util/input/nullableString'; import { nullableTrimmedString } from '@/components/util/input/nullableString';
import { useAdminStore } from '@/store/admin-store'; import { useAdminStore } from '@/store/admin-store';
import { useTabStore } from '@/store/tab-store'; import { useTabStore } from '@/store/tab-store';
@@ -438,7 +443,13 @@ const PublicSewageFacilityInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? '',
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? '',
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? '',
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -789,11 +800,13 @@ const PublicSewageFacilityInp = () => {
sidoListRef.current, sidoListRef.current,
searchContext, searchContext,
); );
const convertedData = list.map((item) => ({ const convertedData = list.map((item) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...item, ...item,
rmrk: item.rmrk ?? null, rmrk: item.rmrk ?? null,
})); }),
);
if (list.length === 0) { if (list.length === 0) {
setShowIsNotApplicable(true); setShowIsNotApplicable(true);
@@ -1575,17 +1588,7 @@ const PublicSewageFacilityInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR" ? "시계열 검증 - " : (e.vrfcCd === "NV" ? "일반검증 - " : "모집단 검증 - ");
const comp = e.cmprCn ?? "";
const now = e.nowCn ?? "";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${comp} / 현재 입력값: ${now})`;
})
.filter(Boolean)
.join("\n");
} }
}} }}
/> />
@@ -20,6 +20,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputPumpingStationApi } from "@/entities/statistics/api/input/statistics-input-pumping-station-service"; import { statisticsInputPumpingStationApi } from "@/entities/statistics/api/input/statistics-input-pumping-station-service";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
PUMPING_STATION_STATS_CD, PUMPING_STATION_STATS_CD,
type PumpingStationItem, type PumpingStationItem,
@@ -75,7 +76,11 @@ import { toGridRows } from "@/components/util/grid/gridFunction";
import { formatCompactYmdForGrid, toCompactYmdOrNull } from "@/components/util/grid/ymdFormat"; import { formatCompactYmdForGrid, toCompactYmdOrNull } from "@/components/util/grid/ymdFormat";
import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport"; import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport";
import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag"; import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -206,7 +211,7 @@ function mapPumpingStationListToGridRows(
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -493,7 +498,9 @@ const PumpingStationInp = () => {
setStatusInfo(nextStatusInfo); setStatusInfo(nextStatusInfo);
setStatsCd(commonInfo.statsCd); setStatsCd(commonInfo.statsCd);
setIsVerificationFailed(isVerificationFailedFromCommonInfo(commonInfo)); setIsVerificationFailed(isVerificationFailedFromCommonInfo(commonInfo));
setFooterVerificationResult(commonInfo.verificationResult ?? null); setFooterVerificationResult(
normalizeVerificationResultMap(commonInfo.verificationResult) ?? null,
);
if (overrides?.mode !== "PRE") { if (overrides?.mode !== "PRE") {
setIsNotApplicable(gridRows.length === 0); setIsNotApplicable(gridRows.length === 0);
} else if (gridRows.length > 0) { } else if (gridRows.length > 0) {
@@ -796,7 +803,13 @@ const PumpingStationInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForSubmit,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: statusInfo?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -935,19 +948,7 @@ const PumpingStationInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 -";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -13,6 +13,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewageExcretaRelatedApi } from "@/entities/statistics/api/input/statistics-input-sewage-excreta-related-service"; import { statisticsInputSewageExcretaRelatedApi } from "@/entities/statistics/api/input/statistics-input-sewage-excreta-related-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
ExcretaRelatedIndustrySaveItem, ExcretaRelatedIndustrySaveItem,
PrivateSewageTreatRelatedIndustrySaveItem, PrivateSewageTreatRelatedIndustrySaveItem,
@@ -84,7 +85,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -552,19 +557,7 @@ function verificationCellTooltip({
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
} }
@@ -588,7 +581,7 @@ function mapListToGridRows<T extends { verificationResult?: SewageExcretaRelated
return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => { return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => {
const row = toGridRows([{ ctpvNm, ...item }])[0] as GridRowWithVerification; const row = toGridRows([{ ctpvNm, ...item }])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -1503,7 +1496,13 @@ const SewageExcretaRelatedInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -21,6 +21,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewageExcretaSlurgeApi } from "@/entities/statistics/api/input/statistics-input-sewage-excreta-slurge-service"; import { statisticsInputSewageExcretaSlurgeApi } from "@/entities/statistics/api/input/statistics-input-sewage-excreta-slurge-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
DigestorOperatingStatusSaveItem, DigestorOperatingStatusSaveItem,
ExcretaSlurgeProcessingStatusSaveItem, ExcretaSlurgeProcessingStatusSaveItem,
@@ -90,7 +91,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -148,19 +153,7 @@ function verificationCellTooltip({
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
} }
@@ -185,7 +178,7 @@ function mapListToGridRows<T extends { verificationResult?: SewageExcretaSlurgeV
return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => { return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => {
const row = toGridRows([{ ctpvNm, ...item }])[0] as GridRowWithVerification; const row = toGridRows([{ ctpvNm, ...item }])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -627,7 +620,6 @@ function buildExcretaSlurgeProcessingStatusSaveItem(
rcycQnt: toGridNumber(row.rcycQnt), rcycQnt: toGridNumber(row.rcycQnt),
olandLfvlm: toGridNumber(row.olandLfvlm), olandLfvlm: toGridNumber(row.olandLfvlm),
incnrQnt: toGridNumber(row.incnrQnt), incnrQnt: toGridNumber(row.incnrQnt),
oceanInputQnt: toGridNumber(row.oceanInputQnt),
fuelQnt: toGridNumber(row.fuelQnt), fuelQnt: toGridNumber(row.fuelQnt),
etcQnt: toGridNumber(row.etcQnt), etcQnt: toGridNumber(row.etcQnt),
unprcsQnt: toGridNumber(row.unprcsQnt), unprcsQnt: toGridNumber(row.unprcsQnt),
@@ -1486,7 +1478,13 @@ const SewageExcretaSlurgeInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForSubmit,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -10,6 +10,7 @@ import {
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewPipeApiService } from "@/entities/statistics/api/input/statistics-sewage-pipe-input-service"; import { statisticsInputSewPipeApiService } from "@/entities/statistics/api/input/statistics-sewage-pipe-input-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
SeweragePipeInputFactInstallStatusSaveRequest, SeweragePipeInputFactInstallStatusSaveRequest,
SeweragePipeInputFactInstallStatusSubmitRequest, SeweragePipeInputFactInstallStatusSubmitRequest,
@@ -82,7 +83,10 @@ import {
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { import {
formatVerificationTooltip,
getVerificationErrorsForField, getVerificationErrorsForField,
normalizeVerificationResultMap,
withNormalizedVerificationResult,
type VerificationResultLikeMap, type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display"; } from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
@@ -289,7 +293,10 @@ function normalizePipeTypeStatusRow(
lyngPrlg: Number(lyngPrlgWhol ?? 0), lyngPrlg: Number(lyngPrlgWhol ?? 0),
dmltnPrlg: Number(dmltnPrlgWhol ?? 0), dmltnPrlg: Number(dmltnPrlgWhol ?? 0),
...yearFields, ...yearFields,
verificationResult: remapPipeTypePrlgWholVerification(verificationResult) ?? undefined, verificationResult:
normalizeVerificationResultMap(
remapPipeTypePrlgWholVerification(verificationResult),
) ?? undefined,
}; };
} }
@@ -719,10 +726,12 @@ const SewagePipeInp = () => {
const response = await statisticsInputSewPipeApiService.getRegionalFactStatus(searchParam); const response = await statisticsInputSewPipeApiService.getRegionalFactStatus(searchParam);
if (response.status === 'success') { if (response.status === 'success') {
const commonInfo = response.data.commonInfo; const commonInfo = response.data.commonInfo;
const convertedData = filterFetched(response.data.regionalFactStatusList).map((d) => ({ const convertedData = filterFetched(response.data.regionalFactStatusList).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
applyRowMap((m) => m.set('ST00020001', toGridRows(convertedData))); applyRowMap((m) => m.set('ST00020001', toGridRows(convertedData)));
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo)); setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd)); setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
@@ -749,10 +758,12 @@ const SewagePipeInp = () => {
const response = await statisticsInputSewPipeApiService.getFactInstallStatus(searchParam); const response = await statisticsInputSewPipeApiService.getFactInstallStatus(searchParam);
if (response.status === 'success') { if (response.status === 'success') {
const commonInfo = response.data.commonInfo; const commonInfo = response.data.commonInfo;
const convertedData = filterFetched(response.data.factInstallStatusList).map((d) => ({ const convertedData = filterFetched(response.data.factInstallStatusList).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
if (convertedData.length === 0) { if (convertedData.length === 0) {
const alreadyHandledForSameSearch = const alreadyHandledForSameSearch =
factInstallNoDataHandledKeyRef.current === searchConditionKey; factInstallNoDataHandledKeyRef.current === searchConditionKey;
@@ -829,10 +840,12 @@ const SewagePipeInp = () => {
const response = await statisticsInputSewPipeApiService.getPipeDiameterStatus(searchParam); const response = await statisticsInputSewPipeApiService.getPipeDiameterStatus(searchParam);
if (response.status === 'success') { if (response.status === 'success') {
const commonInfo = response.data.commonInfo; const commonInfo = response.data.commonInfo;
const convertedData = filterFetched(response.data.pipeDiameterStatusList).map((d) => ({ const convertedData = filterFetched(response.data.pipeDiameterStatusList).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
applyRowMap((m) => m.set('ST00020004', toGridRows(convertedData))); applyRowMap((m) => m.set('ST00020004', toGridRows(convertedData)));
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo)); setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd)); setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
@@ -859,10 +872,12 @@ const SewagePipeInp = () => {
const response = await statisticsInputSewPipeApiService.getManholeStatus(searchParam); const response = await statisticsInputSewPipeApiService.getManholeStatus(searchParam);
if (response.status === 'success') { if (response.status === 'success') {
const commonInfo = response.data.commonInfo; const commonInfo = response.data.commonInfo;
const convertedData = filterFetched(response.data.manholeStatusList).map((d) => ({ const convertedData = filterFetched(response.data.manholeStatusList).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
applyRowMap((m) => m.set('ST00020005', toGridRows(convertedData))); applyRowMap((m) => m.set('ST00020005', toGridRows(convertedData)));
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo)); setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, response.data.statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd)); setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
@@ -889,13 +904,15 @@ const SewagePipeInp = () => {
const response = await statisticsInputSewPipeApiService.getConnectionStatus(searchParam); const response = await statisticsInputSewPipeApiService.getConnectionStatus(searchParam);
if (response.status === 'success') { if (response.status === 'success') {
const commonInfo = response.data.commonInfo; const commonInfo = response.data.commonInfo;
const facilityConvertedData = filterFetched(response.data.facilityConnectionList).map((d) => ({ const facilityConvertedData = filterFetched(response.data.facilityConnectionList).map((d) =>
...d, withNormalizedVerificationResult({ ...d }),
})); );
const adminConvertedData = filterFetched(response.data.adminAreaConnectionList).map((d) => ({ const adminConvertedData = filterFetched(response.data.adminAreaConnectionList).map((d) =>
withNormalizedVerificationResult({
...d, ...d,
ctpvNm: d.ctpvNm || commonInfo.ctpvNm, ctpvNm: d.ctpvNm || commonInfo.ctpvNm,
})); }),
);
applyRowMap((m) => { applyRowMap((m) => {
m.set('treatmentPlantConnectionInp', toGridRows(facilityConvertedData)); m.set('treatmentPlantConnectionInp', toGridRows(facilityConvertedData));
m.set('adminAreaConnectionInp', toGridRows(adminConvertedData)); m.set('adminAreaConnectionInp', toGridRows(adminConvertedData));
@@ -1338,7 +1355,6 @@ const SewagePipeInp = () => {
rmrk: nullableTrimmedString(d.rmrk), rmrk: nullableTrimmedString(d.rmrk),
lyngPrlgWhol: formatNumber(d.lyngPrlg, "lyngPrlg"), lyngPrlgWhol: formatNumber(d.lyngPrlg, "lyngPrlg"),
dmltnPrlgWhol: formatNumber(d.dmltnPrlg, "dmltnPrlg"), dmltnPrlgWhol: formatNumber(d.dmltnPrlg, "dmltnPrlg"),
pipeByPrstWhol: formatNumber(d.pipeByPrstWhol, "pipeByPrstWhol"),
}; };
}); });
const requestData: SeweragePipeInputPipeTypeStatusSubmitRequest = { const requestData: SeweragePipeInputPipeTypeStatusSubmitRequest = {
@@ -1455,7 +1471,13 @@ const SewagePipeInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: values.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: values?.bsnmCd ?? "",
rollbackStatusCode: statusForTab?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1830,7 +1852,6 @@ const SewagePipeInp = () => {
rmrk: nullableTrimmedString(d.rmrk), rmrk: nullableTrimmedString(d.rmrk),
lyngPrlgWhol: formatNumber(d.lyngPrlg, "lyngPrlg"), lyngPrlgWhol: formatNumber(d.lyngPrlg, "lyngPrlg"),
dmltnPrlgWhol: formatNumber(d.dmltnPrlg, "dmltnPrlg"), dmltnPrlgWhol: formatNumber(d.dmltnPrlg, "dmltnPrlg"),
pipeByPrstWhol: formatNumber(d.pipeByPrstWhol, "pipeByPrstWhol"),
}; };
}); });
@@ -2237,17 +2258,7 @@ const SewagePipeInp = () => {
tabKey, tabKey,
); );
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR" ? "시계열 검증 - " : (e.vrfcCd === "NV" ? "일반검증 - " : "모집단 검증 - ");
const comp = e.cmprCn ?? "";
const now = e.nowCn ?? "";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${comp} / 현재 입력값: ${now})`;
})
.filter(Boolean)
.join("\n");
} }
}} }}
/> />
@@ -11,6 +11,7 @@ import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { sewagePipeMaintainApiService } from "@/entities/statistics/api/input/statistics-input-sewage-pipe-maintain-service"; import { sewagePipeMaintainApiService } from "@/entities/statistics/api/input/statistics-input-sewage-pipe-maintain-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
SewagePipeMaintainDredgingSaveItem, SewagePipeMaintainDredgingSaveItem,
SewagePipeMaintainDredgingSaveRequest, SewagePipeMaintainDredgingSaveRequest,
@@ -69,7 +70,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
withNormalizedVerificationResult,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useStatisticsInputFocusStore } from "@/store/statistics-input-focus-store"; import { useStatisticsInputFocusStore } from "@/store/statistics-input-focus-store";
@@ -444,10 +449,12 @@ const SewagePipeMaintainInp = () => {
repairStatusList ?? [], repairStatusList ?? [],
sidoListRef.current, sidoListRef.current,
searchContext, searchContext,
).map((d) => ({ ).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
const gridRows = toGridRows(convertedData); const gridRows = toGridRows(convertedData);
applyRowMap(mergeIntoExistingMap, (m) => { applyRowMap(mergeIntoExistingMap, (m) => {
@@ -487,10 +494,12 @@ const SewagePipeMaintainInp = () => {
pipeDredgingStatusList ?? [], pipeDredgingStatusList ?? [],
sidoListRef.current, sidoListRef.current,
searchContext, searchContext,
).map((d) => ({ ).map((d) =>
withNormalizedVerificationResult({
ctpvNm: commonInfo.ctpvNm, ctpvNm: commonInfo.ctpvNm,
...d, ...d,
})); }),
);
const gridRows = toGridRows(convertedData); const gridRows = toGridRows(convertedData);
applyRowMap(mergeIntoExistingMap, (m) => { applyRowMap(mergeIntoExistingMap, (m) => {
@@ -678,7 +687,13 @@ const SewagePipeMaintainInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1103,14 +1118,7 @@ const SewagePipeMaintainInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR" ? "시계열 검증 - " : e.vrfcCd === "NV" ? "일반검증 - " : "모집단 검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -21,6 +21,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewageReservoirPumpApi } from "@/entities/statistics/api/input/statistics-input-sewage-reservoir-pump-service"; import { statisticsInputSewageReservoirPumpApi } from "@/entities/statistics/api/input/statistics-input-sewage-reservoir-pump-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
type RainfallPumpStationItem, type RainfallPumpStationItem,
type RainfallPumpStationSaveItem, type RainfallPumpStationSaveItem,
@@ -89,7 +90,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -279,7 +284,7 @@ function mapSewageReservoirListToGridRows(
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -435,7 +440,7 @@ function mapRainfallPumpStationListToGridRows(
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (item.verificationResult) { if (item.verificationResult) {
row.verificationResult = item.verificationResult; row.verificationResult = normalizeVerificationResultMap(item.verificationResult);
} }
return row; return row;
}); });
@@ -864,7 +869,13 @@ const SewageReservoirPumpInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1516,19 +1527,7 @@ const SewageReservoirPumpInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 -";
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -8,6 +8,7 @@ import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewerageFinanceApi } from "@/entities/statistics/api/input/statistics-input-sewerage-finance-service"; import { statisticsInputSewerageFinanceApi } from "@/entities/statistics/api/input/statistics-input-sewerage-finance-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import type { import type {
CauserBurdenItem, CauserBurdenItem,
CauserBurdenSaveItem, CauserBurdenSaveItem,
@@ -73,7 +74,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -174,7 +179,9 @@ function mapRegionalListToGridRows<
return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => { return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => {
const { verificationResult, ...rest } = item; const { verificationResult, ...rest } = item;
const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification; const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -940,7 +947,13 @@ const SewerageFinanceInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1215,18 +1228,7 @@ const SewerageFinanceInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -10,6 +10,7 @@ import {
import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
type CheckInputPeriodItem, type CheckInputPeriodItem,
getVerificationPeriodActionBlockedMessage, getVerificationPeriodActionBlockedMessage,
@@ -58,7 +59,11 @@ import { toGridRows } from "@/components/util/grid/gridFunction";
import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport"; import { toExcelExportSearchContextFromSearchForm } from "@/components/util/gridExcelExport";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag"; import { isVerificationFailedFromCommonInfo } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useStatisticsInputFocusStore } from "@/store/statistics-input-focus-store"; import { useStatisticsInputFocusStore } from "@/store/statistics-input-focus-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -87,7 +92,7 @@ const remapCommonInfoVerificationToGridFields = (
// API 키로도 조회 가능하도록 유지 // API 키로도 조회 가능하도록 유지
if (gridField !== key) remapped[key] = errors; if (gridField !== key) remapped[key] = errors;
} }
return remapped; return normalizeVerificationResultMap(remapped) ?? remapped;
}; };
/** 컬럼 가이드 API 조회용 통계코드 (하수도 보급률) */ /** 컬럼 가이드 API 조회용 통계코드 (하수도 보급률) */
@@ -302,7 +307,11 @@ const SeweragePenetrationRateInp = () => {
setRowData( setRowData(
convertedData.map((d) => { convertedData.map((d) => {
const row = toGridRows([d])[0] as GridRowWithVerification; const row = toGridRows([d])[0] as GridRowWithVerification;
if (d.verificationResult) row.verificationResult = d.verificationResult; if (d.verificationResult) {
row.verificationResult = normalizeVerificationResultMap(
d.verificationResult,
);
}
return row; return row;
}) })
); );
@@ -558,7 +567,13 @@ const SeweragePenetrationRateInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: searchValues?.year ?? "",
statsCd,
sewerBzmnCd: searchValues?.bsnmCd ?? "",
rollbackStatusCode: statusInfo?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted(imrResponse.job_id, (id) => await waitForImrJobCompleted(imrResponse.job_id, (id) =>
statisticsApi.getImrStatus(id), statisticsApi.getImrStatus(id),
@@ -867,14 +882,7 @@ const SeweragePenetrationRateInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix = e.vrfcCd === 'IMR' ? '시계열 검증 - ' : (e.vrfcCd === 'NV' ? '일반검증 - ' : '모집단 검증 -');
return `${prefix}${e.rsnExpln}
(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join('\n');
} }
}} }}
/> />
@@ -9,6 +9,7 @@ import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewerageServiceLevelApi } from "@/entities/statistics/api/input/statistics-input-sewerage-service-level-service"; import { statisticsInputSewerageServiceLevelApi } from "@/entities/statistics/api/input/statistics-input-sewerage-service-level-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
SEWERAGE_SERVICE_LEVEL_COMPLAINT_STATS_CD, SEWERAGE_SERVICE_LEVEL_COMPLAINT_STATS_CD,
SEWERAGE_SERVICE_LEVEL_RESIDENT_FRIENDLY_FACT_STATS_CD, SEWERAGE_SERVICE_LEVEL_RESIDENT_FRIENDLY_FACT_STATS_CD,
@@ -63,7 +64,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { nullableTrimmedString } from "@/components/util/input/nullableString"; import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -187,7 +192,9 @@ function mapServiceLevelListToGridRows<
return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => { return filterBySelectedAdmdstCd(list, sidoListRef.current, values).map((item) => {
const { verificationResult, ...rest } = item; const { verificationResult, ...rest } = item;
const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification; const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -839,7 +846,13 @@ const SewerageServiceLevelInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -1146,18 +1159,7 @@ const SewerageServiceLevelInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -20,8 +20,8 @@ const StatisticsReviewHistory = () => {
{ name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false }, { name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false },
{ name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false },
{ name: "menuNm", fieldName: "menuNm", header: { text: "통계항목" }, editable: false }, { name: "menuNm", fieldName: "menuNm", header: { text: "통계항목" }, editable: false },
{ name: "chckerOpinionSm", fieldName: "chckerOpinionSm", header: { text: "검토자의견" }, editable: false }, { name: "splmntOpnnCn", fieldName: "splmntOpnnCn", header: { text: "검토자의견" }, editable: false },
{ name: "wrterOpinionSm", fieldName: "wrterOpinionSm", header: { text: "처리내역" }, editable: false }, { name: "rjctOpnnCn", fieldName: "rjctOpnnCn", header: { text: "반려의견" }, editable: false },
]; ];
const columnLayout = [ const columnLayout = [
@@ -29,8 +29,8 @@ const StatisticsReviewHistory = () => {
"ctpvNm", "ctpvNm",
"sggNm", "sggNm",
"menuNm", "menuNm",
"chckerOpinionSm", "splmntOpnnCn",
"wrterOpinionSm", "rjctOpnnCn",
]; ];
const handleSearch = async (values: SearchFormValues) => { const handleSearch = async (values: SearchFormValues) => {
@@ -21,6 +21,7 @@ import { nullableTrimmedString } from "@/components/util/input/nullableString";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service"; import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputWaterReuseApi } from "@/entities/statistics/api/input/statistics-input-water-reuse-service"; import { statisticsInputWaterReuseApi } from "@/entities/statistics/api/input/statistics-input-water-reuse-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service"; import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { callImrServiceWithRollbackOnFailure } from "@/components/util/input/call-imr-with-rollback";
import { import {
type PublicSewageTreatWaterReuseItem, type PublicSewageTreatWaterReuseItem,
type PublicSewageTreatWaterReuseSaveItem, type PublicSewageTreatWaterReuseSaveItem,
@@ -93,7 +94,11 @@ import {
patchFooterVerificationByTab, patchFooterVerificationByTab,
patchVerificationFailedByTab, patchVerificationFailedByTab,
} from "@/components/util/input/verification-failed-flag"; } from "@/components/util/input/verification-failed-flag";
import type { VerificationResultLikeMap } from "@/components/util/input/verification-result-display"; import {
formatVerificationTooltip,
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "@/components/util/input/verification-result-display";
import { useAdminStore } from "@/store/admin-store"; import { useAdminStore } from "@/store/admin-store";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
@@ -443,7 +448,9 @@ function mapPublicSewageTreatWaterReuseListToGridRows(
instlAprvYmd: formatCompactYmdForGrid(item.instlAprvYmd), instlAprvYmd: formatCompactYmdForGrid(item.instlAprvYmd),
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -462,7 +469,9 @@ function mapRecycledWaterStatusListToGridRows(
oprtngStrtYmd: formatCompactYmdForGrid(item.oprtngStrtYmd), oprtngStrtYmd: formatCompactYmdForGrid(item.oprtngStrtYmd),
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -480,7 +489,9 @@ function mapRainFallUtilFactStatusListToGridRows(
cmptnYmd: formatCompactYmdForGrid(item.cmptnYmd), cmptnYmd: formatCompactYmdForGrid(item.cmptnYmd),
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -497,7 +508,9 @@ function mapTreatWaterReuseStatusListToGridRows<
coRegYmd: formatCompactYmdForGrid(item.coRegYmd), coRegYmd: formatCompactYmdForGrid(item.coRegYmd),
}, },
])[0] as GridRowWithVerification; ])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult; if (verificationResult) {
row.verificationResult = normalizeVerificationResultMap(verificationResult);
}
return row; return row;
}); });
} }
@@ -1355,7 +1368,13 @@ const WaterReuseInp = () => {
}; };
try { try {
const imrResponse = await statisticsApi.callImrService(imrParam); const imrResponse = await callImrServiceWithRollbackOnFailure(imrParam, {
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
sewerBzmnCd: lastSearchedValues?.bsnmCd ?? "",
rollbackStatusCode: activeTabStatus?.lclgvSbmsnSttsCd ?? "",
mdfrUuid: userInfo.userUnqId,
});
if (imrResponse.job_id) { if (imrResponse.job_id) {
await waitForImrJobCompleted( await waitForImrJobCompleted(
imrResponse.job_id, imrResponse.job_id,
@@ -2063,18 +2082,7 @@ const WaterReuseInp = () => {
if (!verification) return; if (!verification) return;
const errors = verification[fieldName]; const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) { if (Array.isArray(errors) && errors.length > 0) {
return errors return formatVerificationTooltip(errors);
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "시계열 검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "모집단 검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.cmprCn} / 현재 입력값: ${e.nowCn})`;
})
.filter(Boolean)
.join("\n");
} }
}; };
@@ -49,7 +49,6 @@ const ExcretaTreatmentFacilityRvw = () => {
const [reviewOpinionContext, setReviewOpinionContext] = const [reviewOpinionContext, setReviewOpinionContext] =
useState<ReviewOpinionDialogContext | null>(null); useState<ReviewOpinionDialogContext | null>(null);
const [latestReviewOpinion, setLatestReviewOpinion] = useState(""); const [latestReviewOpinion, setLatestReviewOpinion] = useState("");
const [latestProcessHistory, setLatestProcessHistory] = useState("");
const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null); const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null);
const columnInfo = useMemo(() => { const columnInfo = useMemo(() => {
@@ -116,7 +115,6 @@ const ExcretaTreatmentFacilityRvw = () => {
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
setLastSearchValues(null); setLastSearchValues(null);
setReviewOpinionOpen(false); setReviewOpinionOpen(false);
setReturnDialogOpen(false); setReturnDialogOpen(false);
@@ -170,14 +168,12 @@ const ExcretaTreatmentFacilityRvw = () => {
statsCd: statsInfo.statsCd ?? "", statsCd: statsInfo.statsCd ?? "",
}); });
setLatestReviewOpinion(statsInfo.splmntOpnnCn ?? ""); setLatestReviewOpinion(statsInfo.splmntOpnnCn ?? "");
setLatestProcessHistory(statsInfo.splmntRsltCn ?? "");
setRowData(toGridRows(convertedData as unknown as object[])); setRowData(toGridRows(convertedData as unknown as object[]));
} else { } else {
setRowData([]); setRowData([]);
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
alert(response.message || "데이터가 없습니다."); alert(response.message || "데이터가 없습니다.");
} }
} catch { } catch {
@@ -216,7 +212,6 @@ const ExcretaTreatmentFacilityRvw = () => {
const row = detailRes.data?.[0]; const row = detailRes.data?.[0];
setLatestReviewOpinion(row?.splmntOpnnCn ?? ""); setLatestReviewOpinion(row?.splmntOpnnCn ?? "");
setLatestProcessHistory(row?.splmntRsltCn ?? "");
setReviewOpinionOpen(true); setReviewOpinionOpen(true);
} catch { } catch {
alert("검토의견 조회 중 오류가 발생했습니다."); alert("검토의견 조회 중 오류가 발생했습니다.");
@@ -234,10 +229,8 @@ const ExcretaTreatmentFacilityRvw = () => {
setStatsStatusInfo((prev) => ({ setStatsStatusInfo((prev) => ({
...prev, ...prev,
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
})); }));
setLatestReviewOpinion(param.splmntOpnnCn); setLatestReviewOpinion(param.splmntOpnnCn);
setLatestProcessHistory(param.splmntRsltCn);
} catch { } catch {
alert("저장 중 오류가 발생했습니다."); alert("저장 중 오류가 발생했습니다.");
} }
@@ -297,7 +290,6 @@ const ExcretaTreatmentFacilityRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -102,7 +102,6 @@ const PrivateSewageFacilityRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -284,7 +283,6 @@ const PrivateSewageFacilityRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -307,7 +305,6 @@ const PrivateSewageFacilityRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -411,7 +408,6 @@ const PrivateSewageFacilityRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -41,7 +41,6 @@ const PublicSewageFacilityRvw = () => {
const [reviewOpinionContext, setReviewOpinionContext] = const [reviewOpinionContext, setReviewOpinionContext] =
useState<ReviewOpinionDialogContext | null>(null); useState<ReviewOpinionDialogContext | null>(null);
const [latestReviewOpinion, setLatestReviewOpinion] = useState(""); const [latestReviewOpinion, setLatestReviewOpinion] = useState("");
const [latestProcessHistory, setLatestProcessHistory] = useState("");
const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null); const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null);
const columnInfo = useMemo(() => { const columnInfo = useMemo(() => {
@@ -100,7 +99,6 @@ const PublicSewageFacilityRvw = () => {
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
setLastSearchValues(null); setLastSearchValues(null);
setSubmitDialogOpen(false); setSubmitDialogOpen(false);
}; };
@@ -143,16 +141,12 @@ const PublicSewageFacilityRvw = () => {
setLatestReviewOpinion( setLatestReviewOpinion(
response.data.statsStatusInfo.splmntOpnnCn ?? "", response.data.statsStatusInfo.splmntOpnnCn ?? "",
); );
setLatestProcessHistory(
response.data.statsStatusInfo.splmntRsltCn ?? "",
);
setRowData(toGridRows(convertedData as unknown as object[])); setRowData(toGridRows(convertedData as unknown as object[]));
} else { } else {
setRowData([]); setRowData([]);
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
alert(response.message || "데이터가 없습니다."); alert(response.message || "데이터가 없습니다.");
} }
} catch (error) { } catch (error) {
@@ -192,7 +186,6 @@ const PublicSewageFacilityRvw = () => {
const row = detailRes.data?.[0]; const row = detailRes.data?.[0];
setLatestReviewOpinion(row?.splmntOpnnCn ?? ""); setLatestReviewOpinion(row?.splmntOpnnCn ?? "");
setLatestProcessHistory(row?.splmntRsltCn ?? "");
setReviewOpinionOpen(true); setReviewOpinionOpen(true);
} catch { } catch {
alert("검토의견 조회 중 오류가 발생했습니다."); alert("검토의견 조회 중 오류가 발생했습니다.");
@@ -210,10 +203,8 @@ const PublicSewageFacilityRvw = () => {
setStatsStatusInfo((prev) => ({ setStatsStatusInfo((prev) => ({
...prev, ...prev,
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
})); }));
setLatestReviewOpinion(param.splmntOpnnCn); setLatestReviewOpinion(param.splmntOpnnCn);
setLatestProcessHistory(param.splmntRsltCn);
} catch { } catch {
alert("저장 중 오류가 발생했습니다."); alert("저장 중 오류가 발생했습니다.");
} }
@@ -267,7 +258,6 @@ const PublicSewageFacilityRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -47,7 +47,6 @@ const PumpingStationRvw = () => {
const [reviewOpinionContext, setReviewOpinionContext] = const [reviewOpinionContext, setReviewOpinionContext] =
useState<ReviewOpinionDialogContext | null>(null); useState<ReviewOpinionDialogContext | null>(null);
const [latestReviewOpinion, setLatestReviewOpinion] = useState(""); const [latestReviewOpinion, setLatestReviewOpinion] = useState("");
const [latestProcessHistory, setLatestProcessHistory] = useState("");
const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null); const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null);
const columnInfo = useMemo(() => { const columnInfo = useMemo(() => {
@@ -111,7 +110,6 @@ const PumpingStationRvw = () => {
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
setLastSearchValues(null); setLastSearchValues(null);
setReviewOpinionOpen(false); setReviewOpinionOpen(false);
setReturnDialogOpen(false); setReturnDialogOpen(false);
@@ -157,14 +155,12 @@ const PumpingStationRvw = () => {
statsCd: statsInfo.statsCd ?? "", statsCd: statsInfo.statsCd ?? "",
}); });
setLatestReviewOpinion(statsInfo.splmntOpnnCn ?? ""); setLatestReviewOpinion(statsInfo.splmntOpnnCn ?? "");
setLatestProcessHistory(statsInfo.splmntRsltCn ?? "");
setRowData(toGridRows(convertedData)); setRowData(toGridRows(convertedData));
} else { } else {
setRowData([]); setRowData([]);
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
alert(response.message || "데이터가 없습니다."); alert(response.message || "데이터가 없습니다.");
} }
} catch { } catch {
@@ -203,7 +199,6 @@ const PumpingStationRvw = () => {
const row = detailRes.data?.[0]; const row = detailRes.data?.[0];
setLatestReviewOpinion(row?.splmntOpnnCn ?? ""); setLatestReviewOpinion(row?.splmntOpnnCn ?? "");
setLatestProcessHistory(row?.splmntRsltCn ?? "");
setReviewOpinionOpen(true); setReviewOpinionOpen(true);
} catch { } catch {
alert("검토의견 조회 중 오류가 발생했습니다."); alert("검토의견 조회 중 오류가 발생했습니다.");
@@ -221,10 +216,8 @@ const PumpingStationRvw = () => {
setStatsStatusInfo((prev) => ({ setStatsStatusInfo((prev) => ({
...prev, ...prev,
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
})); }));
setLatestReviewOpinion(param.splmntOpnnCn); setLatestReviewOpinion(param.splmntOpnnCn);
setLatestProcessHistory(param.splmntRsltCn);
} catch { } catch {
alert("저장 중 오류가 발생했습니다."); alert("저장 중 오류가 발생했습니다.");
} }
@@ -284,7 +277,6 @@ const PumpingStationRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -30,8 +30,6 @@ export interface ReviewOpinionDialogProps {
context: ReviewOpinionDialogContext | null; context: ReviewOpinionDialogContext | null;
/** 다이얼로그 열릴 때 검토의견 초기값 */ /** 다이얼로그 열릴 때 검토의견 초기값 */
initialReviewOpinion?: string; initialReviewOpinion?: string;
/** 다이얼로그 열릴 때 처리내역 초기값 */
initialProcessHistory?: string;
/** 저장 시 생성된 param 전달 (API 호출 등) */ /** 저장 시 생성된 param 전달 (API 호출 등) */
onSave?: (param: ReviewOpinionSaveRequest) => void | Promise<void>; onSave?: (param: ReviewOpinionSaveRequest) => void | Promise<void>;
} }
@@ -41,18 +39,15 @@ export function ReviewOpinionDialog({
onOpenChange, onOpenChange,
context, context,
initialReviewOpinion = "", initialReviewOpinion = "",
initialProcessHistory = "",
onSave, onSave,
}: ReviewOpinionDialogProps) { }: ReviewOpinionDialogProps) {
const { setMessage: alert } = useAlertStore((state) => state); const { setMessage: alert } = useAlertStore((state) => state);
const [reviewOpinion, setReviewOpinion] = useState(""); const [reviewOpinion, setReviewOpinion] = useState("");
const [processHistory, setProcessHistory] = useState("");
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [reviewOpinionError, setReviewOpinionError] = useState(false); const [reviewOpinionError, setReviewOpinionError] = useState(false);
const resetForm = () => { const resetForm = () => {
setReviewOpinion(""); setReviewOpinion("");
setProcessHistory("");
setReviewOpinionError(false); setReviewOpinionError(false);
}; };
@@ -64,8 +59,7 @@ export function ReviewOpinionDialog({
useEffect(() => { useEffect(() => {
if (!open) return; if (!open) return;
setReviewOpinion(initialReviewOpinion); setReviewOpinion(initialReviewOpinion);
setProcessHistory(initialProcessHistory); }, [open, initialReviewOpinion]);
}, [open, initialReviewOpinion, initialProcessHistory]);
const handleSave = async () => { const handleSave = async () => {
if (reviewOpinion.trim() === "") { if (reviewOpinion.trim() === "") {
@@ -96,7 +90,6 @@ export function ReviewOpinionDialog({
sewerBzmnCd: context.sewerBzmnCd, sewerBzmnCd: context.sewerBzmnCd,
statsCd: context.statsCd, statsCd: context.statsCd,
splmntOpnnCn: reviewOpinion, splmntOpnnCn: reviewOpinion,
splmntRsltCn: processHistory,
mdfrUuid: userInfo.userUnqId, mdfrUuid: userInfo.userUnqId,
}; };
await onSave?.(param); await onSave?.(param);
@@ -136,16 +129,6 @@ export function ReviewOpinionDialog({
</p> </p>
)} )}
</div> </div>
<div className="flex flex-col gap-2">
<Label className="text-label mb-2">처리내역</Label>
<Textarea
value={processHistory}
onChange={(e) => setProcessHistory(e.target.value)}
className="min-h-[10rem] resize-y !text-[1.3rem] !leading-6"
placeholder="처리내역을 입력하세요."
disabled={isSaving}
/>
</div>
</div> </div>
<DialogFooter> <DialogFooter>
<DialogClose asChild> <DialogClose asChild>
@@ -30,8 +30,8 @@ export interface ReviewSubmitDialogProps {
context: ReviewerInfoRequest | null; context: ReviewerInfoRequest | null;
onSubmitted?: () => void | Promise<void>; onSubmitted?: () => void | Promise<void>;
/** /**
* true면 검토의견·처리내역 UI를 숨기고 * true면 검토의견 UI를 숨기고
* submit body에 statsCd / splmntOpnnCn / splmntRsltCn을 넣지 않음 * submit body에 statsCd / splmntOpnnCn을 넣지 않음
*/ */
hideOpinionFields?: boolean; hideOpinionFields?: boolean;
} }
@@ -116,7 +116,6 @@ export function ReviewSubmitDialog({
statsCd: context.statsCd, statsCd: context.statsCd,
mdfrUuid: userInfo.userUnqId, mdfrUuid: userInfo.userUnqId,
splmntOpnnCn: reviewerInfo?.splmntOpnnCn ?? "", splmntOpnnCn: reviewerInfo?.splmntOpnnCn ?? "",
splmntRsltCn: reviewerInfo?.splmntRsltCn ?? "",
}; };
const response = await statisticsApi.submitReview(submitParam); const response = await statisticsApi.submitReview(submitParam);
@@ -175,14 +174,6 @@ export function ReviewSubmitDialog({
className="min-h-[10rem] p-2 resize-none !text-xl" className="min-h-[10rem] p-2 resize-none !text-xl"
/> />
</div> </div>
<div className="col-span-2 flex flex-col gap-2">
<Label className="text-label">처리내역</Label>
<Textarea
value={reviewerInfo?.splmntRsltCn ?? "-"}
readOnly
className="min-h-[10rem] p-2 resize-none !text-xl"
/>
</div>
</> </>
)} )}
</div> </div>
@@ -105,7 +105,6 @@ const SewageExcretaRelatedRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -289,7 +288,6 @@ const SewageExcretaRelatedRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -312,7 +310,6 @@ const SewageExcretaRelatedRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -416,7 +413,6 @@ const SewageExcretaRelatedRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -105,7 +105,6 @@ const SewageExcretaSlurgeRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -290,7 +289,6 @@ const SewageExcretaSlurgeRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -313,7 +311,6 @@ const SewageExcretaSlurgeRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -417,7 +414,6 @@ const SewageExcretaSlurgeRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -120,7 +120,6 @@ const SewagePipeMaintainRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -302,7 +301,6 @@ const SewagePipeMaintainRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -325,7 +323,6 @@ const SewagePipeMaintainRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -429,7 +426,6 @@ const SewagePipeMaintainRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -181,7 +181,6 @@ const SewagePipeRvw = () => {
}; };
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -362,7 +361,6 @@ const SewagePipeRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -385,7 +383,6 @@ const SewagePipeRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -488,7 +485,6 @@ const SewagePipeRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -126,7 +126,6 @@ const SewageReservoirPumpRvw = () => {
}, [activeStatsCd, lastSearchValues]); }, [activeStatsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -308,7 +307,6 @@ const SewageReservoirPumpRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -331,7 +329,6 @@ const SewageReservoirPumpRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -435,7 +432,6 @@ const SewageReservoirPumpRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -105,7 +105,6 @@ const SewerageFinanceRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -287,7 +286,6 @@ const SewerageFinanceRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -310,7 +308,6 @@ const SewerageFinanceRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -414,7 +411,6 @@ const SewerageFinanceRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -40,7 +40,6 @@ const SeweragePenetrationRateRvw = () => {
const [reviewOpinionContext, setReviewOpinionContext] = const [reviewOpinionContext, setReviewOpinionContext] =
useState<ReviewOpinionDialogContext | null>(null); useState<ReviewOpinionDialogContext | null>(null);
const [latestReviewOpinion, setLatestReviewOpinion] = useState(""); const [latestReviewOpinion, setLatestReviewOpinion] = useState("");
const [latestProcessHistory, setLatestProcessHistory] = useState("");
const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null); const [lastSearchValues, setLastSearchValues] = useState<SearchFormValues | null>(null);
const columnInfo = useMemo(() => { const columnInfo = useMemo(() => {
@@ -100,7 +99,6 @@ const SeweragePenetrationRateRvw = () => {
setStatsStatusInfo({}); setStatsStatusInfo({});
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
setLastSearchValues(null); setLastSearchValues(null);
}; };
@@ -139,15 +137,11 @@ const SeweragePenetrationRateRvw = () => {
setLatestReviewOpinion( setLatestReviewOpinion(
response.data.statsStatusInfo.splmntOpnnCn ?? "", response.data.statsStatusInfo.splmntOpnnCn ?? "",
); );
setLatestProcessHistory(
response.data.statsStatusInfo.splmntRsltCn ?? "",
);
setRowData(toGridRows(convertedData)); setRowData(toGridRows(convertedData));
} else { } else {
setRowData([]); setRowData([]);
setReviewOpinionContext(null); setReviewOpinionContext(null);
setLatestReviewOpinion(""); setLatestReviewOpinion("");
setLatestProcessHistory("");
alert(response.message || "데이터가 없습니다."); alert(response.message || "데이터가 없습니다.");
} }
} catch (error) { } catch (error) {
@@ -187,7 +181,6 @@ const SeweragePenetrationRateRvw = () => {
const row = detailRes.data?.[0]; const row = detailRes.data?.[0];
setLatestReviewOpinion(row?.splmntOpnnCn ?? ""); setLatestReviewOpinion(row?.splmntOpnnCn ?? "");
setLatestProcessHistory(row?.splmntRsltCn ?? "");
setReviewOpinionOpen(true); setReviewOpinionOpen(true);
} catch { } catch {
alert("검토의견 조회 중 오류가 발생했습니다."); alert("검토의견 조회 중 오류가 발생했습니다.");
@@ -205,10 +198,8 @@ const SeweragePenetrationRateRvw = () => {
setStatsStatusInfo((prev) => ({ setStatsStatusInfo((prev) => ({
...prev, ...prev,
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
})); }));
setLatestReviewOpinion(param.splmntOpnnCn); setLatestReviewOpinion(param.splmntOpnnCn);
setLatestProcessHistory(param.splmntRsltCn);
} catch { } catch {
alert("저장 중 오류가 발생했습니다."); alert("저장 중 오류가 발생했습니다.");
} }
@@ -264,7 +255,6 @@ const SeweragePenetrationRateRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -103,7 +103,6 @@ const SewerageServiceLevelRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -288,7 +287,6 @@ const SewerageServiceLevelRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -311,7 +309,6 @@ const SewerageServiceLevelRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -415,7 +412,6 @@ const SewerageServiceLevelRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -39,22 +39,14 @@ import { toGridRows } from "@/components/util/grid/gridFunction";
type ReviewHistoryRow = ReviewHistoryResponse["data"][number]; type ReviewHistoryRow = ReviewHistoryResponse["data"][number];
const checkPrvnStatusCd = (code: string) => {
return (code === '0' || code === '1') ? '미작성' : (code === '2' ? '제출완료' : (code === '3' ? '승인완료' : '반려'));
};
const checkSubmitStatusCd = (code: string) => {
return code === '0' ? '미작성' : (code === '1' ? '작성중' : (code === '2' ? '제출완료' : (code === '3' ? '승인완료' : '보완요청')));
};
const isStatsInputStatusRowApprovable = (row: Record<string, string | number>) => const isStatsInputStatusRowApprovable = (row: Record<string, string | number>) =>
String(row.submitStatusCd ?? "") === "3" && (String(row.prvnStatusCd ?? "") === "2" || String(row.prvnStatusCd ?? "") === "3"); String(row.lclgvSbmsnSttsCd ?? "") === "3" &&
(String(row.mctpvPicSbmsnSttsCd ?? "") === "2" ||
String(row.mctpvPicSbmsnSttsCd ?? "") === "3");
const mapSewerageListToGridRows = (rawList: StatsInputStatusReviewItem[]) => const mapSewerageListToGridRows = (rawList: StatsInputStatusReviewItem[]) =>
rawList.map((r) => ({ rawList.map((r) => ({
...r, ...r,
prvnStatusNm: checkPrvnStatusCd(r.prvnStatusCd || "0"),
submitStatusNm: checkSubmitStatusCd(r.submitStatusCd || "0"),
reviewHistory: "검토이력", reviewHistory: "검토이력",
})); }));
@@ -97,7 +89,7 @@ const StatsInputStatusRvw = () => {
const reviewHistoryColumns = useMemo(() => { const reviewHistoryColumns = useMemo(() => {
const col = createColumnHelper<ReviewHistoryRow>(); const col = createColumnHelper<ReviewHistoryRow>();
return [ return [
col.accessor("logDt", { col.accessor("regDt", {
header: "등록일", header: "등록일",
cell: (info) => info.getValue(), cell: (info) => info.getValue(),
}), }),
@@ -238,23 +230,23 @@ const StatsInputStatusRvw = () => {
const allSubmitStatusApproved = useMemo( const allSubmitStatusApproved = useMemo(
() => () =>
rowData.length > 0 && rowData.length > 0 &&
rowData.every((row) => String(row.submitStatusCd ?? "") === "3"), rowData.every((row) => String(row.lclgvSbmsnSttsCd ?? "") === "3"),
[rowData], [rowData],
); );
/** 진행상태(prvn) 코드가 모두 승인완료(3) */ /** 진행상태(광역) 코드가 모두 승인완료(3) */
const allPrvnStatusApproved = useMemo( const allPrvnStatusApproved = useMemo(
() => () =>
rowData.length > 0 && rowData.length > 0 &&
rowData.every((row) => String(row.prvnStatusCd ?? "") === "3"), rowData.every((row) => String(row.mctpvPicSbmsnSttsCd ?? "") === "3"),
[rowData], [rowData],
); );
/** 진행상태(prvn) 코드가 모두 제출완료(2) */ /** 진행상태(광역) 코드가 모두 제출완료(2) */
const allPrvnStatusSubmitted = useMemo( const allPrvnStatusSubmitted = useMemo(
() => () =>
rowData.length > 0 && rowData.length > 0 &&
rowData.every((row) => String(row.prvnStatusCd ?? "") === "2"), rowData.every((row) => String(row.mctpvPicSbmsnSttsCd ?? "") === "2"),
[rowData], [rowData],
); );
@@ -392,8 +384,8 @@ const StatsInputStatusRvw = () => {
setRowData={setRowData} setRowData={setRowData}
onDataCellClick={handleReviewHistoryCellClick} onDataCellClick={handleReviewHistoryCellClick}
cellStyleCallback={({ row, fieldName }) => { cellStyleCallback={({ row, fieldName }) => {
if (fieldName === "submitStatusNm") { if (fieldName === "lclgvSbmsnSttsNm") {
const statusCd = String(row.submitStatusCd ?? ""); const statusCd = String(row.lclgvSbmsnSttsCd ?? "");
if (statusCd === "0" || statusCd === "1") { if (statusCd === "0" || statusCd === "1") {
return "rg-cell-stats-status-pending"; return "rg-cell-stats-status-pending";
@@ -408,8 +400,8 @@ const StatsInputStatusRvw = () => {
return "rg-cell-stats-status-rejected"; return "rg-cell-stats-status-rejected";
} }
return undefined; return undefined;
} else if (fieldName === "prvnStatusNm") { } else if (fieldName === "mctpvPicSbmsnSttsNm") {
const statusCd = String(row.prvnStatusCd ?? ""); const statusCd = String(row.mctpvPicSbmsnSttsCd ?? "");
if (statusCd === "0" || statusCd === "1") { if (statusCd === "0" || statusCd === "1") {
return "rg-cell-stats-status-pending"; return "rg-cell-stats-status-pending";
@@ -108,7 +108,6 @@ const WaterReuseRvw = () => {
}, [activeStatsStatusInfo.statsCd, lastSearchValues]); }, [activeStatsStatusInfo.statsCd, lastSearchValues]);
const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? ""; const latestReviewOpinion = activeStatsStatusInfo.splmntOpnnCn ?? "";
const latestProcessHistory = activeStatsStatusInfo.splmntRsltCn ?? "";
const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => { const submitDialogContext = useMemo<ReviewerInfoRequest | null>(() => {
if (lastSearchValues == null) return null; if (lastSearchValues == null) return null;
@@ -291,7 +290,6 @@ const WaterReuseRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: row?.splmntOpnnCn ?? "", splmntOpnnCn: row?.splmntOpnnCn ?? "",
splmntRsltCn: row?.splmntRsltCn ?? "",
}); });
return next; return next;
}); });
@@ -314,7 +312,6 @@ const WaterReuseRvw = () => {
next.set(activeTab, { next.set(activeTab, {
...(next.get(activeTab) ?? {}), ...(next.get(activeTab) ?? {}),
splmntOpnnCn: param.splmntOpnnCn, splmntOpnnCn: param.splmntOpnnCn,
splmntRsltCn: param.splmntRsltCn,
}); });
return next; return next;
}); });
@@ -418,7 +415,6 @@ const WaterReuseRvw = () => {
onOpenChange={setReviewOpinionOpen} onOpenChange={setReviewOpinionOpen}
context={reviewOpinionContext} context={reviewOpinionContext}
initialReviewOpinion={latestReviewOpinion} initialReviewOpinion={latestReviewOpinion}
initialProcessHistory={latestProcessHistory}
onSave={saveReviewOpinion} onSave={saveReviewOpinion}
/> />
<ReviewSubmitDialog <ReviewSubmitDialog
@@ -554,17 +554,20 @@ const DetailComponent = ({
const userInfo = await getUserInfo(); const userInfo = await getUserInfo();
let response; let response;
const vrfcSn = detailInfo?.commonInfo.vrfcSn;
if (vrfcSn == null) {
alert("검증 일련번호가 없습니다.");
return;
}
if (!hasPersistedDetails) { if (!hasPersistedDetails) {
response = response =
await generalverificationApiService.RegistVrfcDetail({ await generalverificationApiService.RegistVrfcDetail(vrfcSn, {
vrfcSn: detailInfo?.commonInfo.vrfcSn ?? null,
detailList: rows, detailList: rows,
rgtrUuid: userInfo.userUnqId, rgtrUuid: userInfo.userUnqId,
}); });
} else { } else {
response = response =
await generalverificationApiService.UpdateVrfcDetail({ await generalverificationApiService.UpdateVrfcDetail(vrfcSn, {
vrfcSn: detailInfo?.commonInfo.vrfcSn ?? null,
detailList: rows, detailList: rows,
mdfrUuid: userInfo.userUnqId, mdfrUuid: userInfo.userUnqId,
}); });
@@ -146,9 +146,15 @@ const RegistDialog = memo(
} }
}; };
const handleUpdateVrfcMaster = async (data: GeneralVerificationMasterSubmitFormData) => { const handleUpdateVrfcMaster = async (
updateVrfcSn: number,
body: UpdateVrfcMasterRequest,
) => {
try { try {
const response = await generalverificationApiService.UpdateVrfcMaster(data as UpdateVrfcMasterRequest); const response = await generalverificationApiService.UpdateVrfcMaster(
updateVrfcSn,
body,
);
if (response.status === 'success') { if (response.status === 'success') {
alert('수정되었습니다.'); alert('수정되었습니다.');
@@ -258,8 +264,11 @@ const RegistDialog = memo(
if (await confirm(confirmMessage)) { if (await confirm(confirmMessage)) {
const userInfo = await getUserInfo(); const userInfo = await getUserInfo();
if (isVrfcSn) { if (isVrfcSn) {
const updateData = { if (data.vrfcSn == null) {
vrfcSn: data.vrfcSn, alert('수정 대상이 없습니다.');
return;
}
await handleUpdateVrfcMaster(data.vrfcSn, {
vrfcNm: data.vrfcNm, vrfcNm: data.vrfcNm,
vrfcClsfCd: data.vrfcClsfCd, vrfcClsfCd: data.vrfcClsfCd,
dcptDgt: data.dcptDgt, dcptDgt: data.dcptDgt,
@@ -267,10 +276,8 @@ const RegistDialog = memo(
...(data.dcptDgt === 0 ...(data.dcptDgt === 0
? {} ? {}
: { dcptPrcsMthCd: data.dcptPrcsMthCd }), : { dcptPrcsMthCd: data.dcptPrcsMthCd }),
trgtStatsCd: data.trgtStatsCd,
mdfrUuid: userInfo.userUnqId, mdfrUuid: userInfo.userUnqId,
}; });
await handleUpdateVrfcMaster(updateData);
} else { } else {
const registData = { const registData = {
vrfcNm: data.vrfcNm, vrfcNm: data.vrfcNm,
@@ -481,6 +481,11 @@ export type DataGridProps = {
headerHeight?: number; headerHeight?: number;
/** RealGrid `displayOptions.fitStyle` (기본 EVEN). 컬럼별 width 유지 시 NONE */ /** RealGrid `displayOptions.fitStyle` (기본 EVEN). 컬럼별 width 유지 시 NONE */
fitStyle?: GridFitStyle; fitStyle?: GridFitStyle;
/**
* true면 붙여넣기·편집으로 행을 추가하지 않음.
* 검증 결과처럼 조회 행 수가 고정된 그리드에서 사용.
*/
preventRowAppend?: boolean;
}; };
export type TabDataGridProps = { export type TabDataGridProps = {
@@ -8,6 +8,7 @@ export const doList = [
"4600000000", "4600000000",
"4700000000", "4700000000",
"4800000000", "4800000000",
"5000000000",
]; ];
export const needBsnmFrgnrPoplSmSidoList = [ export const needBsnmFrgnrPoplSmSidoList = [
@@ -27,7 +27,6 @@ export const ExcretaSlurgeProcessingStatusInpColumn = {
'rcycQnt', 'rcycQnt',
'olandLfvlm', 'olandLfvlm',
'incnrQnt', 'incnrQnt',
'oceanInputQnt',
'fuelQnt', 'fuelQnt',
'etcQnt', 'etcQnt',
'unprcsQnt' 'unprcsQnt'
@@ -51,7 +50,6 @@ export const ExcretaSlurgeProcessingStatusInpColumn = {
'rcycQnt', 'rcycQnt',
'olandLfvlm', 'olandLfvlm',
'incnrQnt', 'incnrQnt',
'oceanInputQnt',
'fuelQnt', 'fuelQnt',
'etcQnt', 'etcQnt',
], ],
@@ -61,7 +59,6 @@ export const ExcretaSlurgeProcessingStatusInpColumn = {
{ name: 'rcycQnt', fieldName: 'rcycQnt', header: { text: '재활용' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, { name: 'rcycQnt', fieldName: 'rcycQnt', header: { text: '재활용' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'olandLfvlm', fieldName: 'olandLfvlm', header: { text: '육상매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, { name: 'olandLfvlm', fieldName: 'olandLfvlm', header: { text: '육상매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'incnrQnt', fieldName: 'incnrQnt', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, { name: 'incnrQnt', fieldName: 'incnrQnt', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'oceanInputQnt', fieldName: 'oceanInputQnt', header: { text: '해양투기' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'fuelQnt', fieldName: 'fuelQnt', header: { text: '연료화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, { name: 'fuelQnt', fieldName: 'fuelQnt', header: { text: '연료화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'etcQnt', fieldName: 'etcQnt', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, { name: 'etcQnt', fieldName: 'etcQnt', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
@@ -100,7 +97,6 @@ export const ExcretaSlurgeProcessingStatusInpColumn = {
'rcycQnt', 'rcycQnt',
'olandLfvlm', 'olandLfvlm',
'incnrQnt', 'incnrQnt',
'oceanInputQnt',
'fuelQnt', 'fuelQnt',
'etcQnt' 'etcQnt'
] ]
@@ -49,6 +49,43 @@ export const ManholeStatusInpColumn = {
styleName: "rg-cell-readonly", styleName: "rg-cell-readonly",
footer: { text: "합계" }, footer: { text: "합계" },
}, },
{
name: "wholMnhlCntSum",
fieldName: "wholMnhlCntSum",
header: { text: "맨홀총계" },
footer: footerInt,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: "#,##0",
styleName: "rg-cell-readonly",
},
{
name: "frlvlMnhlCntSum",
fieldName: "frlvlMnhlCntSum",
header: { text: "주철계" },
footer: footerInt,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: "#,##0",
styleName: "rg-cell-readonly",
},
{
name: "thlvlMnhlCntSum",
fieldName: "thlvlMnhlCntSum",
header: { text: "콘크리트계" },
footer: footerInt,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: "#,##0",
styleName: "rg-cell-readonly",
},
{
name: "picNm",
fieldName: "picNm",
header: { text: "담당자명" },
editable: false,
styleName: "rg-cell-readonly",
},
{ {
...intCol("wholMnhlCnt", "계", false), ...intCol("wholMnhlCnt", "계", false),
computed: { computed: {
@@ -88,6 +125,12 @@ export const ManholeStatusInpColumn = {
}, },
"admdstNm", "admdstNm",
"emphsMngSeNm", "emphsMngSeNm",
{
name: "adminRefGroup",
hideChildHeaders: false,
header: { text: "행정참고자료" },
items: ["wholMnhlCntSum", "frlvlMnhlCntSum", "thlvlMnhlCntSum", "picNm"],
},
{ {
name: "mtrlGroup", name: "mtrlGroup",
hideChildHeaders: false, hideChildHeaders: false,
@@ -75,6 +75,8 @@ export const PublicSewageTreatWaterReuseInpColumn = {
name: 'lglYn', name: 'lglYn',
fieldName: 'lglYn', fieldName: 'lglYn',
header: { text: '법적의무대상(대상/미대상)' }, header: { text: '법적의무대상(대상/미대상)' },
editable: false,
styleName: 'rg-cell-readonly'
}, },
PUBLIC_SEWAGE_TREAT_WATER_REUSE_LGL_YN_VALUES, PUBLIC_SEWAGE_TREAT_WATER_REUSE_LGL_YN_VALUES,
), ),
@@ -32,11 +32,11 @@ export const getGeneralVerificationColumns = (
}, },
{ {
accessorKey: "vrfcClsfNm", accessorKey: "vrfcClsfNm",
header: "검증분류", header: "검증 분류",
}, },
{ {
accessorKey: "useYn", accessorKey: "useYn",
header: "사용여부", header: "사용 여부",
}, },
{ {
accessorKey: "regDt", accessorKey: "regDt",
@@ -346,7 +346,6 @@ const rawSludgeList = [
decimal1Col("rcycQnt", "재활용"), decimal1Col("rcycQnt", "재활용"),
decimal1Col("olandLfvlm", "육상매립"), decimal1Col("olandLfvlm", "육상매립"),
decimal1Col("incnrQnt", "소각"), decimal1Col("incnrQnt", "소각"),
decimal1Col("oceanInputQnt", "해양투기"),
decimal1Col("fuelQnt", "연료화"), decimal1Col("fuelQnt", "연료화"),
decimal1Col("etcQnt", "기타"), decimal1Col("etcQnt", "기타"),
decimal1Col("unprcsQnt", "미처분량\n(이월량)(C)"), decimal1Col("unprcsQnt", "미처분량\n(이월량)(C)"),
@@ -366,7 +365,6 @@ const rawSludgeList = [
"rcycQnt", "rcycQnt",
"olandLfvlm", "olandLfvlm",
"incnrQnt", "incnrQnt",
"oceanInputQnt",
"fuelQnt", "fuelQnt",
"etcQnt", "etcQnt",
], ],
@@ -491,6 +491,10 @@ const rawList = [
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true },
{ name: 'emphsMngSeNm', fieldName: 'emphsMngSeNm', header: { text: '집중강우\n중점관리\n구역구분' }, mergeCells: true }, { name: 'emphsMngSeNm', fieldName: 'emphsMngSeNm', header: { text: '집중강우\n중점관리\n구역구분' }, mergeCells: true },
{ name: 'wholMnhlCntSum', fieldName: 'wholMnhlCntSum', header: { text: '맨홀총계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'frlvlMnhlCntSum', fieldName: 'frlvlMnhlCntSum', header: { text: '주철계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'thlvlMnhlCntSum', fieldName: 'thlvlMnhlCntSum', header: { text: '콘크리트계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'picNm', fieldName: 'picNm', header: { text: '담당자명' } },
{ {
name: 'displayYear', name: 'displayYear',
fieldName: 'displayYear', fieldName: 'displayYear',
@@ -544,6 +548,12 @@ const rawList = [
], ],
}, },
'emphsMngSeNm', 'emphsMngSeNm',
{
name: 'adminRefGroup',
hideChildHeaders: false,
header: { text: '행정참고자료' },
items: ['wholMnhlCntSum', 'frlvlMnhlCntSum', 'thlvlMnhlCntSum', 'picNm'],
},
'displayYear', 'displayYear',
{ {
name: 'mtrlGroup', name: 'mtrlGroup',
@@ -17,12 +17,12 @@ const StatsInputStatusInfoColumnRaw = {
styleName: 'rg-cell-outline-action-btn', styleName: 'rg-cell-outline-action-btn',
}, },
{ name: 'chargerNm', fieldName: 'chargerNm', header: { text: '제출자' } }, { name: 'lclgvPicNm', fieldName: 'lclgvPicNm', header: { text: '제출자' } },
{ name: 'chargerCttpc', fieldName: 'chargerCttpc', header: { text: '연락처' } }, { name: 'lclgvPicTelnoCn', fieldName: 'lclgvPicTelnoCn', header: { text: '연락처' } },
{ name: 'submitStatusNm', fieldName: 'submitStatusNm', header: { text: '지자체진행상태' } }, { name: 'lclgvSbmsnSttsNm', fieldName: 'lclgvSbmsnSttsNm', header: { text: '지자체진행상태' } },
{ name: 'submitStatusCd', fieldName: 'submitStatusCd', header: { text: '지자체진행상태코드' }, visible: false }, { name: 'lclgvSbmsnSttsCd', fieldName: 'lclgvSbmsnSttsCd', header: { text: '지자체진행상태코드' }, visible: false },
{ name: 'prvnStatusNm', fieldName: 'prvnStatusNm', header: { text: '진행상태' } }, { name: 'mctpvPicSbmsnSttsNm', fieldName: 'mctpvPicSbmsnSttsNm', header: { text: '진행상태' } },
{ name: 'prvnStatusCd', fieldName: 'prvnStatusCd', header: { text: '진행상태코드' }, visible: false }, { name: 'mctpvPicSbmsnSttsCd', fieldName: 'mctpvPicSbmsnSttsCd', header: { text: '진행상태코드' }, visible: false },
], ],
columnLayout: [ columnLayout: [
@@ -30,14 +30,14 @@ const StatsInputStatusInfoColumnRaw = {
'sggNm', 'sggNm',
'tabNm', 'tabNm',
'reviewHistory', 'reviewHistory',
'chargerNm', 'lclgvPicNm',
'chargerCttpc', 'lclgvPicTelnoCn',
'submitStatusNm', 'lclgvSbmsnSttsNm',
'prvnStatusNm', 'mctpvPicSbmsnSttsNm',
'statsCd', 'statsCd',
'sewerBzmnCd', 'sewerBzmnCd',
'submitStatusCd', 'lclgvSbmsnSttsCd',
'prvnStatusCd' 'mctpvPicSbmsnSttsCd',
] ]
}; };
@@ -710,6 +710,10 @@ const rawSewagePipeTotList = [
{ name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false },
{ name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false }, { name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false },
{ name: "emphsMngSeNm", fieldName: "emphsMngSeNm", header: { text: "집중강우\n중점관리\n구역구분" }, editable: false }, { name: "emphsMngSeNm", fieldName: "emphsMngSeNm", header: { text: "집중강우\n중점관리\n구역구분" }, editable: false },
{ name: "wholMnhlCntSum", fieldName: "wholMnhlCntSum", header: { text: "맨홀총계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
{ name: "frlvlMnhlCntSum", fieldName: "frlvlMnhlCntSum", header: { text: "주철계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
{ name: "thlvlMnhlCntSum", fieldName: "thlvlMnhlCntSum", header: { text: "콘크리트계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
{ name: "picNm", fieldName: "picNm", header: { text: "담당자명" }, editable: false },
{ name: "wholMnhlCnt", fieldName: "wholMnhlCnt", header: { text: "계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, { name: "wholMnhlCnt", fieldName: "wholMnhlCnt", header: { text: "계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
{ name: "frlvlMnhlCnt", fieldName: "frlvlMnhlCnt", header: { text: "주철" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, { name: "frlvlMnhlCnt", fieldName: "frlvlMnhlCnt", header: { text: "주철" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
{ name: "sclvlMnhlCnt", fieldName: "sclvlMnhlCnt", header: { text: "주철(조화)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, { name: "sclvlMnhlCnt", fieldName: "sclvlMnhlCnt", header: { text: "주철(조화)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false },
@@ -720,6 +724,11 @@ const rawSewagePipeTotList = [
columnLayout: [ columnLayout: [
{ name: "addrGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] }, { name: "addrGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] },
"emphsMngSeNm", "emphsMngSeNm",
{
name: "adminRefGroup",
header: { text: "행정참고자료" },
items: ["wholMnhlCntSum", "frlvlMnhlCntSum", "thlvlMnhlCntSum", "picNm"],
},
{ {
name: "mtrlGroup", name: "mtrlGroup",
header: { text: "맨홀뚜껑 재질(개)" }, header: { text: "맨홀뚜껑 재질(개)" },
@@ -16,7 +16,6 @@ export const HumanWasteSludgeTab4ColumnConfig = {
{ name: "rcycQnt", fieldName: "rcycQnt", header: { text: "재활용" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "rcycQnt", fieldName: "rcycQnt", header: { text: "재활용" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "olandLfvlm", fieldName: "olandLfvlm", header: { text: "육상매립" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "olandLfvlm", fieldName: "olandLfvlm", header: { text: "육상매립" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "incnrQnt", fieldName: "incnrQnt", header: { text: "소각" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "incnrQnt", fieldName: "incnrQnt", header: { text: "소각" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "oceanInputQnt", fieldName: "oceanInputQnt", header: { text: "해양투기" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "fuelQnt", fieldName: "fuelQnt", header: { text: "연료화" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "fuelQnt", fieldName: "fuelQnt", header: { text: "연료화" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "etcQnt", fieldName: "etcQnt", header: { text: "기타" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "etcQnt", fieldName: "etcQnt", header: { text: "기타" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
{ name: "unprcsQnt", fieldName: "unprcsQnt", header: { text: "미처분량\n(이월량)(C)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, { name: "unprcsQnt", fieldName: "unprcsQnt", header: { text: "미처분량\n(이월량)(C)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false },
@@ -29,7 +28,7 @@ export const HumanWasteSludgeTab4ColumnConfig = {
{ {
name: "dspsGroup", name: "dspsGroup",
header: { text: "처분량" }, header: { text: "처분량" },
items: ["wholDspsQnt", "rcycQnt", "olandLfvlm", "incnrQnt", "oceanInputQnt", "fuelQnt", "etcQnt"] items: ["wholDspsQnt", "rcycQnt", "olandLfvlm", "incnrQnt", "fuelQnt", "etcQnt"]
}, },
"unprcsQnt", "unprcsQnt",
"swtrmtFcltNm" "swtrmtFcltNm"
+85 -3
View File
@@ -1,4 +1,4 @@
import type { GridView } from "realgrid"; import { type GridView, ValueType } from "realgrid";
import type { import type {
ColumnConfig, ColumnConfig,
@@ -124,6 +124,82 @@ export function getNonEditableColumnFieldNames(
return fieldNames; return fieldNames;
} }
type ExcelImportCell = {
t?: string;
v?: unknown;
w?: string;
};
/** 엑셀 셀 → 그리드 값. NUMBER 컬럼만 숫자화하고, 코드(01)는 문자열로 유지 */
export function parseExcelImportCellValue(
cell: ExcelImportCell | undefined,
valueType?: ColumnConfig["valueType"],
): string | number {
if (!cell || cell.v === undefined || cell.v === null || cell.v === "") {
return "";
}
if (valueType === ValueType.NUMBER) {
if (typeof cell.v === "number" && !Number.isNaN(cell.v)) {
return cell.v;
}
const stringValue = String(cell.v);
const numericValue = Number(stringValue.replace(/,/g, ""));
if (!Number.isNaN(numericValue) && stringValue.trim() !== "") {
return numericValue;
}
return stringValue;
}
const formatted = typeof cell.w === "string" ? cell.w.trim() : "";
if (/^0\d+$/.test(formatted)) {
return formatted;
}
return String(cell.v);
}
function collectZeroPaddedCodeWidths(
rows: Record<string, string | number>[],
): Map<string, number> {
const widthByField = new Map<string, number>();
for (const row of rows) {
for (const [field, value] of Object.entries(row)) {
const s = String(value ?? "").trim();
if (!/^0\d+$/.test(s)) continue;
widthByField.set(field, Math.max(widthByField.get(field) ?? 0, s.length));
}
}
return widthByField;
}
function restoreImportedCodeLeadingZeros(
importedRow: Record<string, string | number>,
existingRow: Record<string, string | number> | undefined,
codeWidthByField: Map<string, number>,
): Record<string, string | number> {
const next: Record<string, string | number> = { ...importedRow };
for (const [field, value] of Object.entries(next)) {
if (value === "" || value == null) continue;
if (typeof value === "number" && !Number.isInteger(value)) continue;
const importedStr = String(value).trim();
if (!/^\d+$/.test(importedStr)) continue;
const existingStr =
existingRow != null ? String(existingRow[field] ?? "").trim() : "";
let width = codeWidthByField.get(field);
if (!width && /^0\d+$/.test(existingStr)) {
width = existingStr.length;
}
if (!width && field.endsWith("Cd") && importedStr.length <= 2) {
width = 2;
}
if (width && importedStr.length < width) {
next[field] = importedStr.padStart(width, "0");
}
}
return next;
}
/** 엑셀 import 결과를 기존 행과 병합 — preserveFieldNames는 기존 그리드 값 유지 */ /** 엑셀 import 결과를 기존 행과 병합 — preserveFieldNames는 기존 그리드 값 유지 */
export function mergeExcelImportWithExistingRows( export function mergeExcelImportWithExistingRows(
existingRows: Record<string, string | number>[], existingRows: Record<string, string | number>[],
@@ -134,14 +210,20 @@ export function mergeExcelImportWithExistingRows(
options?.preserveFieldNames && options.preserveFieldNames.length > 0 options?.preserveFieldNames && options.preserveFieldNames.length > 0
? new Set(options.preserveFieldNames) ? new Set(options.preserveFieldNames)
: null; : null;
const codeWidthByField = collectZeroPaddedCodeWidths(existingRows);
return importedRows.map((importedRow, index) => { return importedRows.map((importedRow, index) => {
const existingRow = existingRows[index]; const existingRow = existingRows[index];
if (!existingRow) return { ...importedRow }; const normalizedImported = restoreImportedCodeLeadingZeros(
importedRow,
existingRow,
codeWidthByField,
);
if (!existingRow) return normalizedImported;
const merged: Record<string, string | number> = { const merged: Record<string, string | number> = {
...existingRow, ...existingRow,
...importedRow, ...normalizedImported,
}; };
if (preserveSet) { if (preserveSet) {
for (const fieldName of preserveSet) { for (const fieldName of preserveSet) {
@@ -0,0 +1,23 @@
import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import type {
ImrRequest,
ImrResponse,
rollbackStatusRequest,
} from "@/entities/statistics/model/statistics-interface";
/** 제출 직후 IMR 요청이 실패하면 검증 이전 상태로 롤백 */
export async function callImrServiceWithRollbackOnFailure(
imrParam: ImrRequest,
rollbackParam: rollbackStatusRequest,
): Promise<ImrResponse> {
try {
return await statisticsApi.callImrService(imrParam);
} catch (error) {
try {
await statisticsApi.rollbackStatus(rollbackParam);
} catch {
// 롤백 실패는 IMR 실패를 가리지 않음
}
throw error;
}
}
@@ -1,6 +1,9 @@
import type { StatisticsInputCommonInfoBase } from "@/entities/statistics/model/statistics-interface"; import type { StatisticsInputCommonInfoBase } from "@/entities/statistics/model/statistics-interface";
import type { VerificationResultLikeMap } from "./verification-result-display"; import {
normalizeVerificationResultMap,
type VerificationResultLikeMap,
} from "./verification-result-display";
export function isVerificationFailedFromCommonInfo( export function isVerificationFailedFromCommonInfo(
commonInfo: Pick<StatisticsInputCommonInfoBase, "isVerificationFailed"> | null | undefined, commonInfo: Pick<StatisticsInputCommonInfoBase, "isVerificationFailed"> | null | undefined,
@@ -28,6 +31,9 @@ export function patchFooterVerificationByTab(
| undefined, | undefined,
): Map<string, VerificationResultLikeMap | null> { ): Map<string, VerificationResultLikeMap | null> {
const next = new Map(prev); const next = new Map(prev);
next.set(tabKey, commonInfo?.verificationResult ?? null); next.set(
tabKey,
normalizeVerificationResultMap(commonInfo?.verificationResult) ?? null,
);
return next; return next;
} }
@@ -13,6 +13,49 @@ export type VerificationResultLikeMap = Record<
VerificationResultLikeItem[] VerificationResultLikeItem[]
>; >;
/** 입력 조회 verificationResult의 기준값/입력값이 null이면 "-" */
export function displayVerificationCn(
value: string | null | undefined,
): string {
if (value == null || String(value).trim() === "") return "-";
return String(value);
}
export function normalizeVerificationResultItem<T extends VerificationResultLikeItem>(
item: T,
): T {
return {
...item,
nowCn: displayVerificationCn(item.nowCn ?? item.nowVlCn),
cmprCn: displayVerificationCn(item.cmprCn ?? item.compVlCn),
};
}
export function normalizeVerificationResultMap<T extends VerificationResultLikeMap>(
result: T | null | undefined,
): T | undefined {
if (!result || typeof result !== "object") return undefined;
const next = {} as T;
for (const [key, items] of Object.entries(result)) {
(next as VerificationResultLikeMap)[key] = Array.isArray(items)
? items.map((item) => normalizeVerificationResultItem(item))
: [];
}
return next;
}
/** 조회 행/객체에 붙은 verificationResult의 cmprCn·nowCn null을 "-"로 바꿈 */
export function withNormalizedVerificationResult<T extends object>(item: T): T {
if (!("verificationResult" in item) || item.verificationResult == null) {
return item;
}
const verificationResult = normalizeVerificationResultMap(
item.verificationResult as VerificationResultLikeMap,
);
if (!verificationResult) return item;
return { ...item, verificationResult };
}
/** 검증 오류 배열 → RealGrid styleName */ /** 검증 오류 배열 → RealGrid styleName */
export function getVerificationStyleName( export function getVerificationStyleName(
errors: VerificationResultLikeItem[] | null | undefined, errors: VerificationResultLikeItem[] | null | undefined,
@@ -37,8 +80,8 @@ export function formatVerificationTooltip(
: e.vrfcCd === "NV" : e.vrfcCd === "NV"
? "일반검증 - " ? "일반검증 - "
: "모집단 검증 - "; : "모집단 검증 - ";
const comp = e.cmprCn ?? e.compVlCn ?? ""; const comp = displayVerificationCn(e.cmprCn ?? e.compVlCn);
const now = e.nowCn ?? e.nowVlCn ?? ""; const now = displayVerificationCn(e.nowCn ?? e.nowVlCn);
return `${prefix}${e.rsnExpln}\n(검증 기준값: ${comp} / 현재 입력값: ${now})`; return `${prefix}${e.rsnExpln}\n(검증 기준값: ${comp} / 현재 입력값: ${now})`;
}) })
.filter(Boolean) .filter(Boolean)
@@ -56,10 +56,11 @@ export class GeneralverificationApiService implements GeneralverificationService
} }
public async UpdateVrfcMaster( public async UpdateVrfcMaster(
vrfcSn: number,
param: UpdateVrfcMasterRequest, param: UpdateVrfcMasterRequest,
): Promise<UpdateVrfcMasterResponse> { ): Promise<UpdateVrfcMasterResponse> {
const response = await stClient.put<UpdateVrfcMasterResponse>( const response = await stClient.put<UpdateVrfcMasterResponse>(
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters/${param.vrfcSn}`, `${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters/${vrfcSn}`,
param, param,
); );
return response.data; return response.data;
@@ -127,20 +128,22 @@ export class GeneralverificationApiService implements GeneralverificationService
} }
public async RegistVrfcDetail( public async RegistVrfcDetail(
vrfcSn: number,
param: VerifyDetailRegistRequest, param: VerifyDetailRegistRequest,
): Promise<RegistVrfcMasterResponse> { ): Promise<RegistVrfcMasterResponse> {
const response = await stClient.post<RegistVrfcMasterResponse>( const response = await stClient.post<RegistVrfcMasterResponse>(
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/${param.vrfcSn}/details`, `${ENDPOINT.ST_SERVICE.INPUTVERIFY}/${vrfcSn}/details`,
param, param,
); );
return response.data; return response.data;
} }
public async UpdateVrfcDetail( public async UpdateVrfcDetail(
vrfcSn: number,
param: VerifyDetailUpdateRequest, param: VerifyDetailUpdateRequest,
): Promise<RegistVrfcMasterResponse> { ): Promise<RegistVrfcMasterResponse> {
const response = await stClient.put<RegistVrfcMasterResponse>( const response = await stClient.put<RegistVrfcMasterResponse>(
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/${param.vrfcSn}/details`, `${ENDPOINT.ST_SERVICE.INPUTVERIFY}/${vrfcSn}/details`,
param, param,
); );
return response.data; return response.data;
@@ -16,6 +16,8 @@ import {
type ImrStatusResponse, type ImrStatusResponse,
type ReviewerInfoRequest, type ReviewerInfoRequest,
type ReviewerInfoResponse, type ReviewerInfoResponse,
type rollbackStatusRequest,
type rollbackStatusResponse,
type ReviewInputSaveRequest, type ReviewInputSaveRequest,
type ReviewOpinionSaveRequest, type ReviewOpinionSaveRequest,
type ReviewOpinionSaveResponse, type ReviewOpinionSaveResponse,
@@ -156,6 +158,17 @@ export class StatisticsApiService implements StatisticsService {
return response.data; return response.data;
} }
// 입력 - 검증 이전 상태로 롤백
public async rollbackStatus(
param: rollbackStatusRequest,
): Promise<rollbackStatusResponse> {
const response = await stClient.put<rollbackStatusResponse>(
`${ENDPOINT.ST_SERVICE.INPUTCOMMON}/rollback-status`,
param,
);
return response.data;
}
public async callImrService(param: ImrRequest): Promise<ImrResponse> { public async callImrService(param: ImrRequest): Promise<ImrResponse> {
const response = await client.post<ImrResponse>( const response = await client.post<ImrResponse>(
`${ENDPOINT.STATVERIFY_SERVICE.IMR}`, `${ENDPOINT.STATVERIFY_SERVICE.IMR}`,
@@ -46,7 +46,6 @@ export interface CheckVerificationNameResponse {
} }
export interface UpdateVrfcMasterRequest { export interface UpdateVrfcMasterRequest {
vrfcSn?: number | null;
vrfcNm?: string | null; vrfcNm?: string | null;
vrfcClsfCd?: string | null; vrfcClsfCd?: string | null;
dcptDgt?: number | null; dcptDgt?: number | null;
@@ -184,13 +183,11 @@ export interface VerifyDetailRegistData {
} }
export interface VerifyDetailRegistRequest { export interface VerifyDetailRegistRequest {
vrfcSn: number | null;
detailList: VerifyDetailRegistData[]; detailList: VerifyDetailRegistData[];
rgtrUuid: string; rgtrUuid: string;
} }
export interface VerifyDetailUpdateRequest { export interface VerifyDetailUpdateRequest {
vrfcSn: number | null;
detailList: VerifyDetailRegistData[]; detailList: VerifyDetailRegistData[];
mdfrUuid: string; mdfrUuid: string;
} }
@@ -297,6 +294,7 @@ export interface GeneralverificationService {
param: CheckVerificationNameRequest, param: CheckVerificationNameRequest,
): Promise<CheckVerificationNameResponse>; ): Promise<CheckVerificationNameResponse>;
UpdateVrfcMaster( UpdateVrfcMaster(
vrfcSn: number,
param: UpdateVrfcMasterRequest, param: UpdateVrfcMasterRequest,
): Promise<UpdateVrfcMasterResponse>; ): Promise<UpdateVrfcMasterResponse>;
RegistVrfcMaster( RegistVrfcMaster(
@@ -315,9 +313,11 @@ export interface GeneralverificationService {
param: string, param: string,
): Promise<VerifyColumnListResponse>; ): Promise<VerifyColumnListResponse>;
RegistVrfcDetail( RegistVrfcDetail(
vrfcSn: number,
param: VerifyDetailRegistRequest, param: VerifyDetailRegistRequest,
): Promise<RegistVrfcMasterResponse>; ): Promise<RegistVrfcMasterResponse>;
UpdateVrfcDetail( UpdateVrfcDetail(
vrfcSn: number,
param: VerifyDetailUpdateRequest, param: VerifyDetailUpdateRequest,
): Promise<RegistVrfcMasterResponse>; ): Promise<RegistVrfcMasterResponse>;
CopyVrfcData( CopyVrfcData(
@@ -437,7 +437,6 @@ export interface ExcretaSlurgeProcessingStatusItem {
rcycQnt: number; rcycQnt: number;
olandLfvlm: number; olandLfvlm: number;
incnrQnt: number; incnrQnt: number;
oceanInputQnt: number;
fuelQnt: number; fuelQnt: number;
etcQnt: number; etcQnt: number;
unprcsQnt: number; unprcsQnt: number;
@@ -81,7 +81,6 @@ export interface ReportStatusResponseDto {
lastCfmtnPicTelnoCn?: string | null; lastCfmtnPicTelnoCn?: string | null;
lastCfmtnPicDeptNm?: string | null; lastCfmtnPicDeptNm?: string | null;
lastCfmtnPicJbgdNm?: string | null; lastCfmtnPicJbgdNm?: string | null;
splmntRsltCn?: string | null;
splmntOpnnCn?: string | null; splmntOpnnCn?: string | null;
rjctOpnnCn?: string | null; rjctOpnnCn?: string | null;
} }
@@ -308,7 +308,6 @@ export interface SeweragePipeInputPipeTypeStatusSaveItem {
rmrk: string | null; rmrk: string | null;
lyngPrlgWhol: number; lyngPrlgWhol: number;
dmltnPrlgWhol: number; dmltnPrlgWhol: number;
pipeByPrstWhol: number;
} }
/** 관종별 현황 저장 API 요청 */ /** 관종별 현황 저장 API 요청 */
@@ -420,6 +419,10 @@ export interface SeweragePipeInputManholeStatusItem {
folvlMnhlCnt: number; folvlMnhlCnt: number;
filvlMnhlCnt: number; filvlMnhlCnt: number;
rmrk: string; rmrk: string;
wholMnhlCntSum: number;
frlvlMnhlCntSum: number;
thlvlMnhlCntSum: number;
picNm: string | null;
verificationResult?: SeweragePipeInputVerificationResult; verificationResult?: SeweragePipeInputVerificationResult;
} }
@@ -9,12 +9,12 @@ export interface StatsInputStatusReviewItem {
sewerBzmnCd?: string; sewerBzmnCd?: string;
tabNm?: string; tabNm?: string;
statsCd?: string; statsCd?: string;
submitStatusNm?: string; lclgvPicNm?: string;
prvnStatusNm?: string; lclgvPicTelnoCn?: string;
chargerNm?: string; lclgvSbmsnSttsCd?: string;
chargerCttpc?: string; lclgvSbmsnSttsNm?: string;
submitStatusCd?: string; mctpvPicSbmsnSttsCd?: string;
prvnStatusCd?: string; mctpvPicSbmsnSttsNm?: string;
} }
export interface StatsInputStatusReviewResponseData { export interface StatsInputStatusReviewResponseData {
@@ -37,7 +37,7 @@ export interface ReviewHistoryResponse {
status: string; status: string;
message?: string; message?: string;
data: { data: {
logDt: string; regDt: string;
historyContent: string; historyContent: string;
}[] }[]
} }
@@ -31,6 +31,21 @@ export interface cancelSubmitResponse {
message?: string; message?: string;
} }
/** 검증 이전 상태로 롤백 요청 */
export interface rollbackStatusRequest {
statsYr: string;
statsCd: string;
sewerBzmnCd: string;
rollbackStatusCode: string;
mdfrUuid: string;
}
/** 검증 이전 상태로 롤백 응답 */
export interface rollbackStatusResponse {
status: string;
message?: string;
}
export interface ApiResponse<T> { export interface ApiResponse<T> {
status: string; status: string;
data?: T; data?: T;
@@ -327,7 +342,6 @@ export interface ReviewOpinionDetailItem {
sewerBzmnCd: string; sewerBzmnCd: string;
statsCd: string; statsCd: string;
splmntOpnnCn: string | null; splmntOpnnCn: string | null;
splmntRsltCn: string | null;
mdfrUuid: string | null; mdfrUuid: string | null;
} }
@@ -343,7 +357,6 @@ export interface ReviewOpinionSaveRequest {
sewerBzmnCd: string; sewerBzmnCd: string;
statsCd: string; statsCd: string;
splmntOpnnCn: string; splmntOpnnCn: string;
splmntRsltCn: string;
mdfrUuid: string; mdfrUuid: string;
} }
@@ -388,7 +401,6 @@ export interface ReviewSubmitRequest {
/** 통계항목 단위 제출 시 사용 (통계 입력 현황 일괄 제출에는 미사용) */ /** 통계항목 단위 제출 시 사용 (통계 입력 현황 일괄 제출에는 미사용) */
statsCd?: string; statsCd?: string;
splmntOpnnCn?: string; splmntOpnnCn?: string;
splmntRsltCn?: string;
} }
export interface ReviewSubmitResponse { export interface ReviewSubmitResponse {
@@ -454,7 +466,6 @@ export interface ReviewerInfoResponse {
dpmNm: string; dpmNm: string;
cps: string; cps: string;
splmntOpnnCn: string; splmntOpnnCn: string;
splmntRsltCn: string;
} }
} }
@@ -478,9 +489,8 @@ export interface StatiscicsManagementReviewHistoryItem {
ctpvNm: string; ctpvNm: string;
sggNm: string; sggNm: string;
menuNm: string; menuNm: string;
wrterOpinionSm: string | null; splmntOpnnCn: string | null;
chckerOpinionSm: string | null; rjctOpnnCn: string | null;
returnOpinionSm: string | null;
} }
export interface StatiscicsManagementReviewHistoryResponse { export interface StatiscicsManagementReviewHistoryResponse {
@@ -557,6 +567,7 @@ export interface StatisticsService {
saveStatsInputPeriod(param: StatsInputPeriodSaveRequest): Promise<StatsInputPeriodSaveApiResponse>; saveStatsInputPeriod(param: StatsInputPeriodSaveRequest): Promise<StatsInputPeriodSaveApiResponse>;
deleteStatsInputPeriod(param: StatsInputPeriodDeleteRequest): Promise<StatsInputPeriodDeleteApiResponse>; deleteStatsInputPeriod(param: StatsInputPeriodDeleteRequest): Promise<StatsInputPeriodDeleteApiResponse>;
cancelSubmit(param: cancelSubmitRequest): Promise<cancelSubmitResponse>; cancelSubmit(param: cancelSubmitRequest): Promise<cancelSubmitResponse>;
rollbackStatus(param: rollbackStatusRequest): Promise<rollbackStatusResponse>;
callImrService(param: ImrRequest): Promise<ImrResponse>; callImrService(param: ImrRequest): Promise<ImrResponse>;
submitException(param: SubmitExceptionRequest): Promise<SubmitExceptionResponse>; submitException(param: SubmitExceptionRequest): Promise<SubmitExceptionResponse>;
getLogList(param: StatisticsLogRequest): Promise<StatisticsLogResponse>; getLogList(param: StatisticsLogRequest): Promise<StatisticsLogResponse>;
@@ -127,7 +127,6 @@ export interface HumanWasteSludgeReviewItem {
rcycQnt: number | null; rcycQnt: number | null;
olandLfvlm: number | null; olandLfvlm: number | null;
incnrQnt: number | null; incnrQnt: number | null;
oceanInputQnt: number | null;
fuelQnt: number | null; fuelQnt: number | null;
etcQnt: number | null; etcQnt: number | null;
unprcsQnt: number | null; unprcsQnt: number | null;
@@ -218,7 +217,6 @@ export function mapSewageExcretaSlurgeReviewRows(list: unknown[]): object[] {
rcycQnt: row.rcycQnt ?? 0, rcycQnt: row.rcycQnt ?? 0,
olandLfvlm: row.olandLfvlm ?? 0, olandLfvlm: row.olandLfvlm ?? 0,
incnrQnt: row.incnrQnt ?? 0, incnrQnt: row.incnrQnt ?? 0,
oceanInputQnt: row.oceanInputQnt ?? 0,
fuelQnt: row.fuelQnt ?? 0, fuelQnt: row.fuelQnt ?? 0,
etcQnt: row.etcQnt ?? 0, etcQnt: row.etcQnt ?? 0,
unprcsQnt: row.unprcsQnt ?? 0, unprcsQnt: row.unprcsQnt ?? 0,
@@ -108,5 +108,4 @@ export interface StatsStatusInfo {
mctpvPicSbmsnSttsCd?: string; mctpvPicSbmsnSttsCd?: string;
rjctOpnnCn?: string; rjctOpnnCn?: string;
splmntOpnnCn?: string; splmntOpnnCn?: string;
splmntRsltCn?: string;
} }
@@ -247,6 +247,10 @@ export interface SewagePipeReviewManholeItem {
folvlMnhlCnt: number; folvlMnhlCnt: number;
filvlMnhlCnt: number; filvlMnhlCnt: number;
rmrk: string | null; rmrk: string | null;
wholMnhlCntSum: number;
frlvlMnhlCntSum: number;
thlvlMnhlCntSum: number;
picNm: string | null;
} }
export interface SewagePipeManholeResponseData { export interface SewagePipeManholeResponseData {
@@ -266,5 +270,4 @@ export interface StatsStatusInfo {
mctpvPicSbmsnSttsCd?: string; mctpvPicSbmsnSttsCd?: string;
rjctOpnnCn?: string; rjctOpnnCn?: string;
splmntOpnnCn?: string; splmntOpnnCn?: string;
splmntRsltCn?: string;
} }
@@ -59,7 +59,6 @@ export interface statsStatusInfo {
mctpvPicSbmsnSttsCd?: string; mctpvPicSbmsnSttsCd?: string;
rjctOpnnCn?: string; rjctOpnnCn?: string;
splmntOpnnCn?: string; splmntOpnnCn?: string;
splmntRsltCn?: string;
} }
export interface SewerageSupplyRateReviewResponseData { export interface SewerageSupplyRateReviewResponseData {
@@ -168,6 +168,10 @@ export interface FcltyManholeSummaryItem {
thlvlMnhlCnt: number; thlvlMnhlCnt: number;
folvlMnhlCnt: number; folvlMnhlCnt: number;
filvlMnhlCnt: number; filvlMnhlCnt: number;
wholMnhlCntSum: number;
frlvlMnhlCntSum: number;
thlvlMnhlCntSum: number;
picNm: string | null;
} }
/** /**
@@ -135,7 +135,6 @@ export interface HumanWasteSludgeStatusTotalItem {
rcycQnt: number; rcycQnt: number;
olandLfvlm: number; olandLfvlm: number;
incnrQnt: number; incnrQnt: number;
oceanInputQnt: number;
fuelQnt: number; fuelQnt: number;
etcQnt: number; etcQnt: number;
unprcsQnt: number; unprcsQnt: number;
@@ -1,5 +1,7 @@
export const STATISTICS_ROUTE = "/statistics"; export const STATISTICS_ROUTE = "/statistics";
export const STATISTICS_TAB_QUERY_KEY = "tab"; export const STATISTICS_TAB_QUERY_KEY = "tab";
/** 기본 화면(대시보드) 도움말 매칭용. URL에는 넣지 않음 */
export const STATISTICS_DASHBOARD_TAB_ID = "Dashboard";
export function buildStatisticsTabUrl(tabId: string): string { export function buildStatisticsTabUrl(tabId: string): string {
return `${STATISTICS_ROUTE}?${STATISTICS_TAB_QUERY_KEY}=${encodeURIComponent(tabId)}`; return `${STATISTICS_ROUTE}?${STATISTICS_TAB_QUERY_KEY}=${encodeURIComponent(tabId)}`;
@@ -1,13 +1,20 @@
import { PageTitle } from "@common/components"; import { PageTitle } from "@common/components";
import { findMenuItemByUrlPath } from "@/shared/lib/stats-cd-input-navigation";
import { STATISTICS_DASHBOARD_TAB_ID } from "@/shared/lib/statistics-tab-url";
import { TabBar } from "./tab-bar"; import { TabBar } from "./tab-bar";
import { useTabStore } from "@/store/tab-store"; import { useTabStore } from "@/store/tab-store";
function StatisticsPageLayout({ children }: { children: React.ReactNode }) { function StatisticsPageLayout({ children }: { children: React.ReactNode }) {
const { activeTabId, tabs } = useTabStore(); const { activeTabId, tabs, menuList } = useTabStore();
const pageTitle = tabs.find((t) => t.id === activeTabId); const pageTitle = tabs.find((t) => t.id === activeTabId);
const dashboardMenu =
!pageTitle && menuList
? findMenuItemByUrlPath(menuList, STATISTICS_DASHBOARD_TAB_ID)
: null;
const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim()); const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim());
@@ -16,7 +23,7 @@ function StatisticsPageLayout({ children }: { children: React.ReactNode }) {
<TabBar /> <TabBar />
<PageTitle <PageTitle
title={pageTitle?.label ?? ""} title={pageTitle?.label ?? ""}
menuCd={pageTitle?.menuItem?.menuCd} menuCd={pageTitle?.menuItem?.menuCd ?? dashboardMenu?.menuCd}
menuPaths={menuPaths ?? []} menuPaths={menuPaths ?? []}
/> />
{children} {children}
+1 -1
View File
@@ -50,7 +50,7 @@
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
"husky": "^9.1.7", "husky": "^9.1.7",
"lint-staged": "^16.2.7", "lint-staged": "^16.2.7",
"turbo": "2.4.2" "turbo": "2.11.10"
}, },
"pnpm": { "pnpm": {
"overrides": { "overrides": {
+221 -207
View File
@@ -60,8 +60,8 @@ importers:
specifier: ^16.2.7 specifier: ^16.2.7
version: 16.4.0 version: 16.4.0
turbo: turbo:
specifier: 2.4.2 specifier: 2.11.10
version: 2.4.2 version: 2.11.10
apps/_template: apps/_template:
dependencies: dependencies:
@@ -104,10 +104,10 @@ importers:
devDependencies: devDependencies:
eslint: eslint:
specifier: ^9.0.0 specifier: ^9.0.0
version: 9.39.4(jiti@1.21.7) version: 9.39.4(jiti@2.6.1)
eslint-config-next: eslint-config-next:
specifier: 15.3.8 specifier: 15.3.8
version: 15.3.8(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) version: 15.3.8(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
postcss: postcss:
specifier: ^8.4.49 specifier: ^8.4.49
version: 8.5.8 version: 8.5.8
@@ -1839,7 +1839,7 @@ importers:
version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3) version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)
'@storybook/react-vite': '@storybook/react-vite':
specifier: ^8.5.3 specifier: ^8.5.3
version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
'@storybook/test': '@storybook/test':
specifier: ^8.5.3 specifier: ^8.5.3
version: 8.6.15(storybook@8.6.18(prettier@3.8.1)) version: 8.6.15(storybook@8.6.18(prettier@3.8.1))
@@ -1851,22 +1851,22 @@ importers:
version: 22.19.15 version: 22.19.15
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^4.3.4 specifier: ^4.3.4
version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) version: 4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
autoprefixer: autoprefixer:
specifier: ^10.4.20 specifier: ^10.4.20
version: 10.4.27(postcss@8.5.8) version: 10.4.27(postcss@8.5.8)
eslint: eslint:
specifier: ^9.17.0 specifier: ^9.17.0
version: 9.39.4(jiti@2.6.1) version: 9.39.4(jiti@1.21.7)
eslint-plugin-react-hooks: eslint-plugin-react-hooks:
specifier: ^5.0.0 specifier: ^5.0.0
version: 5.2.0(eslint@9.39.4(jiti@2.6.1)) version: 5.2.0(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-react-refresh: eslint-plugin-react-refresh:
specifier: ^0.4.16 specifier: ^0.4.16
version: 0.4.26(eslint@9.39.4(jiti@2.6.1)) version: 0.4.26(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-storybook: eslint-plugin-storybook:
specifier: ^0.11.2 specifier: ^0.11.2
version: 0.11.6(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) version: 0.11.6(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
globals: globals:
specifier: ^15.14.0 specifier: ^15.14.0
version: 15.15.0 version: 15.15.0
@@ -1887,19 +1887,19 @@ importers:
version: 3.4.19(yaml@2.8.3) version: 3.4.19(yaml@2.8.3)
tsup: tsup:
specifier: 8.3.6 specifier: 8.3.6
version: 8.3.6(jiti@2.6.1)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3) version: 8.3.6(jiti@1.21.7)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3)
typescript: typescript:
specifier: ~5.6.2 specifier: ~5.6.2
version: 5.6.3 version: 5.6.3
typescript-eslint: typescript-eslint:
specifier: ^8.18.2 specifier: ^8.18.2
version: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) version: 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
vite: vite:
specifier: ^6.0.5 specifier: ^6.0.5
version: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3) version: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
vite-tsconfig-paths: vite-tsconfig-paths:
specifier: 5.1.4 specifier: 5.1.4
version: 5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) version: 5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
packages/common/config: packages/common/config:
devDependencies: devDependencies:
@@ -4100,6 +4100,36 @@ packages:
react: ^19.2.1 react: ^19.2.1
react-dom: ^19.2.1 react-dom: ^19.2.1
'@turbo/darwin-64@2.11.10':
resolution: {integrity: sha512-By4idRap5+nLnMuRzLB4qkOPRlvNdyY1ne4VJYDyUoUB11H94k7uif9mbe3JT8JSNXs1D68uMcBj6hJ/jMQRvA==}
cpu: [x64]
os: [darwin]
'@turbo/darwin-arm64@2.11.10':
resolution: {integrity: sha512-pyEYlVcuexOPa92p0Wlwl9YT1Is5D60lxN3ItWm3g30YLvFaUq86TF4BBWg5ZAc0uMTnrOzCvuCsOBTdzUWnRQ==}
cpu: [arm64]
os: [darwin]
'@turbo/linux-64@2.11.10':
resolution: {integrity: sha512-1tYeR/IDZ5HEdsb0jNq2L2xam5nMQ+g80tlV2BZmv4OFw+pMcUM0mMmUcfc5wXPPNHVNPuDMjh9Y8G8HgXPLZA==}
cpu: [x64]
os: [android, linux]
'@turbo/linux-arm64@2.11.10':
resolution: {integrity: sha512-HuekQxvVGhUd46g1Im/DKdOtglHr4/gguZAvzEpPUgtxNkztSa8lWhQEGQ+EmPQ0n7w19qjThFU+OfEEd0uvlw==}
cpu: [arm64]
os: [android, linux]
'@turbo/windows-64@2.11.10':
resolution: {integrity: sha512-UJOP3BkbreY3/JlMgJR6ZiimxYIBn+c+B4tnBIxD0E9c3Estmk+XoVNVBNBottZLNRXe3/ScgOU4+/k8tIWysg==}
cpu: [x64]
os: [win32]
'@turbo/windows-arm64@2.11.10':
resolution: {integrity: sha512-xOkEjF3ws/b/YNlc+bvJHMYBn+vL+QbEISZFVi0qS+ImmhA1X3/gmNmBrjjIG3dg6aeN+n6gQitzSkXQ286qJQ==}
cpu: [arm64]
os: [win32]
'@tybys/wasm-util@0.10.1': '@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
@@ -7387,38 +7417,8 @@ packages:
typescript: typescript:
optional: true optional: true
turbo-darwin-64@2.4.2: turbo@2.11.10:
resolution: {integrity: sha512-HFfemyWB60CJtEvVQj9yby5rkkWw9fLAdLtAPGtPQoU3tKh8t/uzCAZKso2aPVbib9vGUuGbPGoGpaRXdVhj5g==} resolution: {integrity: sha512-3GJYwig8ygEI89oaOZdduJX8/aw6O9eRPYHoIt6T3FZl9hkKjiyIspufJoVgqXihPoJu8M5CSV0DlZvzfohBCw==}
cpu: [x64]
os: [darwin]
turbo-darwin-arm64@2.4.2:
resolution: {integrity: sha512-uwSx1dsBSSFeEC0nxyx2O219FEsS/haiESaWwE9JI8mHkQK61s6w6fN2G586krKxyNam4AIxRltleL+O2Em94g==}
cpu: [arm64]
os: [darwin]
turbo-linux-64@2.4.2:
resolution: {integrity: sha512-Fy/uL8z/LAYcPbm7a1LwFnTY9pIi5FAi12iuHsgB7zHjdh4eeIKS2NIg4nroAmTcUTUZ0/cVTo4bDOCUcS3aKw==}
cpu: [x64]
os: [linux]
turbo-linux-arm64@2.4.2:
resolution: {integrity: sha512-AEA0d8h5W/K6iiXfEgiNwWt0yqRL1NpBs8zQCLdc4/L7WeYeJW3sORWX8zt7xhutF/KW9gTm8ehKpiK6cCIsAA==}
cpu: [arm64]
os: [linux]
turbo-windows-64@2.4.2:
resolution: {integrity: sha512-CybtIZ9wRgnnNFVN9En9G+rxsO+mwU81fvW4RpE8BWyNEkhQ8J28qYf4PaimueMxGHHp/28i/G7Kcdn2GAWG0g==}
cpu: [x64]
os: [win32]
turbo-windows-arm64@2.4.2:
resolution: {integrity: sha512-7V0yneVPL8Y3TgrkUIjw7Odmwu1tHnyIiPHFM7eFcA7U+H6hPXyCxge7nC3wOKfjhKCQqUm+Vf/k6kjmLz5G4g==}
cpu: [arm64]
os: [win32]
turbo@2.4.2:
resolution: {integrity: sha512-Qxi0ioQCxMRUCcHKHZkTnYH8e7XCpNfg9QiJcyfWIc+ZXeaCjzV5rCGlbQlTXMAtI8qgfP8fZADv3CFtPwqdPQ==}
hasBin: true hasBin: true
tus-js-client@4.3.1: tus-js-client@4.3.1:
@@ -8590,6 +8590,15 @@ snapshots:
wrap-ansi: 8.1.0 wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0 wrap-ansi-cjs: wrap-ansi@7.0.0
'@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies:
glob: 10.5.0
magic-string: 0.27.0
react-docgen-typescript: 2.4.0(typescript@5.6.3)
vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
optionalDependencies:
typescript: 5.6.3
'@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies: dependencies:
glob: 10.5.0 glob: 10.5.0
@@ -9492,6 +9501,14 @@ snapshots:
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
'@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies:
'@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.1))
browser-assert: 1.2.1
storybook: 8.6.18(prettier@3.8.1)
ts-dedent: 2.2.0
vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
'@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': '@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies: dependencies:
'@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.1)) '@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.1))
@@ -9582,6 +9599,28 @@ snapshots:
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
storybook: 8.6.18(prettier@3.8.1) storybook: 8.6.18(prettier@3.8.1)
'@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies:
'@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
'@rollup/pluginutils': 5.3.0(rollup@4.60.0)
'@storybook/builder-vite': 8.6.18(storybook@8.6.18(prettier@3.8.1))(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
'@storybook/react': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)
find-up: 5.0.0
magic-string: 0.30.21
react: 19.2.4
react-docgen: 7.1.1
react-dom: 19.2.4(react@19.2.4)
resolve: 1.22.11
storybook: 8.6.18(prettier@3.8.1)
tsconfig-paths: 4.2.0
vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
optionalDependencies:
'@storybook/test': 8.6.15(storybook@8.6.18(prettier@3.8.1))
transitivePeerDependencies:
- rollup
- supports-color
- typescript
'@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': '@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.1)))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@8.6.18(prettier@3.8.1))(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies: dependencies:
'@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)) '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))
@@ -9778,6 +9817,24 @@ snapshots:
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
tinymce: 7.9.2 tinymce: 7.9.2
'@turbo/darwin-64@2.11.10':
optional: true
'@turbo/darwin-arm64@2.11.10':
optional: true
'@turbo/linux-64@2.11.10':
optional: true
'@turbo/linux-arm64@2.11.10':
optional: true
'@turbo/windows-64@2.11.10':
optional: true
'@turbo/windows-arm64@2.11.10':
optional: true
'@tybys/wasm-util@0.10.1': '@tybys/wasm-util@0.10.1':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@@ -9893,26 +9950,26 @@ snapshots:
dependencies: dependencies:
xlsx: 0.18.5 xlsx: 0.18.5
'@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
'@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/scope-manager': 8.57.2
'@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
'@typescript-eslint/visitor-keys': 8.57.2 '@typescript-eslint/visitor-keys': 8.57.2
eslint: 9.39.4(jiti@1.21.7) eslint: 9.39.4(jiti@1.21.7)
ignore: 7.0.5 ignore: 7.0.5
natural-compare: 1.4.0 natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.6.3)
typescript: 5.9.3 typescript: 5.6.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)': '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/scope-manager': 8.57.2
'@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)
@@ -9941,15 +9998,15 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': '@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/scope-manager': 8.57.2
'@typescript-eslint/types': 8.57.2 '@typescript-eslint/types': 8.57.2
'@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3)
'@typescript-eslint/visitor-keys': 8.57.2 '@typescript-eslint/visitor-keys': 8.57.2
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.4(jiti@1.21.7) eslint: 9.39.4(jiti@1.21.7)
typescript: 5.9.3 typescript: 5.6.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -10008,15 +10065,15 @@ snapshots:
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
'@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': '@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)':
dependencies: dependencies:
'@typescript-eslint/types': 8.57.2 '@typescript-eslint/types': 8.57.2
'@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3)
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.4(jiti@1.21.7) eslint: 9.39.4(jiti@1.21.7)
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.6.3)
typescript: 5.9.3 typescript: 5.6.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -10076,14 +10133,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)': '@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7)) '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7))
'@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/scope-manager': 8.57.2
'@typescript-eslint/types': 8.57.2 '@typescript-eslint/types': 8.57.2
'@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3)
eslint: 9.39.4(jiti@1.21.7) eslint: 9.39.4(jiti@1.21.7)
typescript: 5.9.3 typescript: 5.6.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -10173,6 +10230,18 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1': '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true optional: true
'@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0)
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))': '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3))':
dependencies: dependencies:
'@babel/core': 7.29.0 '@babel/core': 7.29.0
@@ -11219,26 +11288,6 @@ snapshots:
optionalDependencies: optionalDependencies:
source-map: 0.7.6 source-map: 0.7.6
eslint-config-next@15.3.8(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3):
dependencies:
'@next/eslint-plugin-next': 15.3.8
'@rushstack/eslint-patch': 1.16.1
'@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)
eslint: 9.39.4(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@1.21.7))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.4(jiti@1.21.7))
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
- eslint-import-resolver-webpack
- eslint-plugin-import-x
- supports-color
eslint-config-next@15.3.8(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): eslint-config-next@15.3.8(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
dependencies: dependencies:
'@next/eslint-plugin-next': 15.3.8 '@next/eslint-plugin-next': 15.3.8
@@ -11267,21 +11316,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
eslint: 9.39.4(jiti@1.21.7)
get-tsconfig: 4.13.7
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)): eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
'@nolyfill/is-core-module': 1.0.39 '@nolyfill/is-core-module': 1.0.39
@@ -11297,17 +11331,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@1.21.7)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)
eslint: 9.39.4(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@1.21.7))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
@@ -11319,35 +11342,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
array.prototype.findlastindex: 1.2.6
array.prototype.flat: 1.3.3
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
eslint: 9.39.4(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@1.21.7))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
minimatch: 3.1.5
object.fromentries: 2.0.8
object.groupby: 1.0.3
object.values: 1.2.1
semver: 6.3.1
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
'@rtsao/scc': 1.1.0 '@rtsao/scc': 1.1.0
@@ -11377,25 +11371,6 @@ snapshots:
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@1.21.7)):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.9
array.prototype.flatmap: 1.3.3
ast-types-flow: 0.0.8
axe-core: 4.11.1
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
eslint: 9.39.4(jiti@1.21.7)
hasown: 2.0.2
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
minimatch: 3.1.5
object.fromentries: 2.0.8
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
aria-query: 5.3.2 aria-query: 5.3.2
@@ -11423,32 +11398,14 @@ snapshots:
dependencies: dependencies:
eslint: 9.39.4(jiti@2.6.1) eslint: 9.39.4(jiti@2.6.1)
eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@1.21.7)):
dependencies:
eslint: 9.39.4(jiti@1.21.7)
eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.6.1)): eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
eslint: 9.39.4(jiti@2.6.1) eslint: 9.39.4(jiti@2.6.1)
eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@1.21.7)):
dependencies:
array-includes: 3.1.9
array.prototype.findlast: 1.2.5
array.prototype.flatmap: 1.3.3
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.3.1
eslint: 9.39.4(jiti@1.21.7)
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
minimatch: 3.1.5
object.entries: 1.1.9
object.fromentries: 2.0.8
object.values: 1.2.1
prop-types: 15.8.1
resolve: 2.0.0-next.6
semver: 6.3.1
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)):
dependencies: dependencies:
array-includes: 3.1.9 array-includes: 3.1.9
@@ -11475,6 +11432,16 @@ snapshots:
dependencies: dependencies:
eslint: 9.39.4(jiti@2.6.1) eslint: 9.39.4(jiti@2.6.1)
eslint-plugin-storybook@0.11.6(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3):
dependencies:
'@storybook/csf': 0.1.13
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
eslint: 9.39.4(jiti@1.21.7)
ts-dedent: 2.2.0
transitivePeerDependencies:
- supports-color
- typescript
eslint-plugin-storybook@0.11.6(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3): eslint-plugin-storybook@0.11.6(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3):
dependencies: dependencies:
'@storybook/csf': 0.1.13 '@storybook/csf': 0.1.13
@@ -13584,6 +13551,33 @@ snapshots:
tslib@2.8.1: {} tslib@2.8.1: {}
tsup@8.3.6(jiti@1.21.7)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3):
dependencies:
bundle-require: 5.1.0(esbuild@0.24.2)
cac: 6.7.14
chokidar: 4.0.3
consola: 3.4.2
debug: 4.4.3
esbuild: 0.24.2
joycon: 3.1.1
picocolors: 1.1.1
postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.8)(yaml@2.8.3)
resolve-from: 5.0.0
rollup: 4.60.0
source-map: 0.7.6
sucrase: 3.35.1
tinyexec: 0.3.2
tinyglobby: 0.2.15
tree-kill: 1.2.2
optionalDependencies:
postcss: 8.5.8
typescript: 5.6.3
transitivePeerDependencies:
- jiti
- supports-color
- tsx
- yaml
tsup@8.3.6(jiti@2.6.1)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3): tsup@8.3.6(jiti@2.6.1)(postcss@8.5.8)(typescript@5.6.3)(yaml@2.8.3):
dependencies: dependencies:
bundle-require: 5.1.0(esbuild@0.24.2) bundle-require: 5.1.0(esbuild@0.24.2)
@@ -13638,32 +13632,14 @@ snapshots:
- tsx - tsx
- yaml - yaml
turbo-darwin-64@2.4.2: turbo@2.11.10:
optional: true
turbo-darwin-arm64@2.4.2:
optional: true
turbo-linux-64@2.4.2:
optional: true
turbo-linux-arm64@2.4.2:
optional: true
turbo-windows-64@2.4.2:
optional: true
turbo-windows-arm64@2.4.2:
optional: true
turbo@2.4.2:
optionalDependencies: optionalDependencies:
turbo-darwin-64: 2.4.2 '@turbo/darwin-64': 2.11.10
turbo-darwin-arm64: 2.4.2 '@turbo/darwin-arm64': 2.11.10
turbo-linux-64: 2.4.2 '@turbo/linux-64': 2.11.10
turbo-linux-arm64: 2.4.2 '@turbo/linux-arm64': 2.11.10
turbo-windows-64: 2.4.2 '@turbo/windows-64': 2.11.10
turbo-windows-arm64: 2.4.2 '@turbo/windows-arm64': 2.11.10
tus-js-client@4.3.1: tus-js-client@4.3.1:
dependencies: dependencies:
@@ -13714,9 +13690,20 @@ snapshots:
possible-typed-array-names: 1.1.0 possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10 reflect.getprototypeof: 1.0.10
typescript-eslint@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
'@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3)
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@1.21.7))(typescript@5.6.3)
eslint: 9.39.4(jiti@1.21.7)
typescript: 5.6.3
transitivePeerDependencies:
- supports-color
typescript-eslint@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3): typescript-eslint@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3):
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)
'@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)
'@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3) '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.6.3)
'@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3) '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)
@@ -13850,6 +13837,17 @@ snapshots:
d3-time: 3.1.0 d3-time: 3.1.0
d3-timer: 3.0.1 d3-timer: 3.0.1
vite-tsconfig-paths@5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)):
dependencies:
debug: 4.4.3
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.6.3)
optionalDependencies:
vite: 6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)
transitivePeerDependencies:
- supports-color
- typescript
vite-tsconfig-paths@5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)): vite-tsconfig-paths@5.1.4(typescript@5.6.3)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3)):
dependencies: dependencies:
debug: 4.4.3 debug: 4.4.3
@@ -13872,6 +13870,22 @@ snapshots:
lightningcss: 1.32.0 lightningcss: 1.32.0
terser: 5.46.1 terser: 5.46.1
vite@6.4.1(@types/node@22.19.15)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
postcss: 8.5.8
rollup: 4.60.0
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 22.19.15
fsevents: 2.3.3
jiti: 1.21.7
lightningcss: 1.32.0
terser: 5.46.1
yaml: 2.8.3
vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3): vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(yaml@2.8.3):
dependencies: dependencies:
esbuild: 0.25.12 esbuild: 0.25.12