[st] feat: 일반 검증 관리 -> 검증 항목 관리 탭으로 이동

This commit is contained in:
2026-03-30 17:05:02 +09:00
parent df4f3b296b
commit 2805e382b3
2 changed files with 216 additions and 168 deletions
@@ -1,30 +1,30 @@
"use client";
import { useState, useEffect, useMemo } from 'react';
import { CodeSelectWithAll } from '@/entities/code';
import {
Button,
Label,
Select,
SelectTrigger,
SelectContent,
SelectValue,
SelectItem,
DataTable,
} from "@common/components";
import { LoadingWithAnimation } from '@common/components';
import { NoData } from '@/shared/ui/no-data';
import DetailComponent from './generalVerification/DetailComponent';
import RegistDialog from './generalVerification/RegistDialog';
import { useEffect, useMemo, useState } from "react";
import { getCoreRowModel, useReactTable } from "@tanstack/react-table";
import { getGeneralVerificationColumns } from '@/components/util/column/management/GeneralVerificationColumn';
import type { GeneralverificationList } from '@/entities/statistics/model/general-verification-interface';
import { generalverificationApiService } from '@/entities/statistics/api/general-verification-service';
import { useAlertStore } from '@/shared/lib';
import { useAlertStore } from "@/shared/lib";
import { NoData } from "@/shared/ui/no-data";
import { CodeSelectWithAll } from "@/entities/code";
import { generalverificationApiService } from "@/entities/statistics/api/general-verification-service";
import type { GeneralverificationList } from "@/entities/statistics/model/general-verification-interface";
import {
Button,
DataTable,
Label,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@common/components";
import { LoadingWithAnimation } from "@common/components";
import DetailComponent from "./generalVerification/DetailComponent";
import RegistDialog from "./generalVerification/RegistDialog";
import { getGeneralVerificationColumns } from "@/components/util/column/management/GeneralVerificationColumn";
const GeneralVerificationManagement = () => {
const [searchValues, setSearchValues] = useState<{
@@ -32,12 +32,16 @@ const GeneralVerificationManagement = () => {
useYn: string;
vrfcClsfCd: string;
}>({
statsCd: '',
useYn: '',
vrfcClsfCd: '',
statsCd: "",
useYn: "",
vrfcClsfCd: "",
});
const [vrfcMasterData, setVrfcMasterData] = useState<GeneralverificationList[]>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
const [vrfcMasterData, setVrfcMasterData] = useState<
GeneralverificationList[]
>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>(
{},
);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [selectedVrfcRow, setSelectedVrfcRow] = useState<number | null>(null);
const [showRegistForm, setShowRegistForm] = useState<boolean>(false);
@@ -53,21 +57,26 @@ const GeneralVerificationManagement = () => {
trgtStatsCd: searchValues.statsCd,
vrfcClsfCd: searchValues.vrfcClsfCd,
useYn: searchValues.useYn,
}).filter(([, value]) => value !== '' && value !== 'ALL')
}).filter(([, value]) => value !== "" && value !== "ALL"),
);
const response = await generalverificationApiService.getGeneralverificationList(params);
const response =
await generalverificationApiService.getGeneralverificationList(
params,
);
if (response.status === 'success') {
if (response.status === "success") {
setVrfcMasterData(response.data);
setRowSelection({});
setSelectedVrfcRow(null);
setShowRegistForm(false);
} else {
alert(response.message || '데이터 조회 중 오류가 발생했습니다.');
alert(
response.message || "데이터 조회 중 오류가 발생했습니다.",
);
}
} catch {
alert('데이터 조회 중 오류가 발생했습니다.');
alert("데이터 조회 중 오류가 발생했습니다.");
} finally {
setIsLoading(false);
}
@@ -98,48 +107,67 @@ const GeneralVerificationManagement = () => {
setSelectedVrfcRow(null);
handleSearch();
setShowRegistForm(false);
}
};
useEffect(() => {
handleSearch();
}, []);
return (
<div className="h-full">
<div className="card card-border">
<div className="flex items-center gap-8 p-2">
<div className="flex items-center gap-2">
<Label className="text-label">
통계항목
</Label>
<>
<div className="card card-border !mx-0">
<div className="flex items-center gap-6 pl-2">
<div className="flex items-center gap-4">
<Label className="text-label">통계항목</Label>
<CodeSelectWithAll
upCd="STITEM"
value={searchValues.statsCd}
onValueChange={(value) => setSearchValues({ ...searchValues, statsCd: value })}
onValueChange={(value) =>
setSearchValues({
...searchValues,
statsCd: value,
})
}
placeholder="전체"
className="w-[16rem]"
/>
</div>
<div className="flex items-center gap-2">
<Label className="text-label">
검증분류
</Label>
<Select value={searchValues.vrfcClsfCd} onValueChange={(value) => setSearchValues({ ...searchValues, vrfcClsfCd: value })}>
<div className="flex items-center gap-4">
<Label className="text-label">검증분류</Label>
<Select
value={searchValues.vrfcClsfCd}
onValueChange={(value) =>
setSearchValues({
...searchValues,
vrfcClsfCd: value,
})
}
>
<SelectTrigger className="w-[10rem]">
<SelectValue placeholder="전체"></SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="ALL">전체</SelectItem>
<SelectItem value="DO_SI">도단위 검증</SelectItem>
<SelectItem value="SI_GU">시단위 검증</SelectItem>
<SelectItem value="DO_SI">
도단위 검증
</SelectItem>
<SelectItem value="SI_GU">
시단위 검증
</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex items-center gap-2">
<Label className="text-label">
사용여부
</Label>
<Select value={searchValues.useYn} onValueChange={(value) => setSearchValues({ ...searchValues, useYn: value })}>
<div className="flex items-center gap-4">
<Label className="text-label">사용여부</Label>
<Select
value={searchValues.useYn}
onValueChange={(value) =>
setSearchValues({
...searchValues,
useYn: value,
})
}
>
<SelectTrigger className="w-[10rem]">
<SelectValue placeholder="전체"></SelectValue>
</SelectTrigger>
@@ -150,53 +178,64 @@ const GeneralVerificationManagement = () => {
</SelectContent>
</Select>
</div>
<div className="flex items-center gap-2 ml-auto">
<Button color="green" className="h-[3.2rem] w-[96px]" type="button" onClick={handleReset}>
초기화
</Button>
<Button className="h-[3.2rem] w-[96px]" type="button" onClick={handleSearch}>
<div className="ml-auto flex items-center gap-2">
<Button
color="green"
className="h-[3.2rem]"
onClick={handleSearch}
>
조회
</Button>
</div>
</div>
</div>
<div className="card !my-0 flex flex-col !p-0">
<div className='flex items-center justify-end gap-[0.6rem] px-[1.2rem]'>
<RegistDialog open={showRegistForm} onOpenChange={setShowRegistForm} onSuccess={handleSearch}>
<Button className="h-[3.2rem] w-[96px]" type="button">
등록
<Button
color="gray"
className="h-[3.2rem]"
onClick={handleReset}
>
초기화
</Button>
</RegistDialog>
</div>
<div className="flex justify-center gap-5 !p-0 h-[65vh]">
<div className="card card-border w-1/2 !mx-0 flex flex-col">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">일반 검증 목록</h3>
</div>
<div className="card !m-4 h-full overflow-auto !p-0">
{isLoading && (
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
<div className="relative size-[5rem]">
<LoadingWithAnimation color="primary" />
</div>
</div>
)}
{isLoading ? null
:
vrfcMasterData.length > 0 ?
<DataTable table={table} onRowClick={(value) => handleVrfcMasterRowClick(value)} />
:
<div className="flex h-full items-center justify-center">
<NoData />
</div>
}
</div>
</div>
<DetailComponent selectedVrfcRow={selectedVrfcRow} />
</div>
</div>
</div>
<div className="flex h-[65vh] justify-center gap-5 !p-0">
<div className="card card-border !mx-0 flex w-1/2 flex-col">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
일반 검증 목록
</h3>
<RegistDialog
open={showRegistForm}
onOpenChange={setShowRegistForm}
onSuccess={handleSearch}
>
<Button>등록</Button>
</RegistDialog>
</div>
<div className="card !mx-2 !my-4 h-full overflow-auto !p-0">
{isLoading && (
<div className="[data-theme='black']:bg-transparent absolute inset-0 z-50 flex items-center justify-center rounded-lg p-10">
<div className="relative size-[5rem]">
<LoadingWithAnimation color="primary" />
</div>
</div>
)}
{isLoading ? null : vrfcMasterData.length > 0 ? (
<DataTable
table={table}
onRowClick={(value) =>
handleVrfcMasterRowClick(value)
}
/>
) : (
<div className="flex h-full items-center justify-center">
<NoData />
</div>
)}
</div>
</div>
<DetailComponent selectedVrfcRow={selectedVrfcRow} />
</div>
</>
);
};
export default GeneralVerificationManagement;
export default GeneralVerificationManagement;
@@ -19,6 +19,7 @@ import type {
} from "@/entities/statistics/model/verification-target-management-interface";
import {
Button,
cn,
Dialog,
DialogContent,
DialogFooter,
@@ -32,6 +33,7 @@ import {
TabsTrigger,
} from "@common/components";
import GeneralVerificationManagement from "./GeneralVerificationManagement";
import { VerificationTargetDialog } from "./VerificationTargetDialog";
import DataGrid from "@/components/module/DataGrid";
@@ -39,9 +41,9 @@ import DataGrid from "@/components/module/DataGrid";
const TAB_CONFIG = {
HB: { value: "HB", label: "H-B", columnInfo: hbArticleColumnInfo },
IMR: { value: "IMR", label: "I-MR", columnInfo: imrArticleColumnInfo },
VV: {
value: "VV",
label: "Validation",
GENERAL: {
value: "GENERAL",
label: "일반",
columnInfo: validationArticleColumnInfo,
},
} as const;
@@ -253,83 +255,90 @@ function VerificationArticleManagement() {
</TabsTrigger>
))}
</TabsList>
{activeTab !== "GENERAL" && (
<div className="card card-border !mx-0">
<form onSubmit={handleSubmit}>
<div className="flex items-center gap-6 pl-2">
<div className="flex items-center gap-4">
<Label className="whitespace-nowrap text-label">
통계항목
</Label>
<CodeSelect
upCd="STITEM"
value={statsCd}
onValueChange={setStatsCd}
placeholder="선택"
className="w-[16rem]"
/>
</div>
<div className="card card-border !mx-0">
<form onSubmit={handleSubmit}>
<div className="flex items-center gap-4">
<div className="flex items-center gap-4">
<Label className="whitespace-nowrap px-4 text-label">
통계항목
</Label>
<CodeSelect
upCd="STITEM"
value={statsCd}
onValueChange={setStatsCd}
placeholder="선택"
className="w-[16rem]"
/>
</div>
<div className="flex items-center gap-4">
<Label className="whitespace-nowrap text-label">
검증명
</Label>
<Input
value={vrfcTrgtNm}
onChange={(e) =>
setVrfcTrgtNm(e.target.value)
}
placeholder="검증명"
className="w-[20rem]"
/>
</div>
<div className="flex items-center gap-4">
<Label className="whitespace-nowrap px-4 text-label">
검증명
</Label>
<Input
value={vrfcTrgtNm}
onChange={(e) =>
setVrfcTrgtNm(e.target.value)
}
placeholder="검증명"
className="w-[20rem]"
/>
<div className="ml-auto flex gap-2">
<Button
type="button"
color="white"
onClick={handleCheckColumns}
disabled={
checkColumnsMutation.isPending
}
>
컬럼 검사
</Button>
<Button
type="button"
onClick={handleRegister}
>
등록
</Button>
<Button type="submit" color="green">
조회
</Button>
<Button
type="button"
color="gray"
onClick={handleInitialize}
>
초기화
</Button>
</div>
</div>
<div className="ml-auto flex gap-2">
<Button
type="button"
color="white"
className="h-[3.6rem]"
onClick={handleCheckColumns}
disabled={checkColumnsMutation.isPending}
>
컬럼 검사
</Button>
<Button
type="button"
className="h-[3.6rem]"
onClick={handleRegister}
>
등록
</Button>
<Button
type="submit"
color="green"
className="h-[3.6rem]"
>
조회
</Button>
<Button
type="button"
color="gray"
className="h-[3.6rem]"
onClick={handleInitialize}
>
초기화
</Button>
</div>
</div>
</form>
</div>
</form>
</div>
)}
{Object.entries(TAB_CONFIG).map(([key, config]) => (
<TabsContent key={key} value={config.value}>
<DataGrid
columnInfo={columnInfo}
rowData={rowData}
setRowData={() => {}}
onRowClick={handleRowClick}
isExcelImport={false}
/>
<TabsContent
key={key}
value={config.value}
className={cn(
activeTab === "GENERAL" &&
"!mt-[0.6rem] border-none p-0 shadow-none",
)}
>
{activeTab !== "GENERAL" ? (
<DataGrid
columnInfo={columnInfo}
rowData={rowData}
setRowData={() => {}}
onRowClick={handleRowClick}
isExcelImport={false}
/>
) : (
<GeneralVerificationManagement />
)}
</TabsContent>
))}