Merge remote-tracking branch 'origin/iipbs/st/dev'

This commit is contained in:
2026-11-12 15:05:37 +09:00
18 changed files with 281 additions and 127 deletions
+28
View File
@@ -0,0 +1,28 @@
FROM node:20-alpine
# pnpm 설치
RUN corepack enable && corepack prepare pnpm@8.15.5 --activate
WORKDIR /app
# 모든 소스 복사
COPY . .
# .env.production 파일 생성
RUN mkdir -p /app/apps/st && \
echo "NODE_ENV=production" > /app/apps/st/.env.production && \
echo "PORT=3000" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_PORT=3000" >> /app/apps/st/.env.production && \
echo "SERVER_API_URL=http://dev.onasys.co.kr:8000" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_PROXY_HOST=https://st.apps.rsonesoft.com" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_TINY_API_KEY=t9nc4z6inquvvd5pq1vea8wcp7lb01qmqseh6egms9vpaju2" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_ST_SERVICE_URL=https://apigateway.apps.rsonesoft.com" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_ST_REALGRID_KEY=upVcPE+wPOmtLjqyBIh9RkM/nBOseBrflwxYpzGZyYnkTzf7Gmn/c+YNYZY36ZjDHoLUQjrb+Zx6JscIKXc6ti45WUEqxvh/kkzVSHLUHquykNuBw5QDg+AQvETEhgujkdwMl8bfXmKFzr6UT9cAmQ==" >> /app/apps/st/.env.production && \
echo "NEXT_PUBLIC_SITE_ID=ST" >> /app/apps/st/.env.production
RUN pnpm install --filter=st...
RUN pnpm build --filter=st...
EXPOSE 3000
CMD ["sh", "-c", "pnpm --filter st start & wait"]
@@ -695,20 +695,6 @@ const SidoSggFacilityNameSearchForm = ({
</div>
)}
<div className="flex w-full min-w-0 items-stretch gap-[1.2rem]">
<div className="flex min-w-0 flex-1 flex-col gap-2">
<h3 className="text-[1.4rem] font-medium text-foreground">
처리시설 정보
</h3>
<CompactDataGrid
columnInfo={treatmentFacilityColumnInfo}
rowData={treatmentFacilityRows}
setRowData={setTreatmentFacilityRows}
showHeaderCheckbox={false}
compactFullWidth
onRowClick={handleTreatmentFacilityRowClick}
// compactGridHeightClass="h-[min(40vh,28rem)] min-h-[16rem]"
/>
</div>
<div className="flex min-w-0 flex-1 flex-col gap-2">
<div className="flex items-center justify-between gap-2">
<h3 className="text-[1.4rem] font-medium text-foreground">
@@ -726,6 +712,20 @@ const SidoSggFacilityNameSearchForm = ({
// compactGridHeightClass="h-[min(40vh,28rem)] min-h-[16rem]"
/>
</div>
<div className="flex min-w-0 flex-1 flex-col gap-2">
<h3 className="text-[1.4rem] font-medium text-foreground">
처리시설 정보
</h3>
<CompactDataGrid
columnInfo={treatmentFacilityColumnInfo}
rowData={treatmentFacilityRows}
setRowData={setTreatmentFacilityRows}
showHeaderCheckbox={false}
compactFullWidth
onRowClick={handleTreatmentFacilityRowClick}
// compactGridHeightClass="h-[min(40vh,28rem)] min-h-[16rem]"
/>
</div>
</div>
</div>
);
@@ -16,6 +16,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -144,8 +145,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -444,7 +444,11 @@ const ExcretaTreatmentFacilityInp = () => {
return { ...col, editable: false as const };
}
if (col.fieldName === "sggNm" && enterable) {
return buildSggNmColumn(col, true, sggOptions);
return buildSggNmColumn(
col,
true,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
}
return col;
})
@@ -457,7 +461,7 @@ const ExcretaTreatmentFacilityInp = () => {
columns,
columnLayout: ExcretaTreatFactInpColumn.columnLayout ?? [],
};
}, [statusInfo, inputPeriodEnterable, isAdminInfo, sggOptions, columnGuidesByEngCol]);
}, [statusInfo, inputPeriodEnterable, isAdminInfo, sggOptions, lastSearchedValues?.gugun, columnGuidesByEngCol]);
const canEditGrid =
(computeTabEnterable(statusInfo, inputPeriodEnterable) || isAdminInfo) && inputPeriodEnterable;
@@ -1044,7 +1048,7 @@ const ExcretaTreatmentFacilityInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{statusInfo?.lclgvSbmsnSttsCd === "2" && submitOk && (
{statusInfo?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -161,8 +161,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1200,7 +1199,7 @@ const PrivateSewageFacilityInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -121,8 +121,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1336,7 +1335,7 @@ const PublicSewageFacilityInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{!isMainFacilityTab && activeTabStatus?.lclgvSbmsnSttsCd === '2' && submitOk && (
{!isMainFacilityTab && activeTabStatus?.lclgvSbmsnSttsCd === '2' && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -16,6 +16,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -144,8 +145,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -438,7 +438,11 @@ const PumpingStationInp = () => {
return { ...col, editable: false as const };
}
if (col.fieldName === "sggNm" && enterable) {
return buildSggNmColumn(col, true, sggOptions);
return buildSggNmColumn(
col,
true,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
}
return col;
})
@@ -451,7 +455,7 @@ const PumpingStationInp = () => {
columns,
columnLayout: PumpingStationInpColumn.columnLayout ?? [],
};
}, [statusInfo, inputPeriodEnterable, isAdminInfo, sggOptions, columnGuidesByEngCol]);
}, [statusInfo, inputPeriodEnterable, isAdminInfo, sggOptions, lastSearchedValues?.gugun, columnGuidesByEngCol]);
const canEditGrid =
(computeTabEnterable(statusInfo, inputPeriodEnterable) || isAdminInfo) && inputPeriodEnterable;
@@ -1027,7 +1031,7 @@ const PumpingStationInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{statusInfo?.lclgvSbmsnSttsCd === "2" && submitOk && (
{statusInfo?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -9,6 +9,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -208,8 +209,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1887,7 +1887,11 @@ const SewageExcretaRelatedInp = () => {
SGG_NM_DROPDOWN_TAB_KEYS.has(tabKey) &&
col.fieldName === "sggNm"
) {
next = buildSggNmColumn(col, canEdit, sggOptions);
next = buildSggNmColumn(
col,
canEdit,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
} else if (col.fieldName === "sggNm") {
next = { ...col, editable: false as const, styleName: "rg-cell-readonly" };
}
@@ -1900,7 +1904,7 @@ const SewageExcretaRelatedInp = () => {
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab, sggOptions]);
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab, sggOptions, lastSearchedValues?.gugun]);
const publicInstitutionArticleCellStyleCallback = useCallback<CellStyleCallback>(
({ fieldName, row }) => {
@@ -2023,7 +2027,7 @@ const SewageExcretaRelatedInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -17,6 +17,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -60,6 +61,7 @@ import LastYearDataButton from "@/components/button/LastYearDataButton";
import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton";
import SaveButton from "@/components/button/SaveButton";
import SubmitButton from "@/components/button/SumitButton";
import UpdateOperateDataButton from "@/components/button/UpdateOperateDataButton";
import VerificationResultButton from "@/components/button/VerificationResultButton";
import DataGrid from "@/components/module/DataGrid";
import { openVerificationResultDialogIfNeeded } from "@/components/module/post-submit-verification-results";
@@ -184,10 +186,10 @@ function mapListToGridRows<T extends { verificationResult?: SewageExcretaSlurgeV
});
}
const SewageExcretaSlurgeInpTabList = [
SlurgeProcessingFacStatusInpColumn,
DigestorOperatingStatusInpColumn,
SewageSlurgeProcessingFacStatusInpColumn,
const SewageExcretaSlurgeInpTabList = [
SlurgeProcessingFacStatusInpColumn,
DigestorOperatingStatusInpColumn,
SewageSlurgeProcessingFacStatusInpColumn,
ExcretaSlurgeProcessingStatusInpColumn,
] as const;
@@ -382,8 +384,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1341,18 +1342,18 @@ const SewageExcretaSlurgeInp = () => {
noApplicable || !isSewageSlurgeFacTab
? []
: rowsForSubmit.map((row) =>
buildSewageSlurgeProcessingFacStatusSaveItem(row, list),
);
buildSewageSlurgeProcessingFacStatusSaveItem(row, list),
);
const excretaSlurgeSubmitList =
noApplicable || !isExcretaSlurgeTab
? []
: rowsForSubmit.map((row) =>
buildExcretaSlurgeProcessingStatusSaveItem(row, list),
);
buildExcretaSlurgeProcessingStatusSaveItem(row, list),
);
const sewageSlurgeFacDeleteList = isSewageSlurgeFacTab
? (deleteListByTab.get(tabKey) ?? [])
.filter((row) => isPersistedArticleRowForTab(tabKey, row))
.map((row) => buildSewageSlurgeProcessingFacStatusSaveItem(row, list))
.filter((row) => isPersistedArticleRowForTab(tabKey, row))
.map((row) => buildSewageSlurgeProcessingFacStatusSaveItem(row, list))
: [];
if (
@@ -1373,10 +1374,10 @@ const SewageExcretaSlurgeInp = () => {
(isDigestorTab
? SEWAGE_EXCRETA_DIGESTOR_OPERATING_STATS_CD
: isSewageSlurgeFacTab
? SEWAGE_EXCRETA_SEWAGE_SLURGE_FAC_STATUS_STATS_CD
: isExcretaSlurgeTab
? SEWAGE_EXCRETA_EXCRETA_SLURGE_PROCESSING_STATS_CD
: SEWAGE_EXCRETA_SLURGE_PROCESSING_FAC_STATUS_STATS_CD);
? SEWAGE_EXCRETA_SEWAGE_SLURGE_FAC_STATUS_STATS_CD
: isExcretaSlurgeTab
? SEWAGE_EXCRETA_EXCRETA_SLURGE_PROCESSING_STATS_CD
: SEWAGE_EXCRETA_SLURGE_PROCESSING_FAC_STATUS_STATS_CD);
const verificationQuery = {
...toInputSearchRegion(sidoListRef.current, lastSearchedValues),
@@ -1428,32 +1429,32 @@ const SewageExcretaSlurgeInp = () => {
setGlobalProgressLabel("일반 검증 진행 중...");
const response = isSlurgeFacTab
? await statisticsInputSewageExcretaSlurgeApi.submitSlurgeProcessingFacStatus({
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: slurgeSubmitList,
})
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: slurgeSubmitList,
})
: isDigestorTab
? await statisticsInputSewageExcretaSlurgeApi.submitDigestorOperatingStatus({
? await statisticsInputSewageExcretaSlurgeApi.submitDigestorOperatingStatus({
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: digestorSubmitList,
})
: isSewageSlurgeFacTab
? await statisticsInputSewageExcretaSlurgeApi.submitSewageSlurgeProcessingFacStatus(
{
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: sewageSlurgeFacSubmitList,
deleteList: sewageSlurgeFacDeleteList,
},
)
: await statisticsInputSewageExcretaSlurgeApi.submitExcretaSlurgeProcessingStatus(
{
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: excretaSlurgeSubmitList,
},
);
: isSewageSlurgeFacTab
? await statisticsInputSewageExcretaSlurgeApi.submitSewageSlurgeProcessingFacStatus(
{
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: sewageSlurgeFacSubmitList,
deleteList: sewageSlurgeFacDeleteList,
},
)
: await statisticsInputSewageExcretaSlurgeApi.submitExcretaSlurgeProcessingStatus(
{
...submitRequestBase,
userUuid: userInfo.userUnqId,
submitList: excretaSlurgeSubmitList,
},
);
if (response.status !== "success") {
alert(response.message ?? "데이터 제출 중 오류가 발생했습니다.");
@@ -1533,6 +1534,61 @@ const SewageExcretaSlurgeInp = () => {
}
};
const updateOperateDataButtonFunc = () => {
void (async () => {
if (!lastSearchedValues) {
alert("먼저 조회를 진행해주세요.");
return;
}
if (!(await confirm("자체발생량·함수율·자체 1차 처리량이 운영 데이터로 덮어씁니다."))) {
return;
}
try {
showGlobalProgress({ label: "운영 데이터 업데이트 중...", progress: 0 });
const userInfo = await getUserInfo();
const request = {
statsYr: lastSearchedValues.year ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
...toInputSearchRegion(sidoListRef.current, lastSearchedValues),
userUuid: userInfo.userUnqId,
};
const response =
await statisticsInputSewageExcretaSlurgeApi.updateSlurgeProcessingFacStatusOperationData(
request,
);
if (response.status !== "success") {
alert(
response.message ||
"운영 데이터 업데이트 중 오류가 발생했습니다.",
);
return;
}
setGlobalProgress(50);
const tabKey = SlurgeProcessingFacStatusInpColumn.tabKey;
const param =
searchParamRef.current ??
buildSewageExcretaSlurgeSearchParam(lastSearchedValues);
await loadActiveTabData(tabKey, param, lastSearchedValues, true, false);
setGlobalProgress(100);
alert("운영 데이터가 업데이트되었습니다.");
} catch (error) {
const message =
error &&
typeof error === "object" &&
"response" in error
? (error as { response?: { data?: { message?: string } } })
.response?.data?.message
: undefined;
alert(message || "운영 데이터 업데이트 중 오류가 발생했습니다.");
} finally {
hideGlobalProgress();
}
})();
};
const cnacelSubmitFunc = () => {
void (async () => {
try {
@@ -1644,8 +1700,8 @@ const SewageExcretaSlurgeInp = () => {
const saveList = noApplicable
? []
: rowsForSave.map((row) =>
buildSlurgeProcessingFacStatusSaveItem(row, list),
);
buildSlurgeProcessingFacStatusSaveItem(row, list),
);
if (!noApplicable && saveList.length === 0 && buildSubmitOkForToolbar(searchContextByTab.get(tabKey) ?? lastSearchedValues)) {
alert("해당사항 없음을 체크해주세요.");
@@ -1670,8 +1726,8 @@ const SewageExcretaSlurgeInp = () => {
const saveList = noApplicable
? []
: rowsForSave.map((row) =>
buildDigestorOperatingStatusSaveItem(row, list),
);
buildDigestorOperatingStatusSaveItem(row, list),
);
if (!noApplicable && saveList.length === 0 && buildSubmitOkForToolbar(searchContextByTab.get(tabKey) ?? lastSearchedValues)) {
alert("해당사항 없음을 체크해주세요.");
@@ -1693,8 +1749,8 @@ const SewageExcretaSlurgeInp = () => {
const saveList = noApplicable
? []
: rowsForSave.map((row) =>
buildSewageSlurgeProcessingFacStatusSaveItem(row, list),
);
buildSewageSlurgeProcessingFacStatusSaveItem(row, list),
);
const deleteList = (deleteListByTab.get(tabKey) ?? [])
.filter((row) => isPersistedArticleRowForTab(tabKey, row))
.map((row) => buildSewageSlurgeProcessingFacStatusSaveItem(row, list));
@@ -1723,8 +1779,8 @@ const SewageExcretaSlurgeInp = () => {
const saveList = noApplicable
? []
: rowsForSave.map((row) =>
buildExcretaSlurgeProcessingStatusSaveItem(row, list),
);
buildExcretaSlurgeProcessingStatusSaveItem(row, list),
);
if (!noApplicable && saveList.length === 0 && buildSubmitOkForToolbar(searchContextByTab.get(tabKey) ?? lastSearchedValues)) {
alert("해당사항 없음을 체크해주세요.");
@@ -1776,17 +1832,17 @@ const SewageExcretaSlurgeInp = () => {
const getCheckedItemIndexesFromGrid = (rowCount: number): number[] => {
const gridView = getGridRef.current?.gridView as
| {
getCheckedItems?: () => number[];
getCheckedRows?: () => number[];
}
getCheckedItems?: () => number[];
getCheckedRows?: () => number[];
}
| undefined;
const checked =
(typeof gridView?.getCheckedItems === "function"
? gridView.getCheckedItems()
: typeof gridView?.getCheckedRows === "function"
? gridView.getCheckedRows()
: []) ?? [];
? gridView.getCheckedRows()
: []) ?? [];
return checked.filter(
(idx) => Number.isInteger(idx) && idx >= 0 && idx < rowCount,
@@ -1858,10 +1914,10 @@ const SewageExcretaSlurgeInp = () => {
checkedIndexes.length > 0
? new Set(checkedIndexes)
: new Set(
currentRows
.map((row, idx) => (isCheckedRow(row) ? idx : -1))
.filter((idx) => idx >= 0),
);
currentRows
.map((row, idx) => (isCheckedRow(row) ? idx : -1))
.filter((idx) => idx >= 0),
);
const removedRows = currentRows.filter((_, idx) => checkedIndexSet.has(idx));
const nextRows = currentRows.filter((_, idx) => !checkedIndexSet.has(idx));
@@ -1920,7 +1976,11 @@ const SewageExcretaSlurgeInp = () => {
SGG_NM_DROPDOWN_TAB_KEYS.has(tabKey) &&
col.fieldName === "sggNm"
) {
next = buildSggNmColumn(col, canEdit, sggOptions);
next = buildSggNmColumn(
col,
canEdit,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
} else if (col.fieldName === "sggNm") {
next = { ...col, editable: false as const, styleName: "rg-cell-readonly" };
}
@@ -2080,8 +2140,8 @@ const SewageExcretaSlurgeInp = () => {
onValuesChange={setSearchValues}
/>
{showActionToolbarCard && (
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
<VerificationResultButton
VerificationResultButtonFunc={openVerificationHistoryDialog}
isVerificationFailed={
@@ -2093,19 +2153,24 @@ const SewageExcretaSlurgeInp = () => {
<LastYearDataButton
getLastYearDataFunc={() => void lastYearDataFunc()}
/>
{submitOk && <SubmitButton submitFunc={submitFunc} />}
{activeTab === SEWAGE_EXCRETA_SLURGE_PROCESSING_FAC_STATUS_STATS_CD && (
<UpdateOperateDataButton
updateOperateDataButtonFunc={updateOperateDataButtonFunc}
/>
)}
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
</div>
</div>
</div>
</div>
)}
{showSecondaryToolbarCard && (
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
{showNotApplicableForActiveTab && (
<NotApplicableCheckButton
isCheck={isNotApplicableForActiveTab}
@@ -2114,12 +2179,12 @@ const SewageExcretaSlurgeInp = () => {
)}
{showArticleEditButtons && (
<>
<AddArticleButton addArticleFunc={addArticleFunc} />
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
<AddArticleButton addArticleFunc={addArticleFunc} />
<DeleteArticleButton deleteArticleFunc={deleteArticleFunc} />
</>
)}
</div>
</div>
</div>
</div>
)}
{isLoading && (
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
@@ -453,8 +453,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -2062,7 +2061,7 @@ const SewagePipeInp = () => {
{submitOk && <SubmitButton submitFunc={() => void submitFunc(false)} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -156,8 +156,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1150,7 +1149,7 @@ const SewagePipeMaintainInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -17,6 +17,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -176,8 +177,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1491,7 +1491,11 @@ const SewageReservoirPumpInp = () => {
col.fieldName === "sggNm" &&
canEdit
) {
return buildSggNmColumn(col, true, sggOptions);
return buildSggNmColumn(
col,
true,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
}
return col;
}).map((col) => {
@@ -1504,7 +1508,7 @@ const SewageReservoirPumpInp = () => {
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, sggOptions, columnGuidesByTab]);
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, sggOptions, lastSearchedValues?.gugun, columnGuidesByTab]);
const verificationCellStyle = ({
fieldName,
@@ -1583,7 +1587,7 @@ const SewageReservoirPumpInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -160,8 +160,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1271,7 +1270,7 @@ const SewerageFinanceInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -815,8 +815,7 @@ const SeweragePenetrationRateInp = () => {
toolbarGroupAllowed &&
(baseShowSaveInToolbar ||
baseShowEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return (
<>
@@ -842,7 +841,7 @@ const SeweragePenetrationRateInp = () => {
{submitOk && <SubmitButton submitFunc={() => submitFunc(false)} />}
</>
)}
{statusInfo?.lclgvSbmsnSttsCd === '2' && submitOk && <CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />}
{statusInfo?.lclgvSbmsnSttsCd === '2' && submitOk && inputPeriodCurrent && <CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
</div>
</div>
@@ -169,8 +169,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1202,7 +1201,7 @@ const SewerageServiceLevelInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -17,6 +17,7 @@ import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGa
import { STATISTICS_INPUT_URL_PATH } from "@/shared/lib/stats-cd-input-navigation";
import { useStatisticsInputPendingNavigation } from "@/shared/lib/use-statistics-input-pending-navigation";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { filterSggOptionsBySearchGugun } from "@/components/util/input/filter-sgg-options-by-search";
import { nullableTrimmedString } from "@/components/util/input/nullableString";
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";
@@ -208,8 +209,7 @@ function computeTabToolbarSnapshot(
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
showSubmittedInInputPeriodToolbar);
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
@@ -1982,7 +1982,11 @@ const WaterReuseInp = () => {
ARTICLE_EDIT_TAB_KEYS.has(tabKey) &&
col.fieldName === "sggNm"
) {
next = buildSggNmColumn(col, canEdit, sggOptions);
next = buildSggNmColumn(
col,
canEdit,
filterSggOptionsBySearchGugun(sggOptions, lastSearchedValues?.gugun),
);
}
const guide = columnGuidesByTab[tabKey]?.[col.fieldName]?.trim();
return guide ? { ...next, tooltip: guide } : next;
@@ -1993,7 +1997,7 @@ const WaterReuseInp = () => {
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab, sggOptions]);
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab, sggOptions, lastSearchedValues?.gugun]);
const searchContextForToolbar = searchContextByTab.get(activeTab) ?? lastSearchedValues;
const activeTabStatus = tabStatusInfoMap.get(activeTab) ?? null;
@@ -2125,7 +2129,7 @@ const WaterReuseInp = () => {
{submitOk && <SubmitButton submitFunc={submitFunc} />}
</>
)}
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && (
{activeTabStatus?.lclgvSbmsnSttsCd === "2" && submitOk && inputPeriodEnterable && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
@@ -0,0 +1,13 @@
import type { Sgg } from "@/entities/statistics/model/statistics-interface";
/** 조회 시군구가 전체(ALL)면 시도의 전체 옵션, 특정 구면 해당 구만 */
export function filterSggOptionsBySearchGugun(
sggOptions: readonly Sgg[],
gugun: string | null | undefined,
): Sgg[] {
const selected = gugun?.trim();
if (!selected || selected === "ALL") {
return [...sggOptions];
}
return sggOptions.filter((s) => s.gugun === selected);
}
@@ -22,6 +22,8 @@ import type {
SewageSlurgeProcessingFacStatusSubmitRequest,
SewageSlurgeProcessingFacStatusSubmitResponse,
SlurgeProcessingFacStatusApiResponse,
SlurgeProcessingFacStatusOperationDataUpdateRequest,
SlurgeProcessingFacStatusOperationDataUpdateResponse,
SlurgeProcessingFacStatusSaveRequest,
SlurgeProcessingFacStatusSaveResponse,
SlurgeProcessingFacStatusSubmitRequest,
@@ -68,6 +70,18 @@ export class StatisticsInputSewageExcretaSlurgeApiService implements StatisticsI
return response.data;
}
/** 찌꺼기(슬러지)처리시설현황 운영 데이터 업데이트 — ST00110001 */
public async updateSlurgeProcessingFacStatusOperationData(
request: SlurgeProcessingFacStatusOperationDataUpdateRequest,
): Promise<SlurgeProcessingFacStatusOperationDataUpdateResponse> {
const response =
await stClient.put<SlurgeProcessingFacStatusOperationDataUpdateResponse>(
`${BASE}/slurge-processing-fac-status/operation-data/update`,
request,
);
return response.data;
}
/** 소화조 운영현황 조회 — ST00110002 */
public async getDigestorOperatingStatusList(
params: SewageExcretaSlurgeRequestParams,
@@ -205,6 +205,23 @@ export interface SlurgeProcessingFacStatusSubmitResponse {
};
}
/** ST00110001 운영 데이터 업데이트 요청 */
export interface SlurgeProcessingFacStatusOperationDataUpdateRequest {
statsYr: string;
ctpvNm: string;
/** 도에서만 사용, 특·광역시는 빈 값 */
sggNm?: string;
sewerBzmnCd: string;
userUuid: string;
}
/** ST00110001 운영 데이터 업데이트 응답 */
export interface SlurgeProcessingFacStatusOperationDataUpdateResponse {
status: string;
message?: string;
data?: unknown | null;
}
/**
* ST00110002 조회 `data.digestorOperatingStatusList[]` 한 행.
* `DigestorOperatingStatusInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
@@ -561,6 +578,10 @@ export interface StatisticsInputSewageExcretaSlurgeService {
submitSlurgeProcessingFacStatus(
request: SlurgeProcessingFacStatusSubmitRequest,
): Promise<SlurgeProcessingFacStatusSubmitResponse>;
/** 찌꺼기(슬러지)처리시설현황 운영 데이터 업데이트 — ST00110001 */
updateSlurgeProcessingFacStatusOperationData(
request: SlurgeProcessingFacStatusOperationDataUpdateRequest,
): Promise<SlurgeProcessingFacStatusOperationDataUpdateResponse>;
/** 소화조 운영현황 조회 — ST00110002 */
getDigestorOperatingStatusList(
params: SewageExcretaSlurgeRequestParams,