diff --git a/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx b/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx index 4da13d0e2..831fa6057 100644 --- a/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx +++ b/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx @@ -180,7 +180,8 @@ const HbStatisticsVerification = () => { const params: StAnlsMstSearchParams = { page: historyPagination.pageIndex, size: historyPagination.pageSize, - sort: "anlsSn,desc", + sort: "anlsSn,desc", + vrfcMthdCd: "HB", }; if (appliedHistoryDateRange?.from) { diff --git a/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx b/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx index caef0180b..b852b1496 100644 --- a/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx +++ b/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx @@ -1,11 +1,22 @@ "use client"; -import DataGrid from "@/components/module/DataGrid"; +import { useState } from "react"; + +import { useConfirm } from "@frontend-opensource/use-react-hooks"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; + +import { ENDPOINT } from "@/shared/config"; +import { CodeSelect } from "@/entities/code/ui/code-select"; +import { verificationTargetManagementApi } from "@/entities/statistics/api/verification-target-management-service"; import { hbArticleColumnInfo, imrArticleColumnInfo, validationArticleColumnInfo, } from "@/entities/statistics/model/verification-article-column"; +import type { + VerificationTargetManagementResponse, + VerificationTargetManagementSearchParams, +} from "@/entities/statistics/model/verification-target-management-interface"; import { Button, Input, @@ -15,17 +26,10 @@ import { TabsList, TabsTrigger, } from "@common/components"; -import { CodeSelect } from "@/entities/code/ui/code-select"; -import { verificationTargetManagementApi } from "@/entities/statistics/api/verification-target-management-service"; -import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { useState } from "react"; -import { ENDPOINT } from "@/shared/config"; -import type { - VerificationTargetManagementSearchParams, - VerificationTargetManagementResponse, -} from "@/entities/statistics/model/verification-target-management-interface"; + import { VerificationTargetDialog } from "./VerificationTargetDialog"; -import { useConfirm } from "@frontend-opensource/use-react-hooks"; + +import DataGrid from "@/components/module/DataGrid"; const TAB_CONFIG = { HB: { value: "HB", label: "H-B", columnInfo: hbArticleColumnInfo }, diff --git a/apps/st/src/components/statistics/verification/detail/HbVerificationDetail.tsx b/apps/st/src/components/statistics/verification/detail/HbVerificationDetail.tsx index 359b25a67..71f4f28c8 100644 --- a/apps/st/src/components/statistics/verification/detail/HbVerificationDetail.tsx +++ b/apps/st/src/components/statistics/verification/detail/HbVerificationDetail.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; +import type { StAnlsDtlResponse } from "@/entities/statistics/model/statistics-analysis-detail-interface"; import { Button } from "@common/components"; import Indicators from "./Indicators"; @@ -20,6 +21,18 @@ const HbVerificationDetail: React.FC = ({ null, ); const [selectedSido, setSelectedSido] = useState(null); + const [selectedTargetInfo, setSelectedTargetInfo] = useState<{ + statsNm: string; + vrfcTrgtNm: string; + } | null>(null); + + const handleTargetSelect = (row: StAnlsDtlResponse) => { + setSelectedVrfcTrgtSn(String(row.vrfcTrgtSn)); + setSelectedTargetInfo({ + statsNm: row.statsNm, + vrfcTrgtNm: row.vrfcTrgtNm, + }); + }; return (
@@ -44,7 +57,7 @@ const HbVerificationDetail: React.FC = ({
@@ -57,6 +70,10 @@ const HbVerificationDetail: React.FC = ({ diff --git a/apps/st/src/components/statistics/verification/detail/RegionalGrid.tsx b/apps/st/src/components/statistics/verification/detail/RegionalGrid.tsx index d1dafcd88..7b8d16a5d 100644 --- a/apps/st/src/components/statistics/verification/detail/RegionalGrid.tsx +++ b/apps/st/src/components/statistics/verification/detail/RegionalGrid.tsx @@ -23,6 +23,8 @@ import type { ColumnInfo } from "@/components/type/DataGrid.type"; interface RegionalGridProps { anlsSn: number; vrfcTrgtSn: string | null; + statsNm: string; + vrfcTrgtNm: string; selectedSido: string | null; onSidoSelect: (sido: string | null) => void; } @@ -36,6 +38,8 @@ interface AppliedFilter { const RegionalGrid: React.FC = ({ anlsSn, vrfcTrgtSn, + statsNm, + vrfcTrgtNm, selectedSido, onSidoSelect, }) => { @@ -48,6 +52,7 @@ const RegionalGrid: React.FC = ({ gugun: "", status: "", }); + const [isDownloading, setIsDownloading] = useState(false); const [gridRowData, setGridRowData] = useState< Record[] @@ -256,6 +261,31 @@ const RegionalGrid: React.FC = ({ setShowAllOnEmptyFilter(true); }; + const handleDownload = async () => { + if (!vrfcTrgtSn) return; + setIsDownloading(true); + + try { + const blob = await stAnlsRsltApi.downloadExcel( + anlsSn, + Number(vrfcTrgtSn), + ); + + const url = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `분석결과_${statsNm}-${vrfcTrgtNm}.xlsx`; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } catch (error) { + console.error("Failed to download excel", error); + } finally { + setIsDownloading(false); + } + }; + return (
@@ -310,8 +340,20 @@ const RegionalGrid: React.FC = ({ 초기화 -
diff --git a/apps/st/src/components/statistics/verification/detail/ScatterChart.tsx b/apps/st/src/components/statistics/verification/detail/ScatterChart.tsx index be23841b1..2da038fcd 100644 --- a/apps/st/src/components/statistics/verification/detail/ScatterChart.tsx +++ b/apps/st/src/components/statistics/verification/detail/ScatterChart.tsx @@ -6,6 +6,7 @@ import { Chart as ChartJS, Legend, LinearScale, + LineController, LineElement, PointElement, ScatterController, @@ -21,11 +22,12 @@ import { LoadingWithAnimation } from "@common/components"; ChartJS.register( LinearScale, - PointElement, + LineController, LineElement, - Tooltip, - Legend, + PointElement, ScatterController, + Legend, + Tooltip, zoomPlugin, ); diff --git a/apps/st/src/components/statistics/verification/detail/VerificationList.tsx b/apps/st/src/components/statistics/verification/detail/VerificationList.tsx index 9d28b7164..5c2f89065 100644 --- a/apps/st/src/components/statistics/verification/detail/VerificationList.tsx +++ b/apps/st/src/components/statistics/verification/detail/VerificationList.tsx @@ -16,7 +16,7 @@ import { DataTable } from "@common/components"; interface VerificationListProps { anlsSn: number; selectedVrfcTrgtSn: string | null; - onSelect: (vrfcTrgtSn: string) => void; + onSelect: (row: StAnlsDtlResponse) => void; } const VerificationList: React.FC = ({ @@ -101,7 +101,9 @@ const VerificationList: React.FC = ({ data: rowData, columns, state: { - rowSelection: selectedVrfcTrgtSn ? { [selectedVrfcTrgtSn]: true } : {}, + rowSelection: selectedVrfcTrgtSn + ? { [selectedVrfcTrgtSn]: true } + : {}, }, enableMultiRowSelection: false, getRowId: (row) => String(row.vrfcTrgtSn), @@ -109,13 +111,13 @@ const VerificationList: React.FC = ({ }); const handleRowClick = (row: StAnlsDtlResponse) => { - onSelect(String(row.vrfcTrgtSn)); + onSelect(row); }; useEffect(() => { if (!selectedVrfcTrgtSn && rowData.length > 0) { - const firstTargetSn = rowData[0]?.vrfcTrgtSn; - if (firstTargetSn) onSelect(String(firstTargetSn)); + const firstRow = rowData[0]; + if (firstRow) onSelect(firstRow); } }, [selectedVrfcTrgtSn, rowData, onSelect]); @@ -132,13 +134,15 @@ const VerificationList: React.FC = ({ )} {!isLoading && rowData.length > 0 && ( - +
+ +
)} ); diff --git a/apps/st/src/entities/statistics/api/statistics-analysis-result-api.ts b/apps/st/src/entities/statistics/api/statistics-analysis-result-api.ts index 604e4144a..e8e40f0d2 100644 --- a/apps/st/src/entities/statistics/api/statistics-analysis-result-api.ts +++ b/apps/st/src/entities/statistics/api/statistics-analysis-result-api.ts @@ -31,6 +31,20 @@ export class StAnlsRsltApiService { return response.data; } + + public async downloadExcel( + anlsSn: number, + vrfcTrgtSn: number, + ): Promise { + const response = await client.get( + `${ENDPOINT.STATVERIFY_SERVICE.ST_ANLS_RSLT}/excel-down/${anlsSn}/${vrfcTrgtSn}`, + { + responseType: "blob", + }, + ); + + return response.data; + } } export const stAnlsRsltApi = new StAnlsRsltApiService(); diff --git a/apps/st/src/entities/statistics/model/analysis-history-interface.ts b/apps/st/src/entities/statistics/model/analysis-history-interface.ts index 3ba448b16..ee31b936d 100644 --- a/apps/st/src/entities/statistics/model/analysis-history-interface.ts +++ b/apps/st/src/entities/statistics/model/analysis-history-interface.ts @@ -21,6 +21,7 @@ export interface StAnlsMstSearchParams extends PageableParams { jobUuid?: string; verifyDtStart?: string; verifyDtEnd?: string; + vrfcMthdCd?: string; } export interface StAnlsOutlierDataResponse { diff --git a/apps/st/src/entities/statistics/model/verification-article-column.ts b/apps/st/src/entities/statistics/model/verification-article-column.ts index c62156730..e9e237338 100644 --- a/apps/st/src/entities/statistics/model/verification-article-column.ts +++ b/apps/st/src/entities/statistics/model/verification-article-column.ts @@ -1,5 +1,5 @@ -import { ValueType } from "realgrid"; import type { ColumnInfo } from "@rsone/components"; +import { ValueType } from "realgrid"; export const hbArticleColumnInfo: ColumnInfo = { columns: [ @@ -31,6 +31,15 @@ export const hbArticleColumnInfo: ColumnInfo = { editable: false, sortdisable: false, }, + { + name: "ipcrCntVl", + fieldName: "ipcrCntVl", + header: { text: "μ" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.##", + }, { name: "pctlCrtrVl", fieldName: "pctlCrtrVl", @@ -78,6 +87,7 @@ export const hbArticleColumnInfo: ColumnInfo = { "vrfcTrgtNm", "tblNm", "colNm", + "ipcrCntVl", "pctlCrtrVl", "scopCntCntVl", "thrsCntVl",