[st] feat: 검증 결과 상세 그리드 및 차트 데이터 동기화

This commit is contained in:
2026-03-13 14:51:58 +09:00
parent 6b28c4e332
commit f575e3b677
3 changed files with 58 additions and 32 deletions
@@ -13,6 +13,12 @@ interface HbVerificationDetailProps {
onBack: () => void;
}
export interface AppliedFilter {
sido: string | null;
gugun: string;
status: string;
}
const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
anlsSn,
onBack,
@@ -20,7 +26,11 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
const [selectedVrfcTrgtSn, setSelectedVrfcTrgtSn] = useState<string | null>(
null,
);
const [selectedSido, setSelectedSido] = useState<string | null>(null);
const [appliedFilter, setAppliedFilter] = useState<AppliedFilter>({
sido: "",
gugun: "",
status: "",
});
const [selectedRowId, setSelectedRowId] = useState<number | null>(null);
const [selectedTargetInfo, setSelectedTargetInfo] = useState<{
statsNm: string;
@@ -34,6 +44,11 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
vrfcTrgtNm: row.vrfcTrgtNm,
});
setSelectedRowId(null);
setAppliedFilter({
sido: "",
gugun: "",
status: "",
});
};
return (
@@ -76,8 +91,9 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
vrfcTrgtNm={
selectedTargetInfo?.vrfcTrgtNm || ""
}
onSidoSelect={setSelectedSido}
onFilterChange={setAppliedFilter}
selectedRowId={selectedRowId}
appliedFilter={appliedFilter}
/>
</div>
<div className="flex flex-[0.5] flex-col gap-4 p-4 pt-[4.8rem]">
@@ -89,7 +105,7 @@ const HbVerificationDetail: React.FC<HbVerificationDetailProps> = ({
<ScatterChart
anlsSn={anlsSn}
vrfcTrgtSn={selectedVrfcTrgtSn}
selectedSido={selectedSido}
appliedFilter={appliedFilter}
onPointClick={setSelectedRowId}
/>
</div>
@@ -18,6 +18,8 @@ import {
SelectValue,
} from "@common/components";
import type { AppliedFilter } from "./HbVerificationDetail";
import DataGrid from "@/components/module/DataGrid";
import type { ColumnInfo } from "@/components/type/DataGrid.type";
@@ -26,14 +28,9 @@ interface RegionalGridProps {
vrfcTrgtSn: string | null;
statsNm: string;
vrfcTrgtNm: string;
onSidoSelect: (sido: string | null) => void;
onFilterChange: (filter: AppliedFilter) => void;
selectedRowId?: number | null;
}
interface AppliedFilter {
sido: string | null;
gugun: string;
status: string;
appliedFilter: AppliedFilter;
}
const RegionalGrid: React.FC<RegionalGridProps> = ({
@@ -41,19 +38,15 @@ const RegionalGrid: React.FC<RegionalGridProps> = ({
vrfcTrgtSn,
statsNm,
vrfcTrgtNm,
onSidoSelect,
onFilterChange,
selectedRowId,
appliedFilter,
}) => {
const [selectedSido, setSelectedSido] = useState<string>("");
const [selectedGugun, setSelectedGugun] = useState<string>("");
const [selectedStatus, setSelectedStatus] = useState<string>("");
const [showAllOnEmptyFilter, setShowAllOnEmptyFilter] =
useState<boolean>(true);
const [appliedFilter, setAppliedFilter] = useState<AppliedFilter>({
sido: "",
gugun: "",
status: "",
});
const [isDownloading, setIsDownloading] = useState<boolean>(false);
const [gridRowData, setGridRowData] = useState<
@@ -244,8 +237,7 @@ const RegionalGrid: React.FC<RegionalGridProps> = ({
};
const handleSearch = () => {
onSidoSelect(selectedSido);
setAppliedFilter({
onFilterChange({
sido: selectedSido,
gugun: selectedGugun,
status: selectedStatus,
@@ -254,11 +246,10 @@ const RegionalGrid: React.FC<RegionalGridProps> = ({
};
const handleReset = () => {
onSidoSelect(null);
setSelectedSido("");
setSelectedGugun("");
setSelectedStatus("");
setAppliedFilter({
onFilterChange({
sido: "",
gugun: "",
status: "",
@@ -379,10 +370,10 @@ const RegionalGrid: React.FC<RegionalGridProps> = ({
columnInfo={columnInfo}
rowData={gridRowData}
setRowData={setGridRowData}
idFieldName="rsltSn"
isExcelExport={false}
isExcelImport={false}
highlightedRowId={selectedRowId}
idFieldName="rsltSn"
/>
)}
</div>
@@ -26,6 +26,8 @@ import {
import type { StAnlsRsltResponse } from "@/entities/statistics/model/statistics-analysis-result-interface";
import { LoadingWithAnimation } from "@common/components";
import type { AppliedFilter } from "./HbVerificationDetail";
ChartJS.register(
LinearScale,
LineController,
@@ -40,7 +42,7 @@ ChartJS.register(
interface ScatterChartProps {
anlsSn: number;
vrfcTrgtSn: string | null;
selectedSido: string | null;
appliedFilter: AppliedFilter;
onPointClick?: (rsltSn: number | null) => void;
}
@@ -56,7 +58,7 @@ interface DataPoint extends LinePoint {
const ScatterChart: React.FC<ScatterChartProps> = ({
anlsSn,
vrfcTrgtSn,
selectedSido,
appliedFilter,
onPointClick,
}) => {
const { data: regionCodes } = useQuery({
@@ -64,12 +66,17 @@ const ScatterChart: React.FC<ScatterChartProps> = ({
queryFn: () => CodeApi.getCode("LAESECD"),
});
const selectedSidoName = useMemo(() => {
if (!selectedSido || !regionCodes) return null;
return (
regionCodes.find((c) => c.lwpoCd === selectedSido)?.lwpoCdNm || null
);
}, [regionCodes, selectedSido]);
const filterNames = useMemo(() => {
if (!regionCodes) return { sido: null, gugun: null };
return {
sido:
regionCodes.find((c) => c.lwpoCd === appliedFilter.sido)
?.lwpoCdNm || null,
gugun:
regionCodes.find((c) => c.lwpoCd === appliedFilter.gugun)
?.lwpoCdNm || null,
};
}, [regionCodes, appliedFilter.sido, appliedFilter.gugun]);
const { data: resultData, isLoading: isLoadingGrid } = useStAnlsRsltList(
anlsSn,
@@ -85,7 +92,7 @@ const ScatterChart: React.FC<ScatterChartProps> = ({
const chartConfig = useMemo(() => {
if (!resultData || !chartData) return null;
const rawPoints = resultData.content ?? [];
const rawPoints = (resultData.content ?? []) as StAnlsRsltResponse[];
const boundaries = chartData.list ?? [];
const sortedBoundaries = [...boundaries].sort(
@@ -106,7 +113,19 @@ const ScatterChart: React.FC<ScatterChartProps> = ({
const outlierPoints: DataPoint[] = [];
rawPoints.forEach((item) => {
if (selectedSidoName && item.sido !== selectedSidoName) {
// Apply Filters (Sido, Gugun, Status)
if (filterNames.sido && item.sido !== filterNames.sido) {
return;
}
if (filterNames.gugun && !filterNames.gugun.includes(item.gugun)) {
return;
}
if (
appliedFilter.status &&
item.otlrYn.toLowerCase() !== appliedFilter.status
) {
return;
}
@@ -230,7 +249,7 @@ const ScatterChart: React.FC<ScatterChartProps> = ({
};
return { data, options };
}, [resultData, chartData, selectedSidoName]);
}, [resultData, chartData, filterNames, appliedFilter.status]);
return (
<div className="relative flex-1 p-4">