@@ -593,7 +647,7 @@ const SeweragePenetrationRateInp = () => {
return errors
.map((e) => {
const prefix = e.vrfcCd === 'IMR' ? 'IMR검증 - ' : '일반검증 - ';
- return `${prefix}${e.rsnExpln}`;
+ return `${prefix}${e.rsnExpln}(검증 기준값: ${e.compVlCn} / 현재 입력값: ${e.nowVlCn})`;
})
.filter(Boolean)
.join('\n');
@@ -614,6 +668,25 @@ const SeweragePenetrationRateInp = () => {
submitMode={isExceptionSubmitFlow ? 'exception' : 'normal'}
isLoading={isLoading}
/>
+
+
>
);
};
diff --git a/apps/st/src/components/statistics/management/LogHistory.tsx b/apps/st/src/components/statistics/management/LogHistory.tsx
index ff1747c33..e2abaf60d 100644
--- a/apps/st/src/components/statistics/management/LogHistory.tsx
+++ b/apps/st/src/components/statistics/management/LogHistory.tsx
@@ -7,7 +7,7 @@ import useSWR from "swr";
import { useAlertStore } from "@/shared/lib";
import { CodeSelectWithAll } from "@/entities/code";
-import { statisticsAPi } from "@/entities/statistics/api/statistics-service";
+import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import type {
ApiResponse,
SearchCondition,
@@ -36,13 +36,13 @@ import { toGridRows } from "@/components/util/grid/gridFunction";
const PAGE_SIZE = 100;
const getSidoListFetcher = async (): Promise
> => {
- return statisticsAPi.getSidoList();
+ return statisticsApi.getSidoList();
};
const getSggListFetcher = async (
key: [string, string],
): Promise> => {
- return statisticsAPi.getSggList(key[1]);
+ return statisticsApi.getSggList(key[1]);
};
const LogHistory = () => {
@@ -158,7 +158,7 @@ const LogHistory = () => {
try {
setIsLoading(true);
- const response = await statisticsAPi.getLogList(param);
+ const response = await statisticsApi.getLogList(param);
if (response.status === "success") {
const lostList = response.data?.statsLogList ?? [];
diff --git a/apps/st/src/components/statistics/management/LogHistoryDetailDialog.tsx b/apps/st/src/components/statistics/management/LogHistoryDetailDialog.tsx
index b451b3a14..09667bc88 100644
--- a/apps/st/src/components/statistics/management/LogHistoryDetailDialog.tsx
+++ b/apps/st/src/components/statistics/management/LogHistoryDetailDialog.tsx
@@ -12,7 +12,7 @@ import {
DialogTitle,
} from "@common/components";
-import { statisticsAPi } from "@/entities/statistics/api/statistics-service";
+import { statisticsApi } from "@/entities/statistics/api/statistics-service";
export interface LogHistoryDetailDialogProps {
open: boolean;
@@ -30,7 +30,7 @@ export function LogHistoryDetailDialog({
const sn = row.statsLogSn;
void (async () => {
- const response = await statisticsAPi.getLogDetail(
+ const response = await statisticsApi.getLogDetail(
sn !== undefined && sn !== null ? String(sn) : "",
);
console.log(response.data);
diff --git a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx
index 3af748260..b0f38ed02 100644
--- a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx
+++ b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx
@@ -13,7 +13,7 @@ import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { SeweragePenetrationRateInfoList } from "@/components/util/column/review/SeweragePenetrationRateRvwColumn";
import type { SewerageSupplyRateReviewItem, statsStatusInfo } from "@/entities/statistics/model/statistics-sewerage-penetration-review-interface";
import type { ReviewOpinionSaveRequest } from "@/entities/statistics/model/statistics-interface";
-import { statisticsAPi } from "@/entities/statistics/api/statistics-service";
+import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service";
import type { SearchFormValues } from "@/components/type/SearchForm.type";
import { toGridRows } from "@/components/util/grid/gridFunction";
@@ -141,7 +141,7 @@ const SeweragePenetrationRateRvw = () => {
try {
const userInfo = await getUserInfo();
- const response = await statisticsAPi.submitReview({
+ const response = await statisticsApi.submitReview({
statsYr: reviewOpinionContext.statsYr,
sewerBzmnCd: reviewOpinionContext.sewerBzmnCd,
statsCd: reviewOpinionContext.statsCd,
@@ -169,7 +169,7 @@ const SeweragePenetrationRateRvw = () => {
}
try {
- const detailRes = await statisticsAPi.getReviewOpinionDetail({
+ const detailRes = await statisticsApi.getReviewOpinionDetail({
statsYr: reviewOpinionContext.statsYr,
sewerBzmnCd: reviewOpinionContext.sewerBzmnCd,
statsCd: reviewOpinionContext.statsCd,
@@ -191,7 +191,7 @@ const SeweragePenetrationRateRvw = () => {
const saveReviewOpinion = async (param: ReviewOpinionSaveRequest) => {
try {
- const response = await statisticsAPi.saveReviewOpinion(param);
+ const response = await statisticsApi.saveReviewOpinion(param);
if (response.status !== "success") {
alert(response.message || "저장에 실패했습니다.");
return;
@@ -220,7 +220,7 @@ const SeweragePenetrationRateRvw = () => {
if (await confirm('반려 처리 하시겠습니까?')) {
try {
const userInfo = await getUserInfo();
- const response = await statisticsAPi.saveReviewReturn({
+ const response = await statisticsApi.saveReviewReturn({
statsYr: reviewOpinionContext.statsYr,
sewerBzmnCd: reviewOpinionContext.sewerBzmnCd,
statsCd: reviewOpinionContext.statsCd,
diff --git a/apps/st/src/components/statistics/verification/StatisticsVerificationReport.tsx b/apps/st/src/components/statistics/verification/StatisticsVerificationReport.tsx
index 3b6f86c4f..837433b8d 100644
--- a/apps/st/src/components/statistics/verification/StatisticsVerificationReport.tsx
+++ b/apps/st/src/components/statistics/verification/StatisticsVerificationReport.tsx
@@ -1,567 +1,713 @@
-"use client";
-
-import type { Dispatch, SetStateAction } from "react";
-import { useCallback, useEffect, useMemo, useState } from "react";
-
-import { useConfirm } from "@frontend-opensource/use-react-hooks";
-import dayjs from "dayjs";
-
-import { useAlertStore, useMutationWrapper, useUserStore } from "@/shared/lib";
-import { CodeSelect } from "@/entities/code";
-import {
- type ApprovalRequest,
- statisticsApprovalApi,
- statisticsVerificationDetailColumnInfo,
- type StatisticsVerificationFilterState,
- type StatisticsVerificationSubFilterState,
- statisticsVerificationSummaryColumnInfo,
- type StatsInputStatusList,
- useStAnlsSidoCombo,
- useStAnlsSigunguCombo,
- useStatsVrfcRptData,
- useStatsVrfcRsltData,
- type VerifyResultItem,
-} from "@/entities/statistics";
-import {
- Button,
- Combobox,
- ComboboxChip,
- ComboboxChips,
- ComboboxChipsInput,
- ComboboxContent,
- ComboboxEmpty,
- ComboboxItem,
- ComboboxList,
- ComboboxValue,
- Label,
- LoadingWithAnimation,
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
- useComboboxAnchor,
-} from "@common/components";
-
-import DataGrid from "@/components/module/DataGrid";
-import { toGridRows } from "@/components/util/grid/gridFunction";
-
-const getYearOptions = () => {
- const currentYear = dayjs().year();
- const yearOptionsRange = Array.from(
- { length: currentYear - 2017 },
- (_, i) => {
- const year = 2017 + i;
- return { label: String(year), value: String(year) };
- },
- );
- return yearOptionsRange.map((year) => ({
- label: year.label,
- value: year.value,
- }));
-};
-
-function isSameStatsInputStatusRow(
- a: StatsInputStatusList,
- b: StatsInputStatusList,
-): boolean {
- return (
- a.ctpvNm === b.ctpvNm && a.sggNm === b.sggNm && a.statsCd === b.statsCd
- );
-}
-
-function isSameVerifyResultRow(
- a: VerifyResultItem,
- b: VerifyResultItem,
-): boolean {
- if (a.vrfcSn != null && b.vrfcSn != null) return a.vrfcSn === b.vrfcSn;
- return (
- a.statsYr === b.statsYr &&
- a.statsCd === b.statsCd &&
- a.ctpvNm === b.ctpvNm &&
- a.sggNm === b.sggNm &&
- a.vrfcTrgtNm === b.vrfcTrgtNm &&
- a.vrfcMthdCd === b.vrfcMthdCd
- );
-}
-
-function useGridCheckboxSelection(
- sourceRows: T[],
- isSameRow: (a: T, b: T) => boolean,
- setSelected: Dispatch>,
-) {
- const handleItemChecked = useCallback(
- (itemIndex: number, checked: boolean) => {
- const origin = sourceRows[itemIndex];
- if (origin === undefined) return;
- setSelected((prev) => {
- if (checked) {
- if (prev.some((r) => isSameRow(r, origin))) return prev;
- return [...prev, origin];
- }
- return prev.filter((r) => !isSameRow(r, origin));
- });
- },
- [sourceRows, isSameRow, setSelected],
- );
-
- const handleAllChecked = useCallback(
- (checked: boolean) => {
- if (checked) setSelected([...sourceRows]);
- else setSelected([]);
- },
- [sourceRows, setSelected],
- );
-
- return { handleItemChecked, handleAllChecked };
-}
-
-const DEFAULT_FILTERS: StatisticsVerificationFilterState = {
- ctpvNm: null,
- sggNm: null,
- statsYr: String(dayjs().year() - 1),
- sewerBzmnCd: null,
- statsCd: null,
-};
-
-const DEFAULT_SUB_FILTERS: StatisticsVerificationSubFilterState = {
- ...DEFAULT_FILTERS,
- prcsYnList: "1,2,3",
- pbcpAprvYn: "N",
-};
-
-const STATUS_OPTIONS = [
- { label: "수정완료", value: "1" },
- { label: "예외통과", value: "2" },
- { label: "반려", value: "3" },
-];
-
-const APPROVAL_STATUS_OPTIONS = [
- { label: "승인", value: "Y" },
- { label: "미승인", value: "N" },
-];
-
-function StatisticsVerificationReport() {
- const userInfo = useUserStore((state) => state.userInfo);
- const { setMessage: alert } = useAlertStore((state) => state);
- const { confirm } = useConfirm();
- const [filters, setFilters] =
- useState(DEFAULT_FILTERS);
- const [subFilters, setSubFilters] =
- useState(DEFAULT_SUB_FILTERS);
- const [submittedMainFilters, setSubmittedMainFilters] =
- useState(DEFAULT_FILTERS);
- const [submittedDetailParams, setSubmittedDetailParams] = useState<{
- main: StatisticsVerificationFilterState;
- sub: StatisticsVerificationSubFilterState;
- }>({
- main: DEFAULT_FILTERS,
- sub: DEFAULT_SUB_FILTERS,
- });
- const [selectedSummaryRows, setSelectedSummaryRows] = useState<
- StatsInputStatusList[]
- >([]);
- const [selectedDetailRows, setSelectedDetailRows] = useState<
- VerifyResultItem[]
- >([]);
-
- const { data: sidoData } = useStAnlsSidoCombo();
- const { data: sigunguData } = useStAnlsSigunguCombo(
- filters.sewerBzmnCd ?? "",
- );
-
- const statisticsVerificationReportQuery =
- useStatsVrfcRptData(submittedMainFilters);
- const statisticsVerificationResultQuery = useStatsVrfcRsltData(
- submittedDetailParams,
- );
-
- const statisticsVerificationReportData =
- statisticsVerificationReportQuery.data ?? [];
- const statisticsVerificationReportGridRows = useMemo(
- () => toGridRows(statisticsVerificationReportData),
- [statisticsVerificationReportData],
- );
- const statisticsVerificationResultData = useMemo(
- () =>
- statisticsVerificationResultQuery.data?.pages.flatMap(
- (page) => page.verifyResultList ?? [],
- ) ?? [],
- [statisticsVerificationResultQuery.data],
- );
- const statisticsVerificationResultGridRows = useMemo(
- () => toGridRows(statisticsVerificationResultData),
- [statisticsVerificationResultData],
- );
-
- const isLoading =
- statisticsVerificationReportQuery.isFetching ||
- statisticsVerificationResultQuery.isFetching;
- const isAppendingDetail =
- statisticsVerificationResultQuery.isFetchingNextPage;
- const canLoadMoreDetail = Boolean(
- statisticsVerificationResultQuery.hasNextPage,
- );
-
- const {
- handleItemChecked: handleReportItemChecked,
- handleAllChecked: handleReportAllChecked,
- } = useGridCheckboxSelection(
- statisticsVerificationReportData,
- isSameStatsInputStatusRow,
- setSelectedSummaryRows,
- );
-
- const {
- handleItemChecked: handleResultItemChecked,
- handleAllChecked: handleResultAllChecked,
- } = useGridCheckboxSelection(
- statisticsVerificationResultData,
- isSameVerifyResultRow,
- setSelectedDetailRows,
- );
-
- const { mutateAsync: onApproveStats } = useMutationWrapper({
- mutationFn: (approvalRequests: ApprovalRequest[]) =>
- statisticsApprovalApi.approveStats(approvalRequests),
- onSuccess: (data) => {
- alert(data.message ?? "승인이 완료되었습니다.");
- },
- });
-
- useEffect(() => {
- if (!statisticsVerificationReportQuery.isError) return;
- alert("통계검증리포트 조회 중 오류가 발생했습니다.");
- setSelectedSummaryRows([]);
- }, [
- alert,
- statisticsVerificationReportQuery.errorUpdatedAt,
- statisticsVerificationReportQuery.isError,
- ]);
-
- function handleSearch(
- nextFilters: StatisticsVerificationFilterState,
- nextSubFilters: StatisticsVerificationSubFilterState,
- ) {
- setSelectedSummaryRows([]);
- setSelectedDetailRows([]);
- setSubmittedMainFilters({ ...nextFilters });
- setSubmittedDetailParams({
- main: { ...nextFilters },
- sub: { ...nextSubFilters },
- });
- }
-
- async function handleLoadMoreDetail() {
- if (isLoading || isAppendingDetail || !canLoadMoreDetail) return;
-
- try {
- await statisticsVerificationResultQuery.fetchNextPage();
- } catch {
- alert("추가 데이터를 불러오는 중 오류가 발생했습니다.");
- }
- }
-
- function handleDetailSearchByAreaC() {
- setSelectedDetailRows([]);
- setSubmittedDetailParams({
- main: { ...filters },
- sub: { ...subFilters },
- });
- }
-
- function handleFilterChange<
- K extends keyof StatisticsVerificationFilterState,
- >(key: K) {
- return (
- value?: StatisticsVerificationFilterState[K],
- optionData?: { label: string; value: string },
- ) => {
- if (key === "sewerBzmnCd") {
- setFilters((prev) => ({
- ...prev,
- ctpvNm: optionData?.label,
- sewerBzmnCd: optionData?.value,
- sggNm: "",
- }));
- return;
- }
- setFilters((prev) => ({ ...prev, [key]: value }));
- };
- }
-
- function handleSubFilterChange<
- K extends keyof StatisticsVerificationSubFilterState,
- >(key: K) {
- return (value?: StatisticsVerificationSubFilterState[K]) => {
- setSubFilters((prev) => ({ ...prev, [key]: value }));
- };
- }
-
- function handleReset() {
- setFilters(DEFAULT_FILTERS);
- setSubFilters(DEFAULT_SUB_FILTERS);
- setSelectedSummaryRows([]);
- setSelectedDetailRows([]);
- handleSearch(DEFAULT_FILTERS, DEFAULT_SUB_FILTERS);
- }
-
- async function handleApprove() {
- const commonParam = {
- statsYr: filters.statsYr,
- sewerBzmnCd: filters.sewerBzmnCd ?? "",
- statsCd: filters.statsCd ?? "",
- mdfrId: userInfo?.userUnqId ?? "",
- };
- const approvalRequests = selectedSummaryRows.map((row) => ({
- ...commonParam,
- rjctOpnnCn: row.rjctOpnnCn ?? "",
- lastCfmtnPicNm: row.laePicNm ?? "",
- lastCfmtnPicTelNo: row.laePicTelNo ?? "",
- lastCfmtnPicDeptNm: row.laeKbrdrDeptNm ?? "",
- lastCfmtnPicJbgdNm: row.laeKbrdrJbgdNm ?? "",
- }));
- try {
- if (await confirm("승인하시겠습니까?")) {
- await onApproveStats(approvalRequests);
- }
- } catch {
- alert("승인 중 오류가 발생했습니다.");
- }
- }
-
- function handleReject() {}
-
- return (
-
-
-
-
({
- label: item.adstNm,
- value: item.adstCd,
- })) ?? []
- }
- />
- ({
- label: item.adstNm,
- value: item.adstCd,
- })) ?? []
- }
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{}}
- showHeaderCheckbox={true}
- gridHeight={30}
- />
-
-
- 검증 결과
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{}}
- showHeaderCheckbox={true}
- />
-
- {(isLoading || isAppendingDetail) && (
-
- )}
-
-
- );
-}
-
-interface FilterSelectProps {
- label: string;
- onChange: (
- value?: string,
- optionData?: { label: string; value: string },
- ) => void;
- options: Array<{ label: string; value: string }>;
- value?: string;
-}
-
-function FilterCombobox({
- label,
- onChange,
- options,
- value,
-}: FilterSelectProps) {
- const anchor = useComboboxAnchor();
- const items = useMemo(
- () => options.map((option) => option.value),
- [options],
- );
- const selectedValues = useMemo(() => {
- if (!value) return [];
- return value.split(",").filter(Boolean);
- }, [value]);
-
- return (
-
-
- {
- if (next == null) {
- onChange(undefined);
- return;
- }
- const list = Array.isArray(next) ? next : [next];
- onChange(list.length > 0 ? list.join(",") : undefined);
- }}
- >
-
-
- {(values: string[]) => (
- <>
- {values.map((v) => (
-
- {options.find((o) => o.value === v)
- ?.label ?? v}
-
- ))}
-
- >
- )}
-
-
-
- 검색 결과가 없습니다.
-
- {(item: string) => (
-
- {options.find((o) => o.value === item)?.label ??
- item}
-
- )}
-
-
-
-
- );
-}
-
-function FilterSelect({ label, onChange, options, value }: FilterSelectProps) {
- return (
-
-
-
-
- );
-}
-
-export default StatisticsVerificationReport;
+"use client";
+
+import type { Dispatch, SetStateAction } from "react";
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+
+import { useConfirm } from "@frontend-opensource/use-react-hooks";
+import dayjs from "dayjs";
+import type { RealGridReact } from "realgrid-react";
+
+import { useAlertStore, useMutationWrapper, useUserStore } from "@/shared/lib";
+import { CodeSelect } from "@/entities/code";
+import {
+ type ApproveRequest,
+ type RejectRequest,
+ statisticsApprovalApi,
+ type StatisticsVerificationFilterState,
+ statisticsVerificationReportColumnInfo,
+ statisticsVerificationResultColumnInfo,
+ type StatisticsVerificationSubFilterState,
+ type StatsInputStatusList,
+ useStAnlsSidoCombo,
+ useStAnlsSigunguCombo,
+ useStatsVrfcRptData,
+ useStatsVrfcRsltData,
+ type VerifyResultItem,
+} from "@/entities/statistics";
+import {
+ Button,
+ Combobox,
+ ComboboxChip,
+ ComboboxChips,
+ ComboboxChipsInput,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxValue,
+ Label,
+ LoadingWithAnimation,
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+ useComboboxAnchor,
+} from "@common/components";
+
+import DataGrid from "@/components/module/DataGrid";
+import type { CellEditedCallbackParams } from "@/components/type/DataGrid.type";
+import { toGridRows } from "@/components/util/grid/gridFunction";
+
+const getYearOptions = () => {
+ const currentYear = dayjs().year();
+ const yearOptionsRange = Array.from(
+ { length: currentYear - 2017 },
+ (_, i) => {
+ const year = 2017 + i;
+ return { label: String(year), value: String(year) };
+ },
+ );
+ return yearOptionsRange.map((year) => ({
+ label: year.label,
+ value: year.value,
+ }));
+};
+
+function isSameStatsInputStatusRow(
+ a: StatsInputStatusList,
+ b: StatsInputStatusList,
+): boolean {
+ return (
+ a.ctpvNm === b.ctpvNm && a.sggNm === b.sggNm && a.statsCd === b.statsCd
+ );
+}
+
+function isSameVerifyResultRow(
+ a: VerifyResultItem,
+ b: VerifyResultItem,
+): boolean {
+ if (a.vrfcSn != null && b.vrfcSn != null) return a.vrfcSn === b.vrfcSn;
+ return (
+ a.statsYr === b.statsYr &&
+ a.statsCd === b.statsCd &&
+ a.ctpvNm === b.ctpvNm &&
+ a.sggNm === b.sggNm &&
+ a.vrfcTrgtNm === b.vrfcTrgtNm &&
+ a.vrfcMthdCd === b.vrfcMthdCd
+ );
+}
+
+function useGridCheckboxSelection(
+ sourceRows: T[],
+ isSameRow: (a: T, b: T) => boolean,
+ setSelected: Dispatch>,
+) {
+ const handleItemChecked = useCallback(
+ (itemIndex: number, checked: boolean) => {
+ const origin = sourceRows[itemIndex];
+ if (origin === undefined) return;
+ setSelected((prev) => {
+ if (checked) {
+ if (prev.some((r) => isSameRow(r, origin))) return prev;
+ return [...prev, origin];
+ }
+ return prev.filter((r) => !isSameRow(r, origin));
+ });
+ },
+ [sourceRows, isSameRow, setSelected],
+ );
+
+ const handleAllChecked = useCallback(
+ (checked: boolean) => {
+ if (checked) setSelected([...sourceRows]);
+ else setSelected([]);
+ },
+ [sourceRows, setSelected],
+ );
+
+ return { handleItemChecked, handleAllChecked };
+}
+
+const DEFAULT_FILTERS: StatisticsVerificationFilterState = {
+ ctpvNm: null,
+ sggNm: null,
+ statsYr: String(dayjs().year() - 1),
+ sewerBzmnCd: null,
+ statsCd: null,
+};
+
+const DEFAULT_SUB_FILTERS: StatisticsVerificationSubFilterState = {
+ ...DEFAULT_FILTERS,
+ prcsYnList: "1,2,3",
+ pbcpAprvYn: "N",
+};
+
+const STATUS_OPTIONS = [
+ { label: "수정완료", value: "1" },
+ { label: "예외통과", value: "2" },
+ { label: "반려", value: "3" },
+];
+
+const APPROVAL_STATUS_OPTIONS = [
+ { label: "승인", value: "Y" },
+ { label: "미승인", value: "N" },
+];
+
+function StatisticsVerificationReport() {
+ const userInfo = useUserStore((state) => state.userInfo);
+ const { setMessage: alert } = useAlertStore((state) => state);
+ const { confirm } = useConfirm();
+ const [filters, setFilters] =
+ useState(DEFAULT_FILTERS);
+ const [subFilters, setSubFilters] =
+ useState(DEFAULT_SUB_FILTERS);
+ const [submittedFilters, setSubmittedFilters] =
+ useState(DEFAULT_FILTERS);
+ const [submittedParams, setSubmittedParams] = useState<{
+ main: StatisticsVerificationFilterState;
+ sub: StatisticsVerificationSubFilterState;
+ }>({
+ main: DEFAULT_FILTERS,
+ sub: DEFAULT_SUB_FILTERS,
+ });
+ const [selectedReportRows, setSelectedReportRows] = useState<
+ StatsInputStatusList[]
+ >([]);
+ const [selectedResultRows, setSelectedResultRows] = useState<
+ VerifyResultItem[]
+ >([]);
+ const editedResultRowMapRef = useRef