[st] feat: 통계 검증 상세 테이블 체크박스 기능 추가
This commit is contained in:
@@ -26,6 +26,7 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
|
||||
const [selectedVrfcTrgtSn, setSelectedVrfcTrgtSn] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const [checkedSns, setCheckedSns] = useState<string[]>([]);
|
||||
const [appliedFilter, setAppliedFilter] = useState<AppliedFilter>({
|
||||
sido: "",
|
||||
gugun: "",
|
||||
@@ -75,6 +76,8 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
|
||||
anlsSn={anlsSn}
|
||||
selectedVrfcTrgtSn={selectedVrfcTrgtSn}
|
||||
onSelect={handleTargetSelect}
|
||||
checkedSns={checkedSns}
|
||||
onCheck={setCheckedSns}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { ValueType } from "realgrid";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { CodeApi } from "@/entities/code/api/code-service";
|
||||
import { useStAnlsRsltList } from "@/entities/statistics/api/queries";
|
||||
import { stAnlsRsltApi } from "@/entities/statistics/api/statistics-analysis-result-api";
|
||||
import { regionalGridColumnInfo as columnInfo } from "@/entities/statistics/model/regional-grid-columns";
|
||||
import type { StAnlsRsltResponse } from "@/entities/statistics/model/statistics-analysis-result-interface";
|
||||
import {
|
||||
Button,
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
import type { AppliedFilter } from "./HbVerificationDetail";
|
||||
|
||||
import DataGrid from "@/components/module/DataGrid";
|
||||
import type { ColumnInfo } from "@/components/type/DataGrid.type";
|
||||
|
||||
interface RegionalGridProps {
|
||||
anlsSn: number;
|
||||
@@ -148,89 +147,6 @@ const RegionalGrid: React.FC<RegionalGridProps> = ({
|
||||
gugunOptions,
|
||||
]);
|
||||
|
||||
const columnInfo: ColumnInfo = useMemo(
|
||||
() => ({
|
||||
columns: [
|
||||
{
|
||||
name: "sido",
|
||||
fieldName: "sido",
|
||||
header: { text: "시도" },
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
name: "gugun",
|
||||
fieldName: "gugun",
|
||||
header: { text: "구군" },
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
name: "admdstNm",
|
||||
fieldName: "admdstNm",
|
||||
header: { text: "행정구역" },
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: "prvyrVl",
|
||||
fieldName: "prvyrVl",
|
||||
header: { text: "이전년도" },
|
||||
width: 80,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0",
|
||||
},
|
||||
{
|
||||
name: "cryrVl",
|
||||
fieldName: "cryrVl",
|
||||
header: { text: "당해년도" },
|
||||
width: 80,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0",
|
||||
},
|
||||
{
|
||||
name: "chgRt",
|
||||
fieldName: "chgRt",
|
||||
header: { text: "R" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "trsfRt",
|
||||
fieldName: "trsfRt",
|
||||
header: { text: "S" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "otlrTrsfRt",
|
||||
fieldName: "otlrTrsfRt",
|
||||
header: { text: "E" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "otlrYn",
|
||||
fieldName: "otlrYn",
|
||||
header: { text: "상태" },
|
||||
width: 60,
|
||||
},
|
||||
],
|
||||
columnLayout: [
|
||||
"sido",
|
||||
"gugun",
|
||||
"admdstNm",
|
||||
"prvyrVl",
|
||||
"cryrVl",
|
||||
"chgRt",
|
||||
"trsfRt",
|
||||
"otlrTrsfRt",
|
||||
"otlrYn",
|
||||
],
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
const handleSidoChange = (val: string) => {
|
||||
setSelectedSido(val);
|
||||
setSelectedGugun("");
|
||||
|
||||
@@ -2,44 +2,31 @@ import React, { useEffect, useMemo } from "react";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
type ColumnDef,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { stAnlsDtlApi } from "@/entities/statistics/api/statistics-analysis-detail-api";
|
||||
import { verificationTargetManagementApi } from "@/entities/statistics/api/verification-target-management-service";
|
||||
import type { StAnlsDtlResponse } from "@/entities/statistics/model/statistics-analysis-detail-interface";
|
||||
import { getVerificationListColumns } from "@/entities/statistics/model/verification-list-columns";
|
||||
import { DataTable } from "@common/components";
|
||||
|
||||
interface VerificationListProps {
|
||||
anlsSn: number;
|
||||
selectedVrfcTrgtSn: string | null;
|
||||
onSelect: (row: StAnlsDtlResponse) => void;
|
||||
checkedSns: string[];
|
||||
onCheck: (checkedSns: string[], rows: StAnlsDtlResponse[]) => void;
|
||||
}
|
||||
|
||||
const VerificationList: React.FC<VerificationListProps> = ({
|
||||
anlsSn,
|
||||
selectedVrfcTrgtSn,
|
||||
onSelect,
|
||||
checkedSns,
|
||||
onCheck,
|
||||
}) => {
|
||||
const { data: verificationTargetCodes } = useQuery({
|
||||
queryKey: [ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG, "codes"],
|
||||
queryFn: () =>
|
||||
verificationTargetManagementApi.getVerificationTargetCodes(),
|
||||
});
|
||||
|
||||
const targetCodeMap = useMemo(() => {
|
||||
const map = new Map<string, string>();
|
||||
if (verificationTargetCodes) {
|
||||
verificationTargetCodes.forEach((item) => {
|
||||
map.set(item.vrfcTrgtSn, item.vrfcTrgtNm);
|
||||
});
|
||||
}
|
||||
return map;
|
||||
}, [verificationTargetCodes]);
|
||||
|
||||
const { data: detailData, isLoading } = useQuery({
|
||||
queryKey: [ENDPOINT.STATVERIFY_SERVICE.ST_ANLS_DTL, "list", anlsSn],
|
||||
queryFn: () =>
|
||||
@@ -51,50 +38,9 @@ const VerificationList: React.FC<VerificationListProps> = ({
|
||||
return (detailData?.content ?? []) as StAnlsDtlResponse[];
|
||||
}, [detailData]);
|
||||
|
||||
const columns: ColumnDef<StAnlsDtlResponse>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
header: "통계 년도",
|
||||
accessorKey: "statsYr",
|
||||
},
|
||||
{
|
||||
header: "통계 항목",
|
||||
accessorKey: "statsNm",
|
||||
},
|
||||
{
|
||||
header: "검증 항목",
|
||||
accessorKey: "vrfcTrgtNm",
|
||||
},
|
||||
{
|
||||
header: "μ",
|
||||
accessorKey: "ipcrCntVl",
|
||||
},
|
||||
{
|
||||
header: "Percentile",
|
||||
accessorKey: "pctlCrtrVl",
|
||||
},
|
||||
{
|
||||
header: "A",
|
||||
accessorKey: "scopAjmtCntVl",
|
||||
},
|
||||
{
|
||||
header: "C",
|
||||
accessorKey: "thrsCntVl",
|
||||
},
|
||||
{
|
||||
header: "정상건수",
|
||||
accessorKey: "nmlDataNocs",
|
||||
},
|
||||
{
|
||||
header: "제외건수",
|
||||
accessorKey: "exclDataNocs",
|
||||
},
|
||||
{
|
||||
header: "이상건수",
|
||||
accessorKey: "otlrDataNocs",
|
||||
},
|
||||
],
|
||||
[targetCodeMap],
|
||||
const columns = useMemo(
|
||||
() => getVerificationListColumns({ rowData, checkedSns, onCheck }),
|
||||
[rowData, checkedSns, onCheck],
|
||||
);
|
||||
|
||||
const table = useReactTable({
|
||||
@@ -134,15 +80,13 @@ const VerificationList: React.FC<VerificationListProps> = ({
|
||||
</div>
|
||||
)}
|
||||
{!isLoading && rowData.length > 0 && (
|
||||
<div className="rounded-md border">
|
||||
<DataTable
|
||||
table={table}
|
||||
variant="secondary"
|
||||
onRowClick={handleRowClick}
|
||||
viewPagination={false}
|
||||
className="whitespace-nowrap text-[1.2rem] [&_td]:!px-2 [&_th]:!px-2"
|
||||
/>
|
||||
</div>
|
||||
<DataTable
|
||||
table={table}
|
||||
variant="secondary"
|
||||
onRowClick={handleRowClick}
|
||||
viewPagination={false}
|
||||
className="whitespace-nowrap text-[1.2rem] [&_td]:!px-2 [&_th]:!px-2"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { ValueType } from "realgrid";
|
||||
|
||||
import type { ColumnInfo } from "@/components/type/DataGrid.type";
|
||||
|
||||
export const regionalGridColumnInfo: ColumnInfo = {
|
||||
columns: [
|
||||
{
|
||||
name: "sido",
|
||||
fieldName: "sido",
|
||||
header: { text: "시도" },
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
name: "gugun",
|
||||
fieldName: "gugun",
|
||||
header: { text: "구군" },
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
name: "admdstNm",
|
||||
fieldName: "admdstNm",
|
||||
header: { text: "행정구역" },
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: "prvyrVl",
|
||||
fieldName: "prvyrVl",
|
||||
header: { text: "이전년도" },
|
||||
width: 80,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0",
|
||||
},
|
||||
{
|
||||
name: "cryrVl",
|
||||
fieldName: "cryrVl",
|
||||
header: { text: "당해년도" },
|
||||
width: 80,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0",
|
||||
},
|
||||
{
|
||||
name: "chgRt",
|
||||
fieldName: "chgRt",
|
||||
header: { text: "R" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "trsfRt",
|
||||
fieldName: "trsfRt",
|
||||
header: { text: "S" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "otlrTrsfRt",
|
||||
fieldName: "otlrTrsfRt",
|
||||
header: { text: "E" },
|
||||
width: 60,
|
||||
valueType: ValueType.NUMBER,
|
||||
dataFormat: "#,##0.00",
|
||||
},
|
||||
{
|
||||
name: "otlrYn",
|
||||
fieldName: "otlrYn",
|
||||
header: { text: "상태" },
|
||||
width: 60,
|
||||
},
|
||||
],
|
||||
columnLayout: [
|
||||
"sido",
|
||||
"gugun",
|
||||
"admdstNm",
|
||||
"prvyrVl",
|
||||
"cryrVl",
|
||||
"chgRt",
|
||||
"trsfRt",
|
||||
"otlrTrsfRt",
|
||||
"otlrYn",
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
import React from "react";
|
||||
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
import type { StAnlsDtlResponse } from "@/entities/statistics/model/statistics-analysis-detail-interface";
|
||||
import { Checkbox } from "@common/components";
|
||||
|
||||
interface GetVerificationListColumnsParams {
|
||||
rowData: StAnlsDtlResponse[];
|
||||
checkedSns: string[];
|
||||
onCheck: (checkedSns: string[], rows: StAnlsDtlResponse[]) => void;
|
||||
}
|
||||
|
||||
export const getVerificationListColumns = ({
|
||||
rowData,
|
||||
checkedSns,
|
||||
onCheck,
|
||||
}: GetVerificationListColumnsParams): ColumnDef<StAnlsDtlResponse>[] => [
|
||||
{
|
||||
id: "checkbox",
|
||||
header: () => {
|
||||
const isAllChecked =
|
||||
rowData.length > 0 && checkedSns.length === rowData.length;
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<Checkbox
|
||||
checked={isAllChecked}
|
||||
onCheckedChange={(value: boolean) => {
|
||||
if (value) {
|
||||
onCheck(
|
||||
rowData.map((r) => String(r.vrfcTrgtSn)),
|
||||
rowData,
|
||||
);
|
||||
} else {
|
||||
onCheck([], []);
|
||||
}
|
||||
}}
|
||||
aria-label="Select all rows"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const rowId = String(row.original.vrfcTrgtSn);
|
||||
const isChecked = checkedSns.includes(rowId);
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<Checkbox
|
||||
checked={isChecked}
|
||||
onCheckedChange={(value: boolean) => {
|
||||
const newCheckedSns = value
|
||||
? [...checkedSns, rowId]
|
||||
: checkedSns.filter((id) => id !== rowId);
|
||||
const newCheckedRows = rowData.filter((r) =>
|
||||
newCheckedSns.includes(String(r.vrfcTrgtSn)),
|
||||
);
|
||||
onCheck(newCheckedSns, newCheckedRows);
|
||||
}}
|
||||
onClick={(e: React.MouseEvent) => e.stopPropagation()}
|
||||
aria-label={`Select row ${rowId}`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
{
|
||||
header: "통계 년도",
|
||||
accessorKey: "statsYr",
|
||||
},
|
||||
{
|
||||
header: "통계 항목",
|
||||
accessorKey: "statsNm",
|
||||
},
|
||||
{
|
||||
header: "검증 항목",
|
||||
accessorKey: "vrfcTrgtNm",
|
||||
},
|
||||
{
|
||||
header: "μ",
|
||||
accessorKey: "ipcrCntVl",
|
||||
},
|
||||
{
|
||||
header: "Percentile",
|
||||
accessorKey: "pctlCrtrVl",
|
||||
},
|
||||
{
|
||||
header: "A",
|
||||
accessorKey: "scopAjmtCntVl",
|
||||
},
|
||||
{
|
||||
header: "C",
|
||||
accessorKey: "thrsCntVl",
|
||||
},
|
||||
{
|
||||
header: "정상건수",
|
||||
accessorKey: "nmlDataNocs",
|
||||
},
|
||||
{
|
||||
header: "제외건수",
|
||||
accessorKey: "exclDataNocs",
|
||||
},
|
||||
{
|
||||
header: "이상건수",
|
||||
accessorKey: "otlrDataNocs",
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user