[st] - fix: 오류 수정 및 누락 기능 추가

This commit is contained in:
2026-05-18 11:03:43 +09:00
parent 8384743a30
commit b508568e86
21 changed files with 1121 additions and 518 deletions
@@ -1,6 +1,6 @@
"use client";
import { useCallback } from "react";
import { useCallback, useState } from "react";
import { useQueries } from "@tanstack/react-query";
import { useTabStore as useGridTabStore } from "@rsone/components";
@@ -19,16 +19,30 @@ import {
Badge,
type BadgeProps,
LoadingWithAnimation,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@common/components";
type VerificationReportTabKey = "NV" | "IMR" | "HB";
const VERIFICATION_REPORT_TABS: { value: VerificationReportTabKey; label: string }[] = [
{ value: "NV", label: "일반" },
{ value: "IMR", label: "I-MR" },
{ value: "HB", label: "HB" },
];
const TYPE_CODE_COLOR_MAP: Record<string, BadgeProps["color"]> = {
NV: "gray",
IMR: "red",
HB: "blue",
};
const TYPE_CODE_NAME_MAP: Record<string, string> = {
NV: "일반",
IMR: "I-MR",
HB: "HB",
};
type VerificationSelectionReportProps = {
@@ -46,6 +60,7 @@ const VerificationSelectionReport = ({
(s) => s.setPendingInputTab,
);
const alert = useAlertStore((s) => s.setMessage);
const [activeTab, setActiveTab] = useState<VerificationReportTabKey>("NV");
const statsYr = String(dayjs().year() - 1);
@@ -57,7 +72,7 @@ const VerificationSelectionReport = ({
prcsYnList: "0",
};
const [nvQuery, imrQuery] = useQueries({
const [nvQuery, imrQuery, hbQuery] = useQueries({
queries: [
{
queryKey: [
@@ -91,14 +106,34 @@ const VerificationSelectionReport = ({
vrfcMthdCd: "IMR",
}),
},
{
queryKey: [
"verificationResultList",
statsYr,
"HB",
baseRequest.pbcpAprvYn,
baseRequest.page,
baseRequest.size,
baseRequest.prcsYnList,
],
queryFn: () =>
statisticsApi.getVerificationResultList({
...baseRequest,
vrfcMthdCd: "HB",
}),
},
],
});
const isLoading = nvQuery.isLoading || imrQuery.isLoading;
const error = nvQuery.error ?? imrQuery.error;
const isLoading =
nvQuery.isLoading || imrQuery.isLoading || hbQuery.isLoading;
const error = nvQuery.error ?? imrQuery.error ?? hbQuery.error;
const nvList = nvQuery.data?.data?.verifyResultList ?? [];
const imrList = imrQuery.data?.data?.verifyResultList ?? [];
const listsByTab: Record<VerificationReportTabKey, VerificationResultReportItem[]> = {
NV: nvQuery.data?.data?.verifyResultList ?? [],
IMR: imrQuery.data?.data?.verifyResultList ?? [],
HB: hbQuery.data?.data?.verifyResultList ?? [],
};
const openInputFromStatsCd = useCallback(
(item: VerificationResultReportItem) => {
@@ -147,68 +182,61 @@ const VerificationSelectionReport = ({
],
);
const renderSection = (
typeCode: "IMR" | "NV",
const renderResultList = (
typeCode: VerificationReportTabKey,
items: VerificationResultReportItem[],
) => (
<section className="flex min-h-0 flex-1 flex-col rounded-sm border border-border h-[50rem]">
<div className="flex items-center justify-between border-b border-border px-3 py-2">
<Badge color={TYPE_CODE_COLOR_MAP[typeCode]} className="rounded-full px-2 py-1 text-lg">
{TYPE_CODE_NAME_MAP[typeCode]} {items.length}
</Badge>
</div>
<div className="min-h-0 flex-1 overflow-y-auto p-2">
{items.length === 0 ? (
<div className="flex h-full min-h-[8rem] items-center justify-center text-lg text-muted-foreground">
항목이 없습니다.
</div>
) : (
<div className="space-y-2 tracking-tight">
{items.map((item) => (
<div
key={`${typeCode}-${item.vrfcSn}`}
role="button"
tabIndex={0}
className="flex flex-col rounded-sm border border-border p-3 cursor-pointer hover:bg-gray-100"
onClick={() => openInputFromStatsCd(item)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
openInputFromStatsCd(item);
<div className="min-h-0 flex-1 overflow-y-auto p-2">
{items.length === 0 ? (
<div className="flex h-full min-h-[8rem] items-center justify-center text-lg text-muted-foreground">
항목이 없습니다.
</div>
) : (
<div className="space-y-2 tracking-tight">
{items.map((item) => (
<div
key={`${typeCode}-${item.vrfcSn}`}
role="button"
tabIndex={0}
className="flex flex-col rounded-sm border border-border p-3 cursor-pointer hover:bg-gray-100"
onClick={() => openInputFromStatsCd(item)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
openInputFromStatsCd(item);
}
}}
>
<div className="mb-2 flex items-center justify-between">
<span className="font-medium">
{item.statsNm}
</span>
<Badge
color={
TYPE_CODE_COLOR_MAP[item.vrfcMthdCd] ??
"gray"
}
}}
>
<div className="mb-2 flex items-center justify-between">
<span className="font-medium">
{item.statsNm}
</span>
<Badge
color={
TYPE_CODE_COLOR_MAP[item.vrfcMthdCd] ??
"gray"
}
className="text-sm"
>
{TYPE_CODE_NAME_MAP[item.vrfcMthdCd] ??
item.vrfcMthdNm}
</Badge>
</div>
<p className="text-lg text-muted-foreground">
{item.rsnExpln}
</p>
<div className="flex justify-between text-lg text-muted-foreground">
<span>{item.admdstNm}</span>
<span>
현재: {item.nowVlCn ?? "-"} / 비교:{" "}
{item.compVlCn ?? "-"}
</span>
</div>
className="text-sm"
>
{TYPE_CODE_NAME_MAP[item.vrfcMthdCd] ??
item.vrfcMthdNm}
</Badge>
</div>
))}
</div>
)}
</div>
</section>
<p className="text-lg text-muted-foreground">
{item.rsnExpln}
</p>
<div className="flex justify-between text-lg text-muted-foreground">
<span>{item.admdstNm}</span>
<span>
현재: {item.nowVlCn ?? "-"} / 비교:{" "}
{item.compVlCn ?? "-"}
</span>
</div>
</div>
))}
</div>
)}
</div>
);
return (
@@ -246,10 +274,42 @@ const VerificationSelectionReport = ({
</div>
)}
{!isLoading && !error && (
<div className="grid grid-rows-2 gap-6">
{renderSection("IMR", imrList)}
{renderSection("NV", nvList)}
</div>
<section className="flex min-h-0 flex-1 flex-col h-[85rem]">
<Tabs
value={activeTab}
onValueChange={(value) =>
setActiveTab(value as VerificationReportTabKey)
}
className="flex min-h-0 flex-1 flex-col h-full"
variant="default"
>
<TabsList className="grid w-full grid-cols-3 p-1">
{VERIFICATION_REPORT_TABS.map((tab) => (
<TabsTrigger
key={tab.value}
value={tab.value}
className="!px-2 !py-2 text-[1.3rem] whitespace-normal"
>
{tab.label} ({listsByTab[tab.value].length})
</TabsTrigger>
))}
</TabsList>
{VERIFICATION_REPORT_TABS.map((tab) => (
<TabsContent
key={tab.value}
value={tab.value}
className="mt-0 flex min-h-0 flex-1 flex-col p-0 data-[state=inactive]:hidden"
>
{activeTab === tab.value
? renderResultList(
tab.value,
listsByTab[tab.value],
)
: null}
</TabsContent>
))}
</Tabs>
</section>
)}
</div>
</div>
@@ -38,6 +38,7 @@ import VerificationResultButton from '@/components/button/VerificationResultButt
import DataGrid from '@/components/module/DataGrid';
import SearchForm from '@/components/module/SearchForm';
import SplitDataGrid from '@/components/module/SplitDataGrid';
import { openVerificationResultDialogIfNeeded } from '@/components/module/post-submit-verification-results';
import { VerificationResultDialog } from '@/components/module/VerificationResultDialog';
import { VerificationResultHistoryDialog } from '@/components/module/VerificationResultHistoryDialog';
import type { CellStyleCallbackParams, ColumnInfo, ColumnInfoList } from '@/components/type/DataGrid.type';
@@ -342,14 +343,34 @@ const PublicSewageFacilityInp = () => {
searchParamRef.current,
lastSearchedValues,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: lastSearchedValues.bsnmCd ?? '',
ctpvNm: lastSearchedValues.sido ?? '',
sggNm: lastSearchedValues.gugun === 'ALL' ? '' : (lastSearchedValues.gugun ?? ''),
statsYr: lastSearchedValues.year ?? '',
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert },
);
} catch (e) {
await loadPublicSewageFacilityActiveTabData(
'ST00060001',
searchParamRef.current,
lastSearchedValues,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: lastSearchedValues.bsnmCd ?? '',
ctpvNm: lastSearchedValues.sido ?? '',
sggNm: lastSearchedValues.gugun === 'ALL' ? '' : (lastSearchedValues.gugun ?? ''),
statsYr: lastSearchedValues.year ?? '',
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert, notifySubmitComplete: false },
);
const msg =
e instanceof Error && e.message
? e.message
@@ -363,7 +384,17 @@ const PublicSewageFacilityInp = () => {
searchParamRef.current,
lastSearchedValues,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: lastSearchedValues.bsnmCd ?? '',
ctpvNm: lastSearchedValues.sido ?? '',
sggNm: lastSearchedValues.gugun === 'ALL' ? '' : (lastSearchedValues.gugun ?? ''),
statsYr: lastSearchedValues.year ?? '',
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert },
);
}
} catch {
alert('데이터 제출 중 오류가 발생했습니다.');
@@ -472,7 +503,7 @@ const PublicSewageFacilityInp = () => {
sggNm: lastSearchedValues.gugun === 'ALL' ? '' : lastSearchedValues.gugun ?? '',
sewerBzmnCd: lastSearchedValues.bsnmCd ?? '',
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? 'superAdmin' : '',
// superAdmin: isAdminInfo ? 'superAdmin' : '',
noApplicable: getNoApplicableForRequest(),
saveList,
};
@@ -56,6 +56,7 @@ import DataGrid from "@/components/module/DataGrid";
import GridTopActionButton from "@/components/module/GridTopActionButton";
import SearchForm from "@/components/module/SearchForm";
import SplitDataGrid from "@/components/module/SplitDataGrid";
import { openVerificationResultDialogIfNeeded } from "@/components/module/post-submit-verification-results";
import { VerificationResultDialog } from "@/components/module/VerificationResultDialog";
import { VerificationResultHistoryDialog } from "@/components/module/VerificationResultHistoryDialog";
import type { ColumnConfig,ColumnInfo, ColumnInfoList } from "@/components/type/DataGrid.type";
@@ -1248,7 +1249,17 @@ const SewagePipeInp = () => {
true,
false,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: values.bsnmCd ?? "",
ctpvNm: values.sido ?? "",
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
statsYr: values.year ?? "",
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert },
);
} catch (e) {
await loadSewagePipeActiveTabData(
tabKey,
@@ -1257,7 +1268,17 @@ const SewagePipeInp = () => {
true,
false,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: values.bsnmCd ?? "",
ctpvNm: values.sido ?? "",
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
statsYr: values.year ?? "",
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert, notifySubmitComplete: false },
);
const msg =
e instanceof Error && e.message
? e.message
@@ -1273,7 +1294,17 @@ const SewagePipeInp = () => {
true,
false,
);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
{
sewerBzmnCd: values.bsnmCd ?? "",
ctpvNm: values.sido ?? "",
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
statsYr: values.year ?? "",
statsCd: statsCdForTab,
},
setVerificationResultDialogOpen,
{ notify: alert },
);
}
} catch {
alert("데이터 제출 중 오류가 발생했습니다.");
@@ -1429,7 +1460,7 @@ const SewagePipeInp = () => {
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
sewerBzmnCd: values.bsnmCd ?? "",
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? "superAdmin" : "",
// superAdmin: isAdminInfo ? "superAdmin" : "",
saveList,
};
@@ -1509,7 +1540,7 @@ const SewagePipeInp = () => {
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
sewerBzmnCd: values.bsnmCd ?? "",
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? "superAdmin" : "",
// superAdmin: isAdminInfo ? "superAdmin" : "",
saveList,
};
@@ -1594,7 +1625,7 @@ const SewagePipeInp = () => {
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
sewerBzmnCd: values.bsnmCd ?? "",
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? "superAdmin" : "",
// superAdmin: isAdminInfo ? "superAdmin" : "",
saveList,
};
@@ -1657,7 +1688,7 @@ const SewagePipeInp = () => {
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
sewerBzmnCd: values.bsnmCd ?? "",
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? "superAdmin" : "",
// superAdmin: isAdminInfo ? "superAdmin" : "",
saveList,
};
@@ -1736,7 +1767,7 @@ const SewagePipeInp = () => {
sggNm: values.gugun === "ALL" ? "" : (values.gugun ?? ""),
sewerBzmnCd: values.bsnmCd ?? "",
userId: userInfo.userUnqId,
superAdmin: isAdminInfo ? "superAdmin" : "",
// superAdmin: isAdminInfo ? "superAdmin" : "",
saveList,
};
@@ -41,6 +41,7 @@ import VerificationResultButton from "@/components/button/VerificationResultButt
// import { DataGrid } from "@rsone/components";
import DataGrid from "@/components/module/DataGrid";
import SearchForm from "@/components/module/SearchForm";
import { openVerificationResultDialogIfNeeded } from "@/components/module/post-submit-verification-results";
import { VerificationResultDialog } from "@/components/module/VerificationResultDialog";
import { VerificationResultHistoryDialog } from "@/components/module/VerificationResultHistoryDialog";
import type { SearchFormValues } from "@/components/type/SearchForm.type";
@@ -348,9 +349,9 @@ const SeweragePenetrationRateInp = () => {
statsCd: statsCd,
};
if (isAdminInfo) {
params.superAdmin = 'superAdmin';
}
// if (isAdminInfo) {
// params.superAdmin = 'superAdmin';
// }
try {
setIsLoading(true);
@@ -525,11 +526,35 @@ const SeweragePenetrationRateInp = () => {
}
setGlobalProgress(100);
await fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), true);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
searchValues?.year && searchValues?.sido && searchValues?.bsnmCd && statsCd
? {
sewerBzmnCd: searchValues.bsnmCd,
ctpvNm: searchValues.sido,
sggNm: searchValues.gugun === "ALL" ? "" : (searchValues.gugun ?? ""),
statsYr: searchValues.year,
statsCd,
}
: null,
setVerificationResultDialogOpen,
{ notify: alert },
);
} catch (e) {
await fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), true);
setIsLoading(false);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
searchValues?.year && searchValues?.sido && searchValues?.bsnmCd && statsCd
? {
sewerBzmnCd: searchValues.bsnmCd,
ctpvNm: searchValues.sido,
sggNm: searchValues.gugun === "ALL" ? "" : (searchValues.gugun ?? ""),
statsYr: searchValues.year,
statsCd,
}
: null,
setVerificationResultDialogOpen,
{ notify: alert, notifySubmitComplete: false },
);
const msg =
e instanceof Error && e.message
? e.message
@@ -540,7 +565,19 @@ const SeweragePenetrationRateInp = () => {
} else {
setGlobalProgress(100);
await fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), false);
setVerificationResultDialogOpen(true);
await openVerificationResultDialogIfNeeded(
searchValues?.year && searchValues?.sido && searchValues?.bsnmCd && statsCd
? {
sewerBzmnCd: searchValues.bsnmCd,
ctpvNm: searchValues.sido,
sggNm: searchValues.gugun === "ALL" ? "" : (searchValues.gugun ?? ""),
statsYr: searchValues.year,
statsCd,
}
: null,
setVerificationResultDialogOpen,
{ notify: alert },
);
}
} else {
alert(response.message || '데이터 제출 중 오류가 발생했습니다.');
@@ -641,9 +678,9 @@ const SeweragePenetrationRateInp = () => {
sewerBzmnFrgnrWholPpltnCnt: footerFromApi?.sewerBzmnFrgnrWholPpltnCnt // 행정참고자료 외국인 합계
};
if (isAdminInfo) {
requestData.superAdmin = 'superAdmin';
}
// if (isAdminInfo) {
// requestData.superAdmin = 'superAdmin';
// }
const response = await statisticsInputSewSupplyRateApi.saveSewerageSupplyRate(requestData);