Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev
This commit is contained in:
@@ -67,7 +67,7 @@ const CompactDataGrid = ({
|
||||
fixedColumns,
|
||||
showHeaderCheckbox = false,
|
||||
rowData,
|
||||
setRowData,
|
||||
// setRowData,
|
||||
getGridDataRef,
|
||||
cellStyleCallback,
|
||||
onRowClick,
|
||||
|
||||
@@ -229,12 +229,12 @@ const SearchForm = (props: SearchFormProps = {}) => {
|
||||
<div className="flex items-center p-2">
|
||||
{mergedProps.fctName &&
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="liSnSearchInput" className="mr-2 text-label">
|
||||
<Label htmlFor="fctNmSearchInput" className="mr-2 text-label">
|
||||
시설명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[14rem] rounded-sm !text-[1.3rem] mr-4"
|
||||
id="liSnSearchInput"
|
||||
id="fctNmSearchInput"
|
||||
value={values.fctName}
|
||||
onChange={(e) => setValues({ ...values, fctName: e.target.value })}
|
||||
autoComplete="off"
|
||||
|
||||
@@ -17,9 +17,9 @@ import { useAdminStore } from "@/store/admin-store";
|
||||
const SewagePipeInp = () => {
|
||||
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [_isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeTab, setActiveTab] = useState<string>(SewagePipeInpColumnInfoList[0]?.tabKey ?? "ST00020001");
|
||||
const [isEnterable, setIsEnterable] = useState<boolean>(true);
|
||||
const [isEnterable, _setIsEnterable] = useState<boolean>(true);
|
||||
const { isAdminInfo } = useAdminStore();
|
||||
|
||||
const columnInfo = useMemo(() => {
|
||||
@@ -46,42 +46,42 @@ const SewagePipeInp = () => {
|
||||
});
|
||||
}, [isEnterable, isAdminInfo]);
|
||||
|
||||
const handleSearch = async (values: SearchFormValues) => {
|
||||
if (!values.sido || values.sido === 'ALL') {
|
||||
alert('시도를 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
// const handleSearch = async (values: SearchFormValues) => {
|
||||
// if (!values.sido || values.sido === 'ALL') {
|
||||
// alert('시도를 선택해주세요.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
setActiveTab('ST00020001');
|
||||
// setActiveTab('ST00020001');
|
||||
|
||||
setRowDataMap(new Map());
|
||||
// setRowDataMap(new Map());
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
// try {
|
||||
// setIsLoading(true);
|
||||
|
||||
// const searchParam: SewagePipeReviewRequestParams = {
|
||||
// statsYr: values.year,
|
||||
// sewerBzmnCd: values.bsnmCd,
|
||||
// ctpvNm: values.sido,
|
||||
// sggNm: values.gugun === 'ALL' ? '' : values.gugun
|
||||
// };
|
||||
// // const searchParam: SewagePipeReviewRequestParams = {
|
||||
// // statsYr: values.year,
|
||||
// // sewerBzmnCd: values.bsnmCd,
|
||||
// // ctpvNm: values.sido,
|
||||
// // sggNm: values.gugun === 'ALL' ? '' : values.gugun
|
||||
// // };
|
||||
|
||||
// searchParamRef.current = searchParam;
|
||||
// const response = await statisticsManagementApi.getSewagePipeReviewRegionalList(searchParam);
|
||||
// // searchParamRef.current = searchParam;
|
||||
// // const response = await statisticsManagementApi.getSewagePipeReviewRegionalList(searchParam);
|
||||
|
||||
// if (response?.status === 'success' && response.data) {
|
||||
// const newRowDataMap = new Map<string, Record<string, string | number>[]>();
|
||||
// newRowDataMap.set('ST00020001', toGridRows(response.data as object[]));
|
||||
// setRowDataMap(newRowDataMap);
|
||||
// } else {
|
||||
// alert(response?.message || "데이터가 없습니다.");
|
||||
// }
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
// // if (response?.status === 'success' && response.data) {
|
||||
// // const newRowDataMap = new Map<string, Record<string, string | number>[]>();
|
||||
// // newRowDataMap.set('ST00020001', toGridRows(response.data as object[]));
|
||||
// // setRowDataMap(newRowDataMap);
|
||||
// // } else {
|
||||
// // alert(response?.message || "데이터가 없습니다.");
|
||||
// // }
|
||||
// } catch {
|
||||
// alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
// } finally {
|
||||
// setIsLoading(false);
|
||||
// }
|
||||
// };
|
||||
|
||||
const SubmitExceptionFunc = () => {
|
||||
console.log('submit exception');
|
||||
|
||||
@@ -18,7 +18,6 @@ import DataGrid from '@/components/module/DataGrid';
|
||||
import { CodeSelect } from '@/entities/code';
|
||||
|
||||
import { LogHistoryColumn } from '@/components/util/column/management/LogHistoryColumn';
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
// import { LwpoCodeApi } from "@/entities/code";
|
||||
|
||||
// const getStateCdListFetcher = async () => {
|
||||
|
||||
@@ -85,7 +85,7 @@ const PumpingStationRvw = () => {
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<SearchForm onSubmit={handleSearch} onReset={handleReset} />
|
||||
<SearchForm fctName={true} onSubmit={handleSearch} onReset={handleReset} />
|
||||
|
||||
<div className="card !py-0">
|
||||
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
|
||||
|
||||
@@ -1,125 +1,184 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
|
||||
import { CodeSelect } from '@/entities/code';
|
||||
import { CodeSelectWithAll } from '@/entities/code';
|
||||
import {
|
||||
Button,
|
||||
Label,
|
||||
// Table,
|
||||
// TableBody,
|
||||
// TableCell,
|
||||
// TableHead,
|
||||
// TableRow,
|
||||
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 { getCoreRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { generalVerificationMasterSubmitSchema, type GeneralVerificationMasterSubmitFormData } from '@/entities/statistics/model/general-verification-master-submit-schema';
|
||||
// import { useDataTable } from "@/shared/lib";
|
||||
import { GeneralVerificationColumn } from '@/components/util/column/management/GeneralVerificationColumn';
|
||||
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';
|
||||
|
||||
|
||||
const GeneralVerificationManagement = () => {
|
||||
const [statsCd, setStatsCd] = useState('');
|
||||
// const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
// const [pagination, setPagination] = useState<PaginationState>({
|
||||
// pageIndex: 0,
|
||||
// pageSize: 100,
|
||||
// });
|
||||
const [searchValues, setSearchValues] = useState<{
|
||||
statsCd: string;
|
||||
useYn: string;
|
||||
vrfcClsfCd: string;
|
||||
}>({
|
||||
statsCd: '',
|
||||
useYn: '',
|
||||
vrfcClsfCd: '',
|
||||
});
|
||||
const [vrfcMasterData, setVrfcMasterData] = useState<GeneralverificationList[]>([]);
|
||||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [selectedVrfcRow, setSelectedVrfcRow] = useState<GeneralverificationList | null>(null);
|
||||
const [showRegistForm, setShowRegistForm] = useState<boolean>(false);
|
||||
|
||||
// const { tableComponent } = useDataTable({
|
||||
// tableOptions: {
|
||||
// GeneralVerificationColumn,
|
||||
// state: {
|
||||
// pagination,
|
||||
// rowSelection,
|
||||
// },
|
||||
// manualPagination: true,
|
||||
// enableMultiRowSelection: true,
|
||||
// getCoreRowModel: getCoreRowModel(),
|
||||
// onPaginationChange: setPagination,
|
||||
// onRowSelectionChange: setRowSelection,
|
||||
// },
|
||||
// // dataTableOptions: {
|
||||
// // onRowClick: handleRowClick,
|
||||
// // viewPagination: true,
|
||||
// // },
|
||||
// });
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const mockData = useMemo<GeneralverificationList[]>(
|
||||
() => [
|
||||
{
|
||||
vrfSn: 1,
|
||||
tabNm: '하수도보급률',
|
||||
vrfNm: '인구수 검증',
|
||||
vrfClsCd: '시',
|
||||
statsCd: 'ST000001',
|
||||
useYn: 'Y',
|
||||
rgtrId: '관리자',
|
||||
regDt: '20260102',
|
||||
},
|
||||
{
|
||||
vrfSn: 2,
|
||||
tabNm: '하수도보급률',
|
||||
vrfNm: '인구수 검증',
|
||||
vrfClsCd: '시',
|
||||
statsCd: 'ST000001',
|
||||
useYn: 'Y',
|
||||
rgtrId: '관리자',
|
||||
regDt: '20260102',
|
||||
},
|
||||
{
|
||||
vrfSn: 3,
|
||||
tabNm: '하수도보급률',
|
||||
vrfNm: '인구수 검증',
|
||||
vrfClsCd: '시',
|
||||
statsCd: 'ST000001',
|
||||
useYn: 'Y',
|
||||
rgtrId: '관리자',
|
||||
regDt: '20260102',
|
||||
},
|
||||
{
|
||||
vrfSn: 4,
|
||||
tabNm: '하수도보급률',
|
||||
vrfNm: '인구수 검증',
|
||||
vrfClsCd: '시',
|
||||
statsCd: 'ST000001',
|
||||
useYn: 'Y',
|
||||
rgtrId: '관리자',
|
||||
regDt: '20260102',
|
||||
},
|
||||
],
|
||||
[]
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const params = Object.fromEntries(
|
||||
Object.entries({
|
||||
trgtStatsCd: searchValues.statsCd,
|
||||
vrfcClsfCd: searchValues.vrfcClsfCd,
|
||||
useYn: searchValues.useYn,
|
||||
}).filter(([, value]) => value !== '' && value !== 'ALL')
|
||||
);
|
||||
|
||||
const response = await generalverificationApiService.getGeneralverificationList(params);
|
||||
|
||||
if (response.status === 'success') {
|
||||
setVrfcMasterData(response.data);
|
||||
setRowSelection({});
|
||||
setSelectedVrfcRow(null);
|
||||
setShowRegistForm(false);
|
||||
} else {
|
||||
alert(response.message || '데이터 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const columns = useMemo(
|
||||
() => getGeneralVerificationColumns(handleSearch),
|
||||
[searchValues.statsCd, searchValues.vrfcClsfCd, searchValues.useYn],
|
||||
);
|
||||
|
||||
const table = useReactTable({
|
||||
data: mockData,
|
||||
columns: GeneralVerificationColumn,
|
||||
data: vrfcMasterData,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getRowId: (row) => row.vrfcSn,
|
||||
state: { rowSelection },
|
||||
onRowSelectionChange: setRowSelection,
|
||||
});
|
||||
|
||||
const handleSearch = () => {
|
||||
console.log(statsCd);
|
||||
const form = useForm<GeneralVerificationMasterSubmitFormData>({
|
||||
resolver: zodResolver(generalVerificationMasterSubmitSchema),
|
||||
defaultValues: {},
|
||||
});
|
||||
|
||||
const handleVrfcMasterRowClick = async (row: GeneralverificationList) => {
|
||||
try {
|
||||
const response = await generalverificationApiService.getGeneralverificationInfo(row.vrfcSn);
|
||||
|
||||
if (response.status === 'success') {
|
||||
setRowSelection({ [row.vrfcSn]: true });
|
||||
setSelectedVrfcRow(row);
|
||||
setShowRegistForm(false);
|
||||
|
||||
form.reset(response.data);
|
||||
} else {
|
||||
alert(response.message || '데이터 조회 중 오류가 발생했습니다.');
|
||||
form.reset({});
|
||||
}
|
||||
} catch {
|
||||
alert('데이터 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setRowSelection({});
|
||||
setSelectedVrfcRow(null);
|
||||
handleSearch();
|
||||
setShowRegistForm(false);
|
||||
}
|
||||
|
||||
const handleClickRegist = () => {
|
||||
// setRowSelection({});
|
||||
// setSelectedVrfcRow(null);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleSearch();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className='h-full'>
|
||||
<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>
|
||||
<CodeSelect
|
||||
<CodeSelectWithAll
|
||||
upCd="STITEM"
|
||||
value={statsCd}
|
||||
onValueChange={setStatsCd}
|
||||
value={searchValues.statsCd}
|
||||
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 })}>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</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 })}>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="전체"></SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
<SelectItem value="Y">Y</SelectItem>
|
||||
<SelectItem value="N">N</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button color="green" className="h-[3.2rem] w-[96px]" type="button">
|
||||
<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}>
|
||||
@@ -128,17 +187,39 @@ const GeneralVerificationManagement = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='card !mb-0 flex gap-5 !p-0 h-[calc(100vh-40rem)]'>
|
||||
<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">
|
||||
<DataTable table={table} />
|
||||
</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" onClick={handleClickRegist}>
|
||||
등록
|
||||
</Button>
|
||||
</RegistDialog>
|
||||
</div>
|
||||
<div className='w-1/2'>
|
||||
|
||||
<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} form={form} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import { NoData } from '@/shared/ui/no-data';
|
||||
import {
|
||||
// Button,
|
||||
// Label,
|
||||
// Select,
|
||||
// SelectTrigger,
|
||||
// SelectContent,
|
||||
// SelectValue,
|
||||
// SelectItem,
|
||||
Input,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from "@common/components";
|
||||
import { FormItem, FormControl, FormField, Form } from "@/shared/ui/form";
|
||||
|
||||
import { type UseFormReturn } from "react-hook-form";
|
||||
|
||||
import type { GeneralverificationList } from '@/entities/statistics/model/general-verification-interface';
|
||||
import { type GeneralVerificationMasterSubmitFormData } from '@/entities/statistics/model/general-verification-master-submit-schema';
|
||||
|
||||
interface DetailComponentProps {
|
||||
selectedVrfcRow: GeneralverificationList | null;
|
||||
form: UseFormReturn<GeneralVerificationMasterSubmitFormData>;
|
||||
}
|
||||
|
||||
const DetailComponent = ({ selectedVrfcRow, form }: DetailComponentProps) => {
|
||||
return (
|
||||
<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">
|
||||
{selectedVrfcRow ?
|
||||
<>
|
||||
<div className='flex flex-col'>
|
||||
<Form {...form}>
|
||||
<form>
|
||||
<div>
|
||||
<Table variant="secondary" className="table-fixed">
|
||||
<colgroup>
|
||||
<col width="25%" />
|
||||
<col width="25%" />
|
||||
<col width="25%" />
|
||||
<col width="25%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>* 검증명</TableHead>
|
||||
<TableCell>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="vrfcNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem] w-full min-w-0"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>
|
||||
{form.formState.errors.vrfcNm && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.vrfcNm.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableHead>* 통계항목</TableHead>
|
||||
<TableCell className='text-center'>{(selectedVrfcRow as GeneralverificationList)?.trgtStatsNm ?? "-"}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<NoData />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailComponent;
|
||||
@@ -0,0 +1,614 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, memo, useRef, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogClose,
|
||||
Input,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Label,
|
||||
Select,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectValue,
|
||||
SelectItem,
|
||||
Skeleton,
|
||||
} from "@common/components";
|
||||
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { CodeSelect } from "@/entities/code";
|
||||
|
||||
import { type GeneralVerificationMasterSubmitFormData, generalVerificationMasterSubmitSchema } from '@/entities/statistics/model/general-verification-master-submit-schema';
|
||||
import type { UpdateVrfcMasterRequest, RegistVrfcMasterRequest } from "@/entities/statistics/model/general-verification-interface";
|
||||
import { generalverificationApiService } from '@/entities/statistics/api/general-verification-service';
|
||||
import { UserApi } from "@/entities/user/api/user-service";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { useAlertStore } from "@/shared/lib";
|
||||
import { getUserInfo } from "../../../../../../../packages/common/components/src/api";
|
||||
|
||||
interface RegistDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
children?: React.ReactNode;
|
||||
vrfcSn?: string;
|
||||
/** 수정/등록 성공 시 부모에서 목록 재조회 등 실행 */
|
||||
onSuccess?: () => void;
|
||||
}
|
||||
|
||||
const RegistDialog = memo(
|
||||
({
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
vrfcSn,
|
||||
onSuccess,
|
||||
...props
|
||||
}: RegistDialogProps) => {
|
||||
|
||||
const isVrfcSn = vrfcSn ? true : false;
|
||||
const [checkVrfcNm, setCheckVrfcNm] = useState<boolean>(false);
|
||||
const { confirm } = useConfirm();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const { data: detailData } = useQuery({
|
||||
queryKey: [`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters`, vrfcSn],
|
||||
queryFn: () => generalverificationApiService.getGeneralverificationInfo(vrfcSn!),
|
||||
enabled: open && !!vrfcSn,
|
||||
});
|
||||
|
||||
const form = useForm<GeneralVerificationMasterSubmitFormData>({
|
||||
resolver: zodResolver(generalVerificationMasterSubmitSchema),
|
||||
values: {
|
||||
vrfcSn: detailData?.data.vrfcSn ?? '',
|
||||
vrfcNm: detailData?.data.vrfcNm ?? '',
|
||||
vrfcClsfCd: detailData?.data.vrfcClsfCd ?? '',
|
||||
trgtStatsCd: detailData?.data.trgtStatsCd ?? '',
|
||||
trgtStatsNm: detailData?.data.trgtStatsNm ?? '',
|
||||
dcptDigtCnt: detailData?.data.dcptDigtCnt ?? 0,
|
||||
dcptPrcsMthCd: detailData?.data.dcptPrcsMthCd ?? '',
|
||||
useYn: detailData?.data.useYn ?? 'Y',
|
||||
rgtrId: detailData?.data.rgtrId ?? '',
|
||||
regDt: detailData?.data.regDt ?? '',
|
||||
mdfrId: detailData?.data.mdfrId ?? '',
|
||||
mdfcnDt: detailData?.data.mdfcnDt ?? '',
|
||||
},
|
||||
});
|
||||
|
||||
const dcptDigtCnt = form.watch('dcptDigtCnt');
|
||||
const rgtrId = form.watch('rgtrId');
|
||||
const mdfrId = form.watch('mdfrId');
|
||||
const trgtStatsCd = form.watch('trgtStatsCd');
|
||||
const vrfcNm = form.watch('vrfcNm');
|
||||
|
||||
const { data: registrarUser } = useQuery({
|
||||
queryKey: ['user', 'rgtr', rgtrId],
|
||||
queryFn: () => UserApi.findByUserUnqId(rgtrId!),
|
||||
enabled: open && !!rgtrId,
|
||||
});
|
||||
|
||||
const { data: modifierUser } = useQuery({
|
||||
queryKey: ['user', 'mdfr', mdfrId],
|
||||
queryFn: () => UserApi.findByUserUnqId(mdfrId!),
|
||||
enabled: open && !!mdfrId,
|
||||
});
|
||||
|
||||
const originalVrfcNmRef = useRef<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (detailData?.data.vrfcNm && originalVrfcNmRef.current == null) {
|
||||
originalVrfcNmRef.current = detailData.data.vrfcNm;
|
||||
}
|
||||
}, [detailData]);
|
||||
|
||||
/** 중복 여부 반환: true = 중복, false = 사용 가능 */
|
||||
const runVerificationNameCheck = async (trgtStatsCdVal: string, vrfcNmVal: string, vrfcClsfCd: string): Promise<boolean> => {
|
||||
try {
|
||||
const response = await generalverificationApiService.checkVerificationName({
|
||||
trgtStatsCd: trgtStatsCdVal,
|
||||
vrfcNm: vrfcNmVal,
|
||||
vrfcClsfCd: vrfcClsfCd,
|
||||
});
|
||||
if (response.status === 'success') {
|
||||
const isDuplicate = response.data;
|
||||
setCheckVrfcNm(isDuplicate);
|
||||
return isDuplicate;
|
||||
}
|
||||
alert('중복검사 중 오류가 발생했습니다.');
|
||||
setCheckVrfcNm(true);
|
||||
return true;
|
||||
} catch {
|
||||
alert('중복검사 중 오류가 발생했습니다.');
|
||||
setCheckVrfcNm(true);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateVrfcMaster = async (data: GeneralVerificationMasterSubmitFormData) => {
|
||||
try {
|
||||
const response = await generalverificationApiService.UpdateVrfcMaster(data as UpdateVrfcMasterRequest);
|
||||
|
||||
if (response.status === 'success') {
|
||||
alert('수정되었습니다.');
|
||||
onOpenChange(false);
|
||||
onSuccess?.();
|
||||
} else {
|
||||
alert(response.message ?? '수정 중 오류가 발생했습니다.');
|
||||
}
|
||||
} catch {
|
||||
alert('수정 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleRegistVrfcMaster = async (data: GeneralVerificationMasterSubmitFormData) => {
|
||||
try {
|
||||
const response = await generalverificationApiService.RegistVrfcMaster(data as RegistVrfcMasterRequest);
|
||||
|
||||
if (response.status === 'success') {
|
||||
alert('등록되었습니다.');
|
||||
onOpenChange(false);
|
||||
onSuccess?.();
|
||||
} else {
|
||||
alert(response.message ?? '등록 중 오류가 발생했습니다.');
|
||||
}
|
||||
} catch {
|
||||
alert('등록 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteVrfcMaster = async () => {
|
||||
const deleteMsg = `${detailData?.data.vrfcNm} 검증룰을
|
||||
삭제하시겠습니까?`;
|
||||
|
||||
if (await confirm(deleteMsg)) {
|
||||
try {
|
||||
const response = await generalverificationApiService.DeleteVrfcMaster(vrfcSn || '');
|
||||
|
||||
if (response.status === 'success') {
|
||||
alert('삭제되었습니다.');
|
||||
onOpenChange(false);
|
||||
onSuccess?.();
|
||||
} else {
|
||||
alert(response.message ?? '삭제 중 오류가 발생했습니다.');
|
||||
}
|
||||
} catch {
|
||||
alert('삭제 중 오류가 발생했습니다.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
if (!vrfcNm) return;
|
||||
|
||||
const original = originalVrfcNmRef.current;
|
||||
// 수정 모드: 기준값이 아직 안 세팅됐으면 검사 안 함(다이얼로그 막 열었을 때)
|
||||
if (isVrfcSn && original === null) return;
|
||||
// 수정 모드: 사용자가 검증명을 바꾸지 않았으면 검사 안 함
|
||||
if (original !== null && original === vrfcNm) {
|
||||
setCheckVrfcNm(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// const timer = setTimeout(() => {
|
||||
// runVerificationNameCheck(trgtStatsCd ?? '', vrfcNm, vrfcClsfCd);
|
||||
// }, 500);
|
||||
|
||||
// return () => clearTimeout(timer);
|
||||
}, [vrfcNm, open, isVrfcSn]);
|
||||
|
||||
const onSubmit = async (data: GeneralVerificationMasterSubmitFormData) => {
|
||||
const currentVrfcNm = (data.vrfcNm ?? '').trim();
|
||||
const originalVrfcNm = originalVrfcNmRef.current;
|
||||
|
||||
// 수정 모드인데 기존값과 동일하면 중복검사 완전 생략
|
||||
const skipNameCheck =
|
||||
isVrfcSn &&
|
||||
(originalVrfcNm === null || currentVrfcNm === originalVrfcNm);
|
||||
|
||||
if (!skipNameCheck && currentVrfcNm) {
|
||||
// 제출 시점에 중복검사 실행
|
||||
const isDuplicate = await runVerificationNameCheck(
|
||||
data.trgtStatsCd ?? '',
|
||||
currentVrfcNm,
|
||||
data.vrfcClsfCd,
|
||||
);
|
||||
if (isDuplicate) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const confirmMessage = isVrfcSn
|
||||
? "수정 하시겠습니까?"
|
||||
: "등록 하시겠습니까?";
|
||||
if (await confirm(confirmMessage)) {
|
||||
const userInfo = await getUserInfo();
|
||||
if (isVrfcSn) {
|
||||
const updateData = {
|
||||
vrfcSn: data.vrfcSn,
|
||||
vrfcNm: data.vrfcNm,
|
||||
vrfcClsfCd: data.vrfcClsfCd,
|
||||
dcptDigtCnt: data.dcptDigtCnt,
|
||||
...(data.dcptDigtCnt === 0
|
||||
? {}
|
||||
: { dcptPrcsMthCd: data.dcptPrcsMthCd }),
|
||||
trgtStatsCd: data.trgtStatsCd,
|
||||
mdfrId: userInfo.userUnqId,
|
||||
};
|
||||
await handleUpdateVrfcMaster(updateData);
|
||||
} else {
|
||||
const registData = {
|
||||
vrfcNm: data.vrfcNm,
|
||||
vrfcClsfCd: data.vrfcClsfCd,
|
||||
dcptDigtCnt: data.dcptDigtCnt,
|
||||
dcptPrcsMthCd: data.dcptPrcsMthCd,
|
||||
trgtStatsCd: data.trgtStatsCd,
|
||||
rgtrId: userInfo.userUnqId
|
||||
};
|
||||
await handleRegistVrfcMaster(registData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
form.reset();
|
||||
setCheckVrfcNm(false);
|
||||
originalVrfcNmRef.current = null;
|
||||
}
|
||||
}, [open, form]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{isVrfcSn ?
|
||||
detailData ? detailData.data.vrfcNm
|
||||
:
|
||||
<Skeleton className="h-[14px] rounded-xl w-2/3" />
|
||||
: "일반 검증 등록"}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="space-y-4"
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
void onSubmit(data);
|
||||
})}
|
||||
>
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="25%" />
|
||||
<col width="75%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>* 통계항목</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="trgtStatsCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
upCd="STITEM"
|
||||
value={field.value ?? ''}
|
||||
onValueChange={field.onChange}
|
||||
placeholder="전체"
|
||||
className="w-[16rem]"
|
||||
disabled={isVrfcSn}
|
||||
/>
|
||||
</FormControl>
|
||||
{form.formState.errors.trgtStatsCd && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.trgtStatsCd.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>* 검증명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="vrfcNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="검증명을 입력해주세요"
|
||||
disabled={(trgtStatsCd ?? '') === ''}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>
|
||||
{checkVrfcNm &&
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
이미 등록된 검증명입니다.
|
||||
</p>
|
||||
}
|
||||
{form.formState.errors.vrfcNm && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.vrfcNm.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{/* <Button color="white" className="mt-2">중복검사</Button> */}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>* 검증분류</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="vrfcClsfCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">공통 검증</SelectItem>
|
||||
<SelectItem value="DO_SI">도단위 검증</SelectItem>
|
||||
<SelectItem value="SI_GU">시단위 검증</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
{form.formState.errors.vrfcClsfCd && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.vrfcClsfCd.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>* 소수점자리수</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="dcptDigtCnt"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? 0}
|
||||
className="!text-[1.3rem] w-[10rem]"
|
||||
placeholder="소수점자리수를 입력해주세요"
|
||||
type="number"
|
||||
min={0}
|
||||
/>
|
||||
</FormControl>
|
||||
<p className="text-gray-500 text-base !mt-0">
|
||||
※ 0일시 소수점자리 생략
|
||||
</p>
|
||||
{form.formState.errors.dcptDigtCnt && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.dcptDigtCnt.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>소수점처리방식</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="dcptPrcsMthCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select
|
||||
value={field.value ?? ""}
|
||||
onValueChange={field.onChange}
|
||||
disabled={Number(dcptDigtCnt ?? 0) === 0}
|
||||
>
|
||||
<SelectTrigger className="w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="CEIL">올림</SelectItem>
|
||||
<SelectItem value="ROUND">반올림</SelectItem>
|
||||
<SelectItem value="FLOOR">내림</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<p className="text-gray-500 text-base !mt-0">
|
||||
※ 소수점자리가 1일시 두 번째 자리에서 올림/반올림/내림 처리<br />
|
||||
예시 - 14.16 → 14.2
|
||||
</p>
|
||||
{form.formState.errors.dcptPrcsMthCd && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.dcptPrcsMthCd.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{isVrfcSn &&
|
||||
<>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
<Label htmlFor="useY">사용</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="N" id="useN" />
|
||||
<Label htmlFor="useN">사용안함</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
{form.formState.errors.useYn && (
|
||||
<p className="text-red-500 text-base pt-2">
|
||||
{form.formState.errors.useYn.message}
|
||||
</p>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>등록자</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="rgtrId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
{registrarUser?.userName != null ? (
|
||||
<span className="!text-[1.3rem]">{registrarUser.userName}</span>
|
||||
) : field.value ? (
|
||||
<Skeleton className="h-9 w-24 rounded-xl" />
|
||||
) : (
|
||||
<span className="!text-[1.3rem]">-</span>
|
||||
)}
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>등록일</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="regDt"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
{field.value != null && field.value != '' ?
|
||||
<span className="!text-[1.3rem]">{field.value}</span>
|
||||
:
|
||||
<span className="!text-[1.3rem]">-</span>
|
||||
}
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>수정자</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="mdfrId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
{modifierUser?.userName != null ? (
|
||||
<span className="!text-[1.3rem]">{modifierUser.userName}</span>
|
||||
) : field.value ? (
|
||||
<Skeleton className="h-9 w-24 rounded-xl" />
|
||||
) : (
|
||||
<span className="!text-[1.3rem]">-</span>
|
||||
)}
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>수정일</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="mdfcnDt"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
{field.value != null && field.value != '' ?
|
||||
<span className="!text-[1.3rem]">{field.value}</span>
|
||||
:
|
||||
<span className="!text-[1.3rem]">-</span>
|
||||
}
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<DialogFooter>
|
||||
{vrfcSn &&
|
||||
<Button size="lg" type="button" color="red" onClick={handleDeleteVrfcMaster}>
|
||||
삭제
|
||||
</Button>
|
||||
}
|
||||
<Button size="lg" type="submit">
|
||||
{vrfcSn ? '수정' : '등록'}
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
})
|
||||
|
||||
RegistDialog.displayName = 'RegistDialog';
|
||||
|
||||
export default RegistDialog;
|
||||
@@ -1,10 +1,14 @@
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@common/components";
|
||||
import type { GeneralverificationList } from "@/entities/statistics/model/general-verification-interface";
|
||||
|
||||
export const GeneralVerificationColumn: ColumnDef<GeneralverificationList>[] = [
|
||||
import { Button } from "@common/components";
|
||||
import RegistDialog from "@/components/statistics/verification/generalVerification/RegistDialog";
|
||||
|
||||
export const getGeneralVerificationColumns = (
|
||||
onUpdateSuccess?: () => void,
|
||||
): ColumnDef<GeneralverificationList>[] => [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
@@ -14,21 +18,20 @@ export const GeneralVerificationColumn: ColumnDef<GeneralverificationList>[] = [
|
||||
return totalRows - (pageIndex * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
// {
|
||||
// accessorKey: "vrfcSn",
|
||||
// header: "일련번호",
|
||||
// },
|
||||
{
|
||||
accessorKey: "vrfSn",
|
||||
header: "일련번호",
|
||||
enableHiding: true,
|
||||
},
|
||||
{
|
||||
accessorKey: "tabNm",
|
||||
accessorKey: "trgtStatsNm",
|
||||
header: "통계항목",
|
||||
},
|
||||
{
|
||||
accessorKey: "vrfNm",
|
||||
accessorKey: "vrfcNm",
|
||||
header: "검증명",
|
||||
},
|
||||
{
|
||||
accessorKey: "vrfClsCd",
|
||||
accessorKey: "vrfcClsfNm",
|
||||
header: "검증분류",
|
||||
},
|
||||
{
|
||||
@@ -48,15 +51,31 @@ export const GeneralVerificationColumn: ColumnDef<GeneralverificationList>[] = [
|
||||
header: "관리",
|
||||
cell: ({ row }) => (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<GeneralVerificationManageButton vrfSn={row.original.vrfSn} />
|
||||
<GeneralVerificationManageButton
|
||||
vrfcSn={row.original.vrfcSn}
|
||||
onSuccess={onUpdateSuccess}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const GeneralVerificationManageButton = ({ vrfSn }: { vrfSn: number }) => {
|
||||
const GeneralVerificationManageButton = ({
|
||||
vrfcSn,
|
||||
onSuccess,
|
||||
}: {
|
||||
vrfcSn: string;
|
||||
onSuccess?: () => void;
|
||||
}) => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
return (
|
||||
<Button size="sm" >관리</Button>
|
||||
<RegistDialog
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
vrfcSn={vrfcSn}
|
||||
onSuccess={onSuccess}
|
||||
>
|
||||
<Button size="sm">관리</Button>
|
||||
</RegistDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -88,10 +88,10 @@ export const rawPumpingStationInfoList = {
|
||||
]
|
||||
},
|
||||
{ name: 'pumpstNm', fieldName: 'pumpstNm', header: { text: '펌프장명' }, mergeCells: true },
|
||||
{ name: 'swtrmtFcltNm', fieldName: 'swtrmtFcltNm', header: { text: '처리장명' } }, // bscFctNm -> swtrmtFcltNm
|
||||
{ name: 'pumpSeNm', fieldName: 'pumpSeNm', header: { text: '구분\n(합류/분류)' } }, // pumpCls -> pumpSeNm
|
||||
{ name: 'impdFcltPstnCn', fieldName: 'impdFcltPstnCn', header: { text: '위치' } }, // addr -> impdFcltPstnCn
|
||||
{ name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동년월일' } }, // rnDt -> oprtngStrtYmd
|
||||
{ name: 'swtrmtFcltNm', fieldName: 'swtrmtFcltNm', header: { text: '처리장명' } },
|
||||
{ name: 'pumpSeNm', fieldName: 'pumpSeNm', header: { text: '구분\n(합류/분류)' } },
|
||||
{ name: 'impdFcltPstnCn', fieldName: 'impdFcltPstnCn', header: { text: '위치' } },
|
||||
{ name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동년월일' } },
|
||||
{
|
||||
name: 'planMltvArea', fieldName: 'planMltvArea', header: { text: '계획배수면적\n(km2)' },
|
||||
footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000'
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { ValueType } from "realgrid";
|
||||
const baseYear = new Date().getFullYear();
|
||||
import dayjs from 'dayjs';
|
||||
import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary";
|
||||
import type { GridView } from "@/components/type/DataGrid.type";
|
||||
|
||||
|
||||
const currentYear = dayjs().year() - 1;
|
||||
const startYear = 1996;
|
||||
const totalCount = currentYear - startYear + 1 + 1;
|
||||
|
||||
// 하수도 통계 관리 02. 하수관로
|
||||
const rawList = [
|
||||
{
|
||||
@@ -248,7 +253,7 @@ const rawList = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{ name: 'prcsFcltCpct', fieldName: 'prcsFcltCpct', header: { text: '하수처리\n시설용량\n(㎥/일)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: 'prcsFcltCpct', fieldName: 'prcsFcltCpct', header: { text: '하수처리\n시설용량\n(㎥/일)' },valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: 'prcsZoneArea', fieldName: 'prcsZoneArea', header: { text: '합계' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' },
|
||||
{ name: 'cbsysPrcsZoneArea', fieldName: 'cbsysPrcsZoneArea', header: { text: '합류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' },
|
||||
{ name: 'sprsysPrcsZoneArea', fieldName: 'sprsysPrcsZoneArea', header: { text: '분류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' },
|
||||
@@ -273,19 +278,19 @@ const rawList = [
|
||||
{
|
||||
name: 'addrGroup', header: { text: '행정구역' },
|
||||
items: [
|
||||
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] },
|
||||
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 6 }, { colspan: 6 }] },
|
||||
'sggNm', 'admdstNm'
|
||||
]
|
||||
},
|
||||
'swtrmtFcltNm','prcsFcltCpct', 'displayYear',
|
||||
{ name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['prcsZoneArea', 'cbsysPrcsZoneArea', 'sprsysPrcsZoneArea'] }, // name 변경됨
|
||||
{ name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['prcsZoneArea', 'cbsysPrcsZoneArea', 'sprsysPrcsZoneArea'] },
|
||||
'sprsysVartnRt',
|
||||
{ name: 'drainGroup', header: { text: '배수설비(개소)' }, items: ['mltvEqpmCnt', 'cbsysMltvEqpmCnt', 'sprsysMltvEqpmCnt'] }, // name 변경됨
|
||||
{ name: 'drainGroup', header: { text: '배수설비(개소)' }, items: ['mltvEqpmCnt', 'cbsysMltvEqpmCnt', 'sprsysMltvEqpmCnt'] },
|
||||
{
|
||||
name: 'pipeGroup', header: { text: '하수관로' },
|
||||
items: [
|
||||
'wholFcltPrlg',
|
||||
{ name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['wholIcptgAtlfcPrlg', 'icptgPrlg', 'atlfcsPrlg'] }, // name 변경됨
|
||||
{ name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['wholIcptgAtlfcPrlg', 'icptgPrlg', 'atlfcsPrlg'] },
|
||||
{
|
||||
name: 'siteGroup', header: { text: '토실/토구(개소)' },
|
||||
items: [
|
||||
@@ -383,18 +388,18 @@ const rawList = [
|
||||
{ name: 'lyngPrlgSum', fieldName: 'lyngPrlg', header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: 'dmltnPrlgSum', fieldName: 'dmltnPrlg', header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
|
||||
/* 동적 연도 컬럼 (1996년이전[yy30] ~ 2025년[yy1]) */
|
||||
...Array.from({ length: 30 }, (_, i) => {
|
||||
const dtoNum = 30 - i; // 30, 29, ..., 1
|
||||
|
||||
...Array.from({ length: totalCount }, (_, i) => {
|
||||
const dtoNum = totalCount - i;
|
||||
|
||||
const wholField = `yy${dtoNum}PrlgWhol`;
|
||||
const wholField = `yy${dtoNum}PrlgWhol`;
|
||||
const lyngField = `yy${dtoNum}LyngPrlg`;
|
||||
const dmltnField = `yy${dtoNum}DmltnPrlg`;
|
||||
|
||||
|
||||
return [
|
||||
{ name: `${wholField}_col`, fieldName: wholField, header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: `${lyngField}_col`, fieldName: lyngField, header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: `${dmltnField}_col`, fieldName: dmltnField, header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }
|
||||
{ name: wholField, fieldName: wholField, header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: lyngField, fieldName: lyngField, header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
|
||||
{ name: dmltnField, fieldName: dmltnField, header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }
|
||||
];
|
||||
}).flat(),
|
||||
|
||||
@@ -404,15 +409,17 @@ const rawList = [
|
||||
'displayYear',
|
||||
{ name: 'summaryGroup', header: { text: '총계' }, items: ['pipeByPrstWholSum','lyngPrlgSum', 'dmltnPrlgSum'] },
|
||||
|
||||
...Array.from({ length: 30 }, (_, i) => {
|
||||
const dtoNum = 30 - i;
|
||||
const yearLabel = i === 0 ? '1996년이전' : `${1995 + i}년`;
|
||||
const wholField = `yy${dtoNum}PrlgWhol`;
|
||||
...Array.from({ length: totalCount }, (_, i) => {
|
||||
|
||||
const dtoNum = totalCount - i;
|
||||
const yearLabel = i === 0
|
||||
? '1996년이전'
|
||||
: `${startYear + (i - 1)}년`;
|
||||
|
||||
return {
|
||||
name: `group_${yearLabel}`,
|
||||
header: { text: yearLabel },
|
||||
items: [`${wholField}_col`, `yy${dtoNum}LyngPrlg_col`, `yy${dtoNum}DmltnPrlg_col`]
|
||||
items: [`yy${dtoNum}PrlgWhol`, `yy${dtoNum}LyngPrlg`, `yy${dtoNum}DmltnPrlg`]
|
||||
};
|
||||
}),
|
||||
'rmrk'
|
||||
@@ -512,7 +519,7 @@ const rawList = [
|
||||
name: 'addrGroup',
|
||||
header: { text: '행정구역' },
|
||||
items: [
|
||||
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] },
|
||||
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 6 }, { colspan: 6 }] },
|
||||
'sggNm',
|
||||
'admdstNm',
|
||||
]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export { CodeApi } from "./api/code-service";
|
||||
export type { ICode } from "./model/code-interface";
|
||||
export { CodeSelect } from "./ui/code-select";
|
||||
export { CodeSelectWithAll } from "./ui/code-select-with-all";
|
||||
|
||||
export { UpCodeApi } from "./api/upcode-service";
|
||||
export {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
cn,
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@common/components";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { CodeApi } from "../api/code-service";
|
||||
|
||||
type CodeSelectProps = {
|
||||
upCd: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
} & React.ComponentPropsWithoutRef<typeof Select>;
|
||||
|
||||
function CodeSelectWithAll({
|
||||
upCd,
|
||||
placeholder = "선택",
|
||||
className,
|
||||
...props
|
||||
}: CodeSelectProps) {
|
||||
const { data: code } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CODE, upCd],
|
||||
queryFn: () => CodeApi.getCode(upCd),
|
||||
enabled: !!upCd,
|
||||
});
|
||||
|
||||
return (
|
||||
<Select {...props}>
|
||||
<SelectTrigger className={cn("w-[12rem]", className)}>
|
||||
<SelectValue placeholder={placeholder} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALL">전체</SelectItem>
|
||||
{code?.map((item) => (
|
||||
<SelectItem key={item.lwpoCd} value={item.lwpoCd}>
|
||||
{item.lwpoCdNm}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
export { CodeSelectWithAll };
|
||||
@@ -0,0 +1,66 @@
|
||||
import { stClient } from "@/shared/api/client";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import type {
|
||||
GeneralverificationRequest,
|
||||
GeneralverificationResponse,
|
||||
GeneralverificationService,
|
||||
GeneralverificationInfoResponse,
|
||||
CheckVerificationNameRequest,
|
||||
CheckVerificationNameResponse,
|
||||
UpdateVrfcMasterRequest,
|
||||
UpdateVrfcMasterResponse,
|
||||
RegistVrfcMasterRequest,
|
||||
RegistVrfcMasterResponse,
|
||||
DeleteVrfcMasterResponse,
|
||||
} from "../model/general-verification-interface";
|
||||
|
||||
export class GeneralverificationApiService implements GeneralverificationService {
|
||||
public async getGeneralverificationList(param: GeneralverificationRequest): Promise<GeneralverificationResponse> {
|
||||
const response = await stClient.get<GeneralverificationResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters`,
|
||||
{ params: param },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getGeneralverificationInfo(param: string): Promise<GeneralverificationInfoResponse> {
|
||||
const response = await stClient.get<GeneralverificationInfoResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters/${param}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async checkVerificationName(param: CheckVerificationNameRequest): Promise<CheckVerificationNameResponse> {
|
||||
const response = await stClient.get<CheckVerificationNameResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/check-name`,
|
||||
{ params: param },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async UpdateVrfcMaster(param: UpdateVrfcMasterRequest): Promise<UpdateVrfcMasterResponse> {
|
||||
const response = await stClient.put<UpdateVrfcMasterResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/masters/${param.vrfcSn}`,
|
||||
param,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async RegistVrfcMaster(param: RegistVrfcMasterRequest): Promise<RegistVrfcMasterResponse> {
|
||||
const response = await stClient.post<RegistVrfcMasterResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/master`,
|
||||
param,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async DeleteVrfcMaster(param: string): Promise<DeleteVrfcMasterResponse> {
|
||||
const response = await stClient.delete<DeleteVrfcMasterResponse> (
|
||||
`${ENDPOINT.ST_SERVICE.INPUTVERIFY}/${param}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const generalverificationApiService = new GeneralverificationApiService();
|
||||
@@ -1,12 +1,89 @@
|
||||
export interface GeneralverificationList {
|
||||
vrfSn: number;
|
||||
tabNm: string;
|
||||
vrfNm: string;
|
||||
vrfClsCd: string;
|
||||
statsCd: string;
|
||||
vrfcSn: string;
|
||||
vrfcNm: string;
|
||||
vrfcClsfCd: string;
|
||||
vrfcClsfNm: string;
|
||||
trgtStatsCd: string;
|
||||
trgtStatsNm: string;
|
||||
dcptDigtCnt: number;
|
||||
dcptPrcsMthCd: string;
|
||||
dcptPrcsMthNm: string;
|
||||
useYn: string;
|
||||
rgtrId?: string;
|
||||
regDt?: string;
|
||||
mdfrId?: string;
|
||||
mdfcnDt?: string;
|
||||
rgtrId?: string;
|
||||
mdfrId?: string;
|
||||
}
|
||||
|
||||
export interface GeneralverificationRequest {
|
||||
trgtStatsCd?: string;
|
||||
vrfcClsfCd?: string;
|
||||
useYn?: string;
|
||||
}
|
||||
|
||||
export interface GeneralverificationResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
data: GeneralverificationList[];
|
||||
}
|
||||
|
||||
export interface GeneralverificationInfoResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
data: GeneralverificationList;
|
||||
}
|
||||
|
||||
export interface CheckVerificationNameRequest {
|
||||
trgtStatsCd: string;
|
||||
vrfcNm: string;
|
||||
vrfcClsfCd: string;
|
||||
}
|
||||
|
||||
export interface CheckVerificationNameResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
data: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateVrfcMasterRequest {
|
||||
vrfcSn?: string | null;
|
||||
vrfcNm?: string | null;
|
||||
vrfcClsfCd?: string | null;
|
||||
dcptDigtCnt?: number | null;
|
||||
dcptPrcsMthCd?: string | null;
|
||||
useYn?: string | null;
|
||||
mdfrId?: string | null;
|
||||
}
|
||||
|
||||
export interface UpdateVrfcMasterResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface RegistVrfcMasterRequest {
|
||||
vrfcNm?: string | null;
|
||||
vrfcClsfCd?: string | null;
|
||||
dcptDigtCnt?: number | null;
|
||||
dcptPrcsMthCd?: string | null;
|
||||
rgtrId?: string | null;
|
||||
trgtStatsCd?: string | null;
|
||||
}
|
||||
|
||||
export interface RegistVrfcMasterResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface DeleteVrfcMasterResponse {
|
||||
status: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface GeneralverificationService {
|
||||
getGeneralverificationList(param: GeneralverificationRequest): Promise<GeneralverificationResponse>;
|
||||
getGeneralverificationInfo(param: string): Promise<GeneralverificationInfoResponse>;
|
||||
checkVerificationName(param: CheckVerificationNameRequest): Promise<CheckVerificationNameResponse>;
|
||||
UpdateVrfcMaster(param: UpdateVrfcMasterRequest): Promise<UpdateVrfcMasterResponse>;
|
||||
RegistVrfcMaster(param: RegistVrfcMasterRequest): Promise<RegistVrfcMasterResponse>;
|
||||
DeleteVrfcMaster(param: string): Promise<DeleteVrfcMasterResponse>;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const generalVerificationMasterSubmitSchema = z
|
||||
.object({
|
||||
vrfcSn: z.string().nullable().optional(),
|
||||
vrfcNm: z.string().min(1, "검증명을 입력하세요"),
|
||||
vrfcClsfCd: z.string().min(1, "검증분류를 선택하세요"),
|
||||
trgtStatsCd: z.string().min(1, "통계항목을 선택하세요"),
|
||||
trgtStatsNm: z.string().nullable().optional(),
|
||||
dcptDigtCnt: z.coerce.number(),
|
||||
dcptPrcsMthCd: z.string().nullable().optional(),
|
||||
useYn: z.string().nullable().optional(),
|
||||
rgtrId: z.string().nullable().optional(),
|
||||
regDt: z.string().nullable().optional(),
|
||||
mdfrId: z.string().nullable().optional(),
|
||||
mdfcnDt: z.string().nullable().optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => data.dcptDigtCnt === 0 || !!data.dcptPrcsMthCd,
|
||||
{
|
||||
path: ["dcptPrcsMthCd"],
|
||||
message: "소수점 처리방식을 선택하세요",
|
||||
},
|
||||
);
|
||||
|
||||
export type GeneralVerificationMasterSubmitFormData = z.infer<
|
||||
typeof generalVerificationMasterSubmitSchema
|
||||
>;
|
||||
@@ -93,7 +93,7 @@ function formatDateTime(date: Date): string {
|
||||
/** H-B 탭 목데이터 생성 */
|
||||
export function createHBArticleMock(count = 10): HBArticleItem[] {
|
||||
faker.seed(100);
|
||||
return Array.from({ length: count }, (_, index) => ({
|
||||
return Array.from({ length: count }, (_, _index) => ({
|
||||
statsItmNm: faker.helpers.arrayElement(HB_STATS_ITEMS),
|
||||
vrfcItmNm: faker.helpers.arrayElement(HB_VERIFICATION_ITEMS),
|
||||
tblNm: faker.helpers.arrayElement(TABLE_NAMES),
|
||||
@@ -113,7 +113,7 @@ export function createHBArticleMock(count = 10): HBArticleItem[] {
|
||||
/** I-MR 탭 목데이터 생성 */
|
||||
export function createIMRArticleMock(count = 10): IMRArticleItem[] {
|
||||
faker.seed(200);
|
||||
return Array.from({ length: count }, (_, index) => ({
|
||||
return Array.from({ length: count }, (_, _index) => ({
|
||||
statsItmNm: faker.helpers.arrayElement(IMR_STATS_ITEMS),
|
||||
vrfcNm: faker.helpers.arrayElement(VERIFICATION_NAMES),
|
||||
tblNm: faker.helpers.arrayElement(TABLE_NAMES),
|
||||
|
||||
@@ -71,6 +71,7 @@ export const ENDPOINT = {
|
||||
INPUT: "/st-input-service/api/v1/input",
|
||||
REVIEW: "/st-management-service/api/v1/review",
|
||||
INPUTCOMMON: "/st-input-service/api/v1/common",
|
||||
INPUTVERIFY: "/st-input-service/api/v1/verify",
|
||||
},
|
||||
STATVERIFY_SERVICE: {
|
||||
VRFCTGT_MNG: "/statverify-service/api/v1/vrfc-trgt-mng",
|
||||
|
||||
Reference in New Issue
Block a user