This commit is contained in:
2025-08-20 13:00:08 +09:00
116 changed files with 3946 additions and 2031 deletions
@@ -191,6 +191,7 @@ export interface LinkSearchParam extends PageableParams {
startDate?: string;
endDate?: string;
isSucc?: string;
linkClfsCd?: string;
}
export type LinkFormData = z.infer<typeof linkFormSchema>;
+26 -3
View File
@@ -4,7 +4,7 @@ import "@common/assets/styles/grid.css";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { Button, Input, Label, LoadingWithAnimation } from "@common/components";
import { Button, Input, Label, LoadingWithAnimation, Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from "@common/components";
import { getCoreRowModel } from "@tanstack/react-table";
import { LinkApi, type Link, type LinkSearchParam } from "@/entities/link";
import { useQuery } from "@tanstack/react-query";
@@ -18,10 +18,12 @@ function LinkPage() {
const [linkSn, setLinkSn] = useState<string>('');
const [linkNm, setLinkNm] = useState<string>('');
const [linkClfsCd, setLinkClfsCd] = useState<string>('');
const [linkSearchParam, setLinkSearchParam] = useState<LinkSearchParam>({
linkSn: '',
linkNm: ''
linkNm: '',
linkClfsCd: '',
});
const query = useQuery({
@@ -32,10 +34,12 @@ function LinkPage() {
const handleResetSearchParam = () => {
setLinkSn('');
setLinkNm('');
setLinkClfsCd('ALL');
setLinkSearchParam({
...linkSearchParam,
linkSn: '',
linkNm: '',
linkClfsCd: 'ALL',
});
};
@@ -44,7 +48,8 @@ function LinkPage() {
setLinkSearchParam({
...linkSearchParam,
linkSn,
linkNm
linkNm,
linkClfsCd,
});
};
@@ -100,6 +105,24 @@ function LinkPage() {
onChange={(e) => setLinkNm(e.target.value)}
autoComplete="off"
/>
<Label htmlFor="linkClfsCd" className="mr-2 text-label">
연계 분류
</Label>
<Select onValueChange={(e) => setLinkClfsCd(e)} value={linkClfsCd}>
<SelectTrigger id="linkClfsCd" className="w-[20rem] mr-4">
<SelectValue placeholder="전체"></SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="ALL">전체</SelectItem>
<SelectItem value="link0001">TIBERO 데이터베이스</SelectItem>
<SelectItem value="link0002">ORACLE 데이터베이스</SelectItem>
<SelectItem value="link0003">공공데이터 포털 API</SelectItem>
<SelectItem value="link0004">한강홍수통제소 API</SelectItem>
<SelectItem value="link0005">기상청 API</SelectItem>
<SelectItem value="link0006">국가지하수정보센터 API</SelectItem>
<SelectItem value="link0007">행정정보공동이용센터 연계</SelectItem>
</SelectContent>
</Select>
<Button color="green" className="h-[3.2rem]" type="button" onClick={handleResetSearchParam}>
초기화
</Button>
@@ -10,7 +10,7 @@ import {
UiModal,
} from "@common/business_components";
import { Input } from "@common/components";
import { Button, Label } from "@common/components/ui";
import { Button, Label } from "@common/components/ui";
import { useSearchParams } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { AccessibleFormField } from "./AccessibleFormField";
@@ -208,22 +208,23 @@ export function SdmInfoRegForm({
formIndex: 0,
required: true,
component: (field) => (
<div className="w-full">
<div className="">
<DatePicker
mode="single"
selected={field.value as Date}
onSelect={(date) => {
field.onChange(date as Date);
}}
className="w-full"
defaultMonth={field.value as Date}
className=""
//defaultMonth={field.value as Date}
field={{
value: field.value as Date,
onChange: (date: Date | undefined) => {
field.onChange(date as Date);
},
}}
selectClass={undefined}
showOutsideDays={true}
selectClass={undefined}
/>
</div>
),
@@ -269,7 +270,7 @@ export function SdmInfoRegForm({
},
{
name: "money",
label: "희망단가(원/m3)",
label: "희망단가(원)",
formIndex: 0,
required: true,
component: (field) => (
@@ -363,7 +364,7 @@ export function SdmInfoRegForm({
name === "money" ? (
<div>
<Label className="text-black" >
희망단가*
희망단가(원)*
</Label>
{ component(field)}
</div>
+2
View File
@@ -4,6 +4,7 @@ import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const isProd = process.env.NODE_ENV === "production";
const compat = new FlatCompat({
baseDirectory: __dirname,
@@ -14,6 +15,7 @@ const eslintConfig = [
{rules:{
// other rules..
"@typescript-eslint/no-explicit-any": "off",
...(isProd ? { "react-hooks/exhaustive-deps": "off" } : {}),
}},
];
+31 -12
View File
@@ -4,6 +4,26 @@
item: Record<string, unknown>;
}
export const roundNumber = (value : any, decimals: number) => {
if (typeof value === 'number') {
return addCommas((Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals)).toFixed(decimals));
} else if (typeof value === 'string' && !isNaN(Number(value))) {
return addCommas(Number(value).toFixed(decimals));
}
}
export const addCommas = (value: string | number): any => {
if (typeof value === 'number') {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",").split('.').map((part, index) =>
index === 0 ? part : part.replace(/(\d{3})/g, '$1,')
).join('.');
} else if (typeof value === 'string') {
return value.includes('.')?value.split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.'):String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
}
export default function DataForm({ type, column, item }: DataFormProps) {
if(item) {
const value = item[column];
@@ -16,31 +36,30 @@ export default function DataForm({ type, column, item }: DataFormProps) {
if(value && value != '') {
item[column] = value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
break;
case 'float1':
break;
case 'float0':
if(value) {
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 10) / 10).split('.').map((part, index) =>
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
break;
case 'float1':
if(value) {
item[column] = roundNumber(value, 1);
}
break;
case 'float2':
if(value) {
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 100) / 100).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
item[column] = roundNumber(value, 2);
}
break;
case 'float3':
if(value) {
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1000) / 1000).split('.').map((part, index) =>
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
).join('.')
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
item[column] = roundNumber(value, 3);
}
break;
}
}
}
}
@@ -47,11 +47,6 @@ export default function SearchInputText({label=undefined, setValue=()=>{}, sidoS
}, [fcltyName]);
const handleSuggestionClick = useCallback((bscFctCd: string, bscFctNm: string, fctCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '') => {
console.log('bscFctNm : ', bscFctNm);
console.log('bscFctCd : ', bscFctCd);
console.log('fctCpc : ', fctCpc);
console.log('trtFrfNm : ', trtFrfNm);
console.log('efflWqltStndrdNm : ', efflWqltStndrdNm);
setTextValue(bscFctNm);
setValue(bscFctCd, bscFctNm, fctCpc, trtFrfNm, efflWqltStndrdNm);
setIsOpen(false);
@@ -1,11 +1,12 @@
"use client"
import { roundNumber } from "@/app/components/common/DataForm";
import { useFoStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/processFacility";
import { ContentsDiv, UiModal, UiTable } from "@common/business_components";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
import { useEffect, useState } from "react";
import DashBoardChartModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export type facilityInfoProps = {
searchYear?: string;
@@ -171,7 +172,6 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
el['provisionalApproval'] = waterUsage1;
}
});
console.log('planFcltyList :', planFcltyList);
}
}, [waterUsage1, waterUsage2, waterUsage3, searchYear, planFcltyList]);
// 연도가 바뀌면 hasSearched를 false로 리셋
@@ -225,7 +225,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
:(index < 5 || index > 5)&& (index!= 4) && (head.id ==='provisionalApproval'||head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour')
?<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
:(head.id === "provisionalApproval" && index === 4)
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{Math.round((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3 * 100)/100}</TableCell>
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{roundNumber(String((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3), 0)}</TableCell>
:((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') )
?null
:(head.id === 'item' && index != 5)?
@@ -148,8 +148,8 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
return (
<>
<ListDiv className="!h-[80px] !mt-10">
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
<ListDiv className="!mt-5 !h-[80px]">
<div className="!m-[0.5rem] max-h-[40rem] overflow-auto">
<Table>
<thead>
<TableRow>
@@ -186,7 +186,7 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
</Table>
</div>
</ListDiv>
<ListDiv className="h-[450px] overflow-y-auto">
<ListDiv className="h-[550px] overflow-y-auto">
<UiTable
headName={"강수현황"}
tableData={getTableData()}
@@ -226,7 +226,7 @@ export default function FacilityPrecipitation() {
queryClick={chkVal}
excelClick={excelDownload}
initClick={resetVal}
ref={ref} isAdmin={false} />
ref={ref} isAdmin={false}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll">
@@ -240,7 +240,7 @@ export default function FacilityPrecipitation() {
{selectedRow !== null && (
<UiModal
body={<PrecipitationModal searchYear={searchYear} fcltyName={fcltyNm} facilityCd={fcltyCd} detailList={gridListPrecipitationDetail}></PrecipitationModal>}
bodyClass="sm:max-w-[90vw] w-[72vw] h-[40vw]"
bodyClass="sm:max-w-[90vw] w-[1150px] h-[700px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
noHeaderYn="Y"
@@ -6,6 +6,7 @@ import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
import { Button, TabsContent } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader";
import { roundUp } from "@/app/store/common";
const tabList = [
{ value: 'tab_term_year', label: '연간' },
@@ -74,6 +75,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
let avgefflAmnt = 0;
let avginfoRnDay = 0;
console.log('filteredData', filteredData);
filteredData.forEach((item: FlowRateModalInterface) => {
const totInflAmnt = parseNumber(item.totInflAmnt);
const inflAmnt = parseNumber(item.inflAmnt);
@@ -106,32 +108,32 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const newFilteredData = [
{
msrDt: '평균',
totInflAmnt: Math.round(avgtotInflAmnt / filteredData.length * 10) / 10,
inflAmnt: Math.round(avginflAmnt / filteredData.length * 10) / 10,
sumFlow: Math.round(avgsumFlow / filteredData.length * 10) / 10,
returnAmnt: Math.round(avgreturnAmnt / filteredData.length * 10) / 10,
efflAmnt: Math.round(avgefflAmnt / filteredData.length * 10) / 10,
infoRnDay: avginfoRnDay > 0 ? Math.round(avginfoRnDay / filteredData.length * 10) / 10 : 0,
totInflAmnt: roundUp((avgtotInflAmnt / filteredData.length), 0),
inflAmnt: roundUp((avginflAmnt / filteredData.length), 0),
sumFlow: roundUp((avgsumFlow / filteredData.length), 0),
returnAmnt: roundUp((avgreturnAmnt / filteredData.length), 0),
efflAmnt: roundUp((avgefflAmnt / filteredData.length), 0),
infoRnDay: avginfoRnDay > 0 ? roundUp((avginfoRnDay / filteredData.length), 1) : '0.0',
rainEffectDay: 0,
},
{
msrDt: '최대',
totInflAmnt: Math.round(maxtotInflAmnt * 10) / 10,
inflAmnt: Math.round(maxinflAmnt * 10) / 10,
sumFlow: Math.round(maxsumFlow * 10) / 10,
returnAmnt: Math.round(maxreturnAmnt * 10) / 10,
efflAmnt: Math.round(maxefflAmnt * 10) / 10,
infoRnDay: maxinfoRnDay > 0 ? (Math.round(maxinfoRnDay * 10) / 10).toFixed(1) : '0.0',
totInflAmnt: roundUp(maxtotInflAmnt, 0),
inflAmnt: roundUp(maxinflAmnt, 0),
sumFlow: roundUp(maxsumFlow, 0),
returnAmnt: roundUp(maxreturnAmnt, 0),
efflAmnt: roundUp(maxefflAmnt, 0),
infoRnDay: maxinfoRnDay > 0 ? roundUp(maxinfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
{
msrDt: '최소',
totInflAmnt: Math.round(mintotInflAmnt * 10) / 10,
inflAmnt: Math.round(mininflAmnt * 10) / 10,
sumFlow: Math.round(minsumFlow * 10) / 10,
returnAmnt: Math.round(minreturnAmnt * 10) / 10,
efflAmnt: Math.round(minefflAmnt * 10) / 10,
infoRnDay: mininfoRnDay > 0 ? (Math.round(mininfoRnDay * 10) / 10).toFixed(1) : '0.0',
totInflAmnt: roundUp(mintotInflAmnt, 0),
inflAmnt: roundUp(mininflAmnt, 0),
sumFlow: roundUp(minsumFlow, 0),
returnAmnt: roundUp(minreturnAmnt, 0),
efflAmnt: roundUp(minefflAmnt, 0),
infoRnDay: mininfoRnDay > 0 ? roundUp(mininfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
...filteredData
@@ -130,7 +130,7 @@ export default function ProcessFacilitySearch() {
initializeCommonData();
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchFlowRateList]);
}, [isInit, initializeCommonData, searchFlowRateList, selectSearchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -187,7 +187,7 @@ export default function ProcessFacilitySearch() {
queryClick={chkVal}
excelClick={excelDownload}
initClick={resetVal}
ref={ref} isAdmin={false} />
ref={ref} isAdmin={false}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll">
@@ -24,7 +24,6 @@ export default function ProcessFacilitySearch() {
isInit,
selectUpdownData,
selectOperationData,
selectFacilityPartData,
selectSidoData,
selectSigunData,
selectRegionData,
@@ -249,7 +248,6 @@ export default function ProcessFacilitySearch() {
<SelectBox className="col-span-3" label={processFacilityLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={val => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
<SearchInput className="col-span-3" label={processFacilityLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
<SelectBox className="col-span-3" label={processFacilityLabelArray[5] as string} selectArray={selectOperationData} onSelectValue={val => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectFacilityPartData} onSelectValue={val => setFacilityPartValue(val.toString())} value={facilityPartValue} selectClass={undefined} />
</>}
rightChildren={undefined}
selectSidoData={selectSidoData}
@@ -7,8 +7,9 @@ import { Table, TableCell, TableHead, TableRow, TabsContent } from "@common/comp
import { useEffect, useState } from "react";
type ModalProps ={
fcltyName: string;
searchYear : string;
fcltyCd?: string;
fcltyName?: string;
searchYear? : string;
}
const tabList1 = [
@@ -17,7 +18,7 @@ const tabList1 = [
{ value: 'tab_term_winter', label: '동절기' },
];
export default function UnderWaterInputModal({fcltyName='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYear=new Date().getFullYear().toString()} : ModalProps) {
// 그리드 관련
const {UnderWaterDetail, unserWaterModal} = useFoStore((state) => state);
@@ -34,64 +35,11 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
gridListUnderWaterDetail,
} = UnderWaterDetail;
// 필터링 된 후 최대, 최소, 평균 값 계산
const setFilterAfterData = (filteredData: UnderWaterInputModalProps[]) => {
let maxRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
let maxSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
let maxUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
let minRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
let minSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
let minUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
let avgRealSewageInput = 0;
let avgSewageOccur = 0;
let avgUnderWaterInput = 0;
filteredData.forEach((item: UnderWaterInputModalProps) => {
maxRealSewageInput = Math.max(Number(maxRealSewageInput), Number(item.realSewageInput));
maxSewageOccur = Math.max(Number(maxSewageOccur), Number(item.sewageOccur));
maxUnderWaterInput = Math.max(Number(maxUnderWaterInput), Number(item.underWaterInput));
minRealSewageInput = Math.min(Number(minRealSewageInput) || 0, Number(item.realSewageInput));
minSewageOccur = Math.min(Number(minSewageOccur) || 0, Number(item.sewageOccur));
minUnderWaterInput = Math.min(Number(minUnderWaterInput) || 0, Number(item.underWaterInput));
avgRealSewageInput += Number(item.realSewageInput ?? 0);
avgSewageOccur += Number(item.sewageOccur ?? 0);
avgUnderWaterInput += Number(item.underWaterInput ?? 0);
})
const newFilteredData = [
{
msrDt: '평균',
realSewageInput: filteredData.length==0?0:Math.round(Number(avgRealSewageInput) / filteredData.length * 10) / 10,
sewageOccur: filteredData.length==0?0:Math.round(Number(avgSewageOccur) / filteredData.length * 1000) / 1000 ,
underWaterInput: filteredData.length==0?0:Math.round(Number(avgUnderWaterInput) / filteredData.length * 1000) / 1000,
},
{
msrDt : '최대',
realSewageInput : Math.round(maxRealSewageInput * 10) / 10,
sewageOccur : Math.round(maxSewageOccur * 1000) / 1000 ,
underWaterInput : Math.round(maxUnderWaterInput * 1000) / 1000,
},
{
msrDt : '최소',
realSewageInput : Math.round(minRealSewageInput * 10) / 10,
sewageOccur : Math.round(minSewageOccur * 1000) / 1000 ,
underWaterInput : Math.round(minUnderWaterInput * 1000) / 1000,
},
...filteredData
];
return newFilteredData;
}
// 날짜 필터링 관련 상태
const [copyYearList, setCopyYearList] = useState<UnderWaterInputModalProps[]>([]);
useEffect(() => {
const filteredYearData = setFilterAfterData(gridListUnderWaterDetail);
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
setCopyYearList(gridListUnderWaterDetail);
}, [gridListUnderWaterDetail]);
useEffect(() => {
@@ -115,9 +63,11 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
setPrevEndYmDate(searchYear+'12');
}
}, [searchYear, tabTerm]);
useEffect(()=>{
unserWaterModal(fcltyName, searchYear);
}, [])
unserWaterModal(fcltyCd, searchYear, searchYear+'01', searchYear+'12');
}, [fcltyCd, searchYear, unserWaterModal]);
useEffect(() => {
if(endYmDate < startYmDate) {
alert('종료일이 시작일보다 작습니다.')
@@ -130,16 +80,13 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
// 유효한 경우 현재 값을 이전 값으로 저장
setPrevStartYmDate(startYmDate);
setPrevEndYmDate(endYmDate);
const filteredData = gridListUnderWaterDetail.filter((item: UnderWaterInputModalProps) => {
// msrDt가 "2024-01" 형태이므로 "202401" 형태로 변환
const itemDate = item.msrDt.replace('-', '');
return itemDate >= startYmDate && itemDate <= endYmDate;
});
const filteredYearData = setFilterAfterData(filteredData);
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
}, [startYmDate, endYmDate, gridListUnderWaterDetail, prevStartYmDate, prevEndYmDate]);
useEffect(() => {
unserWaterModal(fcltyCd, searchYear, prevStartYmDate, prevEndYmDate);
} , [fcltyCd, searchYear, unserWaterModal, prevStartYmDate, prevEndYmDate]);
return (
<>
<UITab tabList={tabList1} defaultValue="tab_term_year" onValueChange={(val) => {setTabTerm(val)}}>
@@ -66,11 +66,11 @@ export default function UnderWaterInput() {
// 모달 상태 추가
const [selectedRow, setSelectedRow] = useState<number | null>(null);
const [fcltyCd, setFcltyCd] = useState<string>("");
const [fcltyNm, setFcltyNm] = useState<string>("");
// 그리드 관련
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
// 초기화 변수
const [resetPage, setResetPage] = useState<boolean>(false);
// 표 너비
@@ -116,7 +116,8 @@ export default function UnderWaterInput() {
// 셀 클릭 시 모달 표시
const cellClick = (index: number) => {
if (underWater[index]) {
setFcltyNm(underWater[index].bscFctCd);
setFcltyCd(underWater[index].bscFctCd || "");
setFcltyNm(underWater[index].bscFctNm || "");
setSelectedRow(index); // 클릭한 행의 index 저장
}
};
@@ -129,7 +130,7 @@ export default function UnderWaterInput() {
initializeCommonData();
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchUnderWaterList]);
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -227,7 +228,7 @@ export default function UnderWaterInput() {
</ContentsDiv>
{selectedRow !== null && (
<UiModal
body={<UnderWaterInputModal fcltyName={fcltyNm} searchYear={searchYear}></UnderWaterInputModal>}
body={<UnderWaterInputModal fcltyCd={fcltyCd} fcltyName={fcltyNm} searchYear={searchYear}></UnderWaterInputModal>}
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
+11 -2
View File
@@ -131,7 +131,7 @@ const selectEnvPartSigunData: SelectDataType[] = [
// 상향 하향 데이터
const selectUpdownData:SelectDataType[] = [
{ text: "전체", val: '0' },
{ text: "500이하", val: '400' },
{ text: "500미만", val: '400' },
{ text: "500이상", val: '500' },
];
@@ -201,6 +201,16 @@ const selectMiddleRegionData: SelectDataType[] = [
{ text: "전체", val: '0' }
];
/**
* 반올림 함수
* @param value : 대상 숫자
* @param precision : 반올림할 자릿수
* @returns
*/
export const roundUp = (value: number, precision: number = 1): number => {
return Math.round(value * (10 ** precision)) / (10 ** precision);
}
/**
* STORE - API
*/
@@ -226,7 +236,6 @@ export const fetchPlanInfo = async (targetYear : string | undefined, ctpvNm : st
}
}
// 시도 API 호출 함수 추가
const fetchSidoData = async (): Promise<SelectDataType[]> => {
try {
+329 -198
View File
@@ -4,7 +4,7 @@
import { getFetch } from "@/app/components/api";
import DataForm from "@/app/components/common/DataForm";
import { fetchPlanInfo } from "../common";
import { fetchPlanInfo, roundUp } from "../common";
import type { FacilityWaterQltyProps } from "../facilityWaterQlty";
import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput";
@@ -152,21 +152,21 @@ export interface RainManageExcelType {
강우량: string,
강우조건비율: number | '',
일수: number | '',
유입유량: number | '',
시설용량대비: number | '',
설계유입수질BOD: number | '',
설계유입수질TOC: number | '',
설계유입수질SS: number | '',
유입유량: string | number | '',
시설용량대비: string |number | '',
설계유입수질BOD: string | number | '',
설계유입수질TOC: string | number | '',
설계유입수질SS: string | number | '',
설계유입수질TN: string | number | '',
설계유입수질TP: string | number | '',
유입수질BOD: number | '',
유입수질TOC: number | '',
유입수질SS: number | '',
유입수질BOD: string | number | '',
유입수질TOC: string | number | '',
유입수질SS: string | number | '',
유입수질TN: string | number | '',
유입수질TP: string | number | '',
방류수질BOD: number | '',
방류수질TOC: number | '',
방류수질SS: number | '',
방류수질BOD: string | number | '',
방류수질TOC: string |number | '',
방류수질SS: string | number | '',
방류수질TN: string | number | '',
방류수질TP: string | number | '',
}
@@ -355,29 +355,29 @@ const upHeadListOperationStatus : TableUpperProps[] = [
const upHeadListRainManage : TableUpperProps[] = [
{ id: "rainItem", title: "강우량", row:0, rowSpan:2 },
{ id: "rainRate", title: "강우조건\n비율(%)", row:0, rowSpan:2 },
{ id: "rainDay", title: "일수", row:0, rowSpan:2 },
{ id: "rainRate", title: "강우조건\n비율(%)", row:0, rowSpan:2, align: "right" },
{ id: "rainDay", title: "일수", row:0, rowSpan:2, align: "right" },
{ id: "A", title: "유입(㎥/일)", row:0, colSpan:2 },
{ id: "inflAmnt", title: "유입유량", row:1 },
{ id: "fctCpc", title: "시설용량대비", row:1 },
{ id: "inflAmnt", title: "유입유량", row:1, align: "right" },
{ id: "fctCpc", title: "시설용량대비", row:1, align: "right" },
{ id: "B", title: "설계유입수질(㎎/L)", row:0, colSpan:5 },
{ id: "dsInflWqltBod", title: "BOD", row:1 },
{ id: "dsInflWqltCod", title: "TOC\n(COD)", row:1 },
{ id: "dsInflWqltSs", title: "SS", row:1 },
{ id: "dsInflWqltTn", title: "T-N", row:1 },
{ id: "dsInflWqltTp", title: "T-P", row:1 },
{ id: "dsInflWqltBod", title: "BOD", row:1, align: "right" },
{ id: "dsInflWqltCod", title: "TOC\n(COD)", row:1, align: "right" },
{ id: "dsInflWqltSs", title: "SS", row:1, align: "right" },
{ id: "dsInflWqltTn", title: "T-N", row:1, align: "right" },
{ id: "dsInflWqltTp", title: "T-P", row:1, align: "right" },
{ id: "C", title: "유입수질(㎎/L)", row:0, colSpan:5 },
{ id: "inflAssctBfrWqltBod", title: "BOD", row:1 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)", row:1 },
{ id: "inflAssctBfrWqltSs", title: "SS", row:1 },
{ id: "inflAssctBfrWqltTn", title: "T-N", row:1 },
{ id: "inflAssctBfrWqltTp", title: "T-P", row:1 },
{ id: "inflAssctBfrWqltBod", title: "BOD", row:1, align: "right" },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)", row:1, align: "right" },
{ id: "inflAssctBfrWqltSs", title: "SS", row:1, align: "right" },
{ id: "inflAssctBfrWqltTn", title: "T-N", row:1, align: "right" },
{ id: "inflAssctBfrWqltTp", title: "T-P", row:1, align: "right" },
{ id: "D", title: "방류수질(㎎/L)", row:0, colSpan:5 },
{ id: "efflWqltBod", title: "BOD", row:1 },
{ id: "efflWqltToc", title: "TOC\n(COD)", row:1 },
{ id: "efflWqltSs", title: "SS", row:1 },
{ id: "efflWqltTn", title: "T-N", row:1 },
{ id: "efflWqltTp", title: "T-P", row:1 },
{ id: "efflWqltBod", title: "BOD", row:1, align: "right" },
{ id: "efflWqltToc", title: "TOC\n(COD)", row:1, align: "right" },
{ id: "efflWqltSs", title: "SS", row:1, align: "right" },
{ id: "efflWqltTn", title: "T-N", row:1, align: "right" },
{ id: "efflWqltTp", title: "T-P", row:1, align: "right" },
]
const upHeadListDrainageEquipment : TableUpperProps[] = [
@@ -401,7 +401,7 @@ const upHeadListDrainageEquipment : TableUpperProps[] = [
{ id: "etc", title: "비고", row:0, upName:"upChangeRe7", upSequnce:1 },
]
const operationalStatusList : OperationalStatusListProps[] = [
let operationalStatusList : OperationalStatusListProps[] = [
{
flowRate : '유량\n(㎥/일)',
waterQlty : '유입',
@@ -872,30 +872,49 @@ export const dashBoardInitState:DashBoardType = {
/**
* 데이터 폼 포맷설정
*/
export const dataFormSettingPlan=(item : planFcltyListProps) => {
DataForm({ type: 'float2', column: 'provisionalApproval', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float2', column: 'now', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'stepOne', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'stepTwo', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'stepThree', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'stepFour', item: item as unknown as Record<string, unknown>});
export const dataFormSettingPlan=(item : planFcltyListProps, decmials : number) => {
DataForm({ type: 'float'+decmials, column: 'provisionalApproval', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float'+decmials, column: 'now', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float'+decmials, column: 'stepOne', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float'+decmials, column: 'stepTwo', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float'+decmials, column: 'stepThree', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float'+decmials, column: 'stepFour', item: item as unknown as Record<string, unknown>});
}
export const dataFormSetting=(item : OperationalStatusListProps)=> {
DataForm({ type: 'float2', column: 'yearAvg', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float2', column: 'yearMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'yearMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'summerAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'summerThree', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'summerRain', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'winterAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'winterSunnyAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'winterSunnyMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'winterSunnyMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'groundWaterAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'groundWaterSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'groundWaterWinter', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'rainRate', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'yearAvg', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'yearMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'yearMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'summerAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'summerThree', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'summerRain', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'winterAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'winterSunnyAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'winterSunnyMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'winterSunnyMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'groundWaterAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'groundWaterSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'groundWaterWinter', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'rainRate', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'rdi', item: item as unknown as Record<string, unknown>});
};
export const dataFormSettingWqlty=(item : OperationalStatusListProps)=> {
DataForm({ type: 'float1', column: 'yearAvg', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'yearMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'yearMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'summerAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'summerThree', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'summerRain', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'winterAll', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'winterSunnyAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'winterSunnyMax', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'winterSunnyMin', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'groundWaterAvg', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'groundWaterSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'groundWaterWinter', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'rainRate', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'rdi', item: item as unknown as Record<string, unknown>});
};
const changeValue=(operationalStatus, data, keyTxt = 'INFL_AMNT')=>{
@@ -921,7 +940,7 @@ const changeValue=(operationalStatus, data, keyTxt = 'INFL_AMNT')=>{
const winterAvgBod = data.winterSunny && data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD && data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD != 'null' ? Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD) : 0;
const summerLowBod = data.summerBod && data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD && data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD != 'null' ? Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD) : 0;
const summerLowRain = data.summerBod && data.summerBod.INFO_RN_DAY && data.summerBod.INFO_RN_DAY != 'null' ? Number(data.summerBod.INFO_RN_DAY) : 0;
operationalStatus.rdi = winterAvgBod === 0 ? 0 : summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatus.rdi = winterAvgBod === 0 ? 0 : roundUp(summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod), 1);
operationalStatus.rdiRain = summerLowRain;
}
@@ -1012,12 +1031,12 @@ export const calRainEffectDayRainManage = (data: RainManageListProps[]) => {
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
@@ -1068,21 +1087,21 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
let minDiff=9999999;
let minIndex;
res.forEach((el:any, idx) => {
if(minDiff>Math.abs(Number(targetYear) - Number(el.yr))){
minDiff=Math.abs(Number(targetYear) - Number(el.yr));
if(minDiff>Math.abs(Number(targetYear) - Number(el.planYr))){
minDiff=Math.abs(Number(targetYear) - Number(el.planYr));
minIndex=idx;
}
});
const rtnPlanData = res[minIndex];
planFcltyList.map((el, index) => {
planYearList = [];
planYearList.push(rtnPlanData?rtnPlanData.yrDt4.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.yrDc1.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.yrDc2.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.yrDc3.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.yrDc4.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYrDt4.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYr.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYrDc1.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYrDc2.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYrDc3.toString():"");
planYearList.push(rtnPlanData?rtnPlanData.planYrDc4.toString():"");
if(index === 0){
el.provisionalApproval = rtnPlanData?rtnPlanData.planSwageQntSumDt4:'';
@@ -1111,17 +1130,22 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
if(index === 4){
el.provisionalApproval = rtnPlanData?rtnPlanData.ugwtUseSum:'';
}
if(index == 0 || index === 2){
dataFormSettingPlan(el, 1);
}else if(index == 4){
}else{
dataFormSettingPlan(el, 0);
}
// 임시시
dataFormSettingPlan(el);
console.log('planFcltyList', planFcltyList);
console.log('rtnPlanData', rtnPlanData);
set((state: DashBoardType) => ({
...state,
PlanFclty: {
...state.PlanFclty,
planFcltyList: planFcltyList,
isLoadingPlanFclty: false,
planYearList: planYearList,
},
}));
});
@@ -1139,6 +1163,17 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const res = await fetchOperationStatus(searchYear, fcltyCd);
const data = res.data;
let yearMaxSumFlow = 1;
let yearMinSumFlow = 1;
let yearAvgSumFlow = 1;
let summerAll = 1;
let summerThree = 1;
let summerRain = 1;
let winterAll = 1;
let winterSunnyMin = 1;
let winterSunnyAvg = 1;
let winterSunnyMax = 1;
if(data && operationalStatusList){
// 유량 - 유입
if (operationalStatusList?.[0]) {
@@ -1146,6 +1181,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const yearAvg = data.yearData===null?'':(data.yearData.AVG_INFL_AMNT?data.yearData.AVG_INFL_AMNT:0)+(data.yearData.AVG_SUM_FLOW?data.yearData.AVG_SUM_FLOW:0)+(data.yearData.AVG_RETURN_AMNT?data.yearData.AVG_RETURN_AMNT:0);
const yearMax = data.yearData===null?'':(data.yearData.MAX_INFL_AMNT?data.yearData.MAX_INFL_AMNT:0)+(data.yearData.MAX_SUM_FLOW?data.yearData.MAX_SUM_FLOW:0)+(data.yearData.MAX_RETURN_AMNT?data.yearData.MAX_RETURN_AMNT:0);
const yearMin = data.yearData===null?'':(data.yearData.MIN_INFL_AMNT?data.yearData.MIN_INFL_AMNT:0)+(data.yearData.MIN_SUM_FLOW?data.yearData.MIN_SUM_FLOW:0)+(data.yearData.MIN_RETURN_AMNT?data.yearData.MIN_RETURN_AMNT:0);
operationalStatusList[0].yearAvg = yearAvg;
operationalStatusList[0].yearMax = yearMax;
operationalStatusList[0].yearMin = yearMin;
@@ -1166,52 +1202,130 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
(data.summerSunny.AVG_TP_INFL_WQLT_TP ? data.summerSunny.AVG_TP_INFL_WQLT_TP : 0)
);
// 겨울
operationalStatusList[0].winterAll = data.winter === null ? '' : (data.winter.AVG_INFL_AMNT ? data.winter.AVG_INFL_AMNT : 0) + (data.winter.AVG_SUM_FLOW ? data.winter.AVG_SUM_FLOW : 0) + (data.winter.AVG_TP_INFL_WQLT_TP ? data.winter.AVG_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterSunnyMin = data.winterSunny === null ? '' : (data.winterSunny.MIN_INFL_AMNT ? data.winterSunny.MIN_INFL_AMNT : 0) + (data.winterSunny.MIN_SUM_FLOW ? data.winterSunny.MIN_SUM_FLOW : 0) + (data.winterSunny.MIN_TP_INFL_WQLT_TP ? data.winterSunny.MIN_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterSunnyAvg = data.winterSunny === null ? '' : (data.winterSunny.AVG_INFL_AMNT ? data.winterSunny.AVG_INFL_AMNT : 0) + (data.winterSunny.AVG_SUM_FLOW ? data.winterSunny.AVG_SUM_FLOW : 0) + (data.winterSunny.AVG_TP_INFL_WQLT_TP ? data.winterSunny.AVG_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterSunnyMax = data.winterSunny === null ? '' : (data.winterSunny.MAX_INFL_AMNT ? data.winterSunny.MAX_INFL_AMNT : 0) + (data.winterSunny.MAX_SUM_FLOW ? data.winterSunny.MAX_SUM_FLOW : 0) + (data.winterSunny.MAX_TP_INFL_WQLT_TP ? data.winterSunny.MAX_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterAll = data.winter === null ? '' : (
(data.winter.AVG_INFL_AMNT ? data.winter.AVG_INFL_AMNT : 0) +
(data.winter.AVG_SUM_FLOW ? data.winter.AVG_SUM_FLOW : 0) +
(data.winter.AVG_TP_INFL_WQLT_TP ? data.winter.AVG_TP_INFL_WQLT_TP : 0)
);
operationalStatusList[0].winterSunnyMin = data.winterSunny === null ? '' : (
(data.winterSunny.MIN_INFL_AMNT ? data.winterSunny.MIN_INFL_AMNT : 0) +
(data.winterSunny.MIN_SUM_FLOW ? data.winterSunny.MIN_SUM_FLOW : 0) +
(data.winterSunny.MIN_TP_INFL_WQLT_TP ? data.winterSunny.MIN_TP_INFL_WQLT_TP : 0)
);
operationalStatusList[0].winterSunnyAvg = data.winterSunny === null ? '' : (
(data.winterSunny.AVG_INFL_AMNT ? data.winterSunny.AVG_INFL_AMNT : 0) +
(data.winterSunny.AVG_SUM_FLOW ? data.winterSunny.AVG_SUM_FLOW : 0) +
(data.winterSunny.AVG_TP_INFL_WQLT_TP ? data.winterSunny.AVG_TP_INFL_WQLT_TP : 0)
);
operationalStatusList[0].winterSunnyMax = data.winterSunny === null ? '' : (
(data.winterSunny.MAX_INFL_AMNT ? data.winterSunny.MAX_INFL_AMNT : 0) +
(data.winterSunny.MAX_SUM_FLOW ? data.winterSunny.MAX_SUM_FLOW : 0) +
(data.winterSunny.MAX_TP_INFL_WQLT_TP ? data.winterSunny.MAX_TP_INFL_WQLT_TP : 0)
);
// 연계처리수
let yearDay = 0;
let summerDay = 0;
let winterDay = 0;
let summerRainDay = 0;
let summerChungchunDay = 0;
let winterChungchuDay = 0;
let yearSumFlow = 0;
let maxYearSumFlow = 0;
let minYearSumFlow = 9999999;
let summerSumFlow = 0;
let summerChungchunSumFlow = 0;
let summerRainDaySumFlow = 0;
let winterSumFlow = 0;
let winterChungchunSumFlow = 0;
let minWinterChungchunSumFlow = 9999999;
let maxWinterChungchunSumFlow = 0;
// 연계처리수,지하수유입량
const bscFctCd = fcltyCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
const calData = calRainEffectDay(res2.data, 'SUNNY');
let chungcunSumFlow = 0;
let sumSummerChungcunDay = 0;
let sumSummerChungcunFlow = 0;
let sumWinterChungcunDay = 0;
let sumWinterChungcunFlow = 0;
/* let yearSumFlow = 0;
let summerSumFlow = 0;
let winterSumFlow = 0; */
calData.forEach((flowItem: FlowDataItem) => {
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
//yearSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
sumSummerChungcunDay += 1;
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
//summerSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
sumWinterChungcunDay += 1;
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
// winterSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
yearDay = res2.data?res2.data.length:1;
res2.data.forEach((item: FlowDataItem) => {
yearSumFlow += item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0;
if(maxYearSumFlow < (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0)) {
maxYearSumFlow = item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0;
}
if(minYearSumFlow > (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0) || minYearSumFlow === 0) {
minYearSumFlow = item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0;
}
if(item.msrDt.substring(4,6) === '06' || item.msrDt.substring(4,6) === '07' || item.msrDt.substring(4,6) === '08') {
summerDay += 1;
summerSumFlow += item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0;
} else if(item.msrDt.substring(4,6) === '01' || item.msrDt.substring(4,6) === '02') {
winterDay += 1;
winterSumFlow += item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0;
}
});
const calData = calRainEffectDay(res2.data, 'SUNNY');
const calRainDate = calRainEffectDay(res2.data, 'RAIN');
// 지하수유입량 - 청천시 기준
let chungcunSumFlow = 0;
let sumSummerChungcunFlow = 0;
let sumWinterChungcunFlow = 0;
// 하절기, 동절기 청천시 계산
calData.forEach((flowItem: FlowDataItem) => {
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
summerChungchunDay += 1;
summerChungchunSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
if(minWinterChungchunSumFlow > (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0) || minWinterChungchunSumFlow === 0) {
minWinterChungchunSumFlow = flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}
if(maxWinterChungchunSumFlow < (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0)) {
maxWinterChungchunSumFlow = flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}
winterChungchuDay += 1;
winterChungchunSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}
});
// 하절기 강우시 계산
calRainDate.forEach((flowItem: FlowDataItem) => {
if(flowItem.msrDt.substring(4,6) === '06' || flowItem.msrDt.substring(4,6) === '07' || flowItem.msrDt.substring(4,6) === '08') {
summerRainDay += 1;
summerRainDaySumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}
});
operationalStatusList[0].yearAvg = roundUp(Number(operationalStatusList[0].yearAvg) + (yearSumFlow&&Number(yearSumFlow) != 0?Number(yearSumFlow / yearDay):0), 0);
operationalStatusList[0].yearMax = roundUp(Number(operationalStatusList[0].yearMax) + Number(maxYearSumFlow), 0);
operationalStatusList[0].yearMin = roundUp(Number(operationalStatusList[0].yearMin) + Number(minYearSumFlow), 0);
operationalStatusList[0].summerAll = roundUp(Number(operationalStatusList[0].summerAll) + (summerSumFlow&&Number(summerSumFlow)!=0?Number(summerSumFlow / summerDay):0), 0);
operationalStatusList[0].summerThree = roundUp(Number(operationalStatusList[0].summerThree) + (summerRainDaySumFlow&&Number(summerRainDaySumFlow)!=0?Number(summerRainDaySumFlow / summerRainDay):0), 0);
operationalStatusList[0].summerRain = roundUp(Number(operationalStatusList[0].summerRain) + (summerChungchunSumFlow&&Number(summerChungchunSumFlow)!=0?Number(summerChungchunSumFlow / summerChungchunDay):0), 0);
operationalStatusList[0].winterAll = roundUp(Number(operationalStatusList[0].winterAll) + (winterSumFlow&&Number(winterSumFlow)!=0?Number(winterSumFlow / winterDay):0), 0);
operationalStatusList[0].winterSunnyMin = roundUp(Number(operationalStatusList[0].winterSunnyMin) + Number(minWinterChungchunSumFlow), 0);
operationalStatusList[0].winterSunnyMax = roundUp(Number(operationalStatusList[0].winterSunnyMax) + (winterChungchunSumFlow&&Number(winterChungchunSumFlow)!=0?Number(winterChungchunSumFlow / winterChungchuDay):0), 0);
operationalStatusList[0].winterSunnyAvg = roundUp(Number(operationalStatusList[0].winterSunnyAvg) + Number(maxWinterChungchunSumFlow), 0);
// 연계처리수
/* const avgYearSumFlow = yearSumFlow / calData.length;
const avgSummerSumFlow = summerSumFlow / calData.length;
const avgWinterSumFlow = winterSumFlow / calData.length; */
yearAvgSumFlow = Number((yearSumFlow&&Number(yearSumFlow)!=0)?(yearSumFlow / yearDay):'');
yearMaxSumFlow = maxYearSumFlow;
yearMinSumFlow = minYearSumFlow;
summerAll = summerSumFlow&&Number(summerSumFlow)!=0?Number(summerSumFlow / summerDay):0
summerThree= summerRainDaySumFlow&&Number(summerRainDaySumFlow)!=0?Number(summerRainDaySumFlow / summerRainDay):0;
summerRain = summerChungchunSumFlow&&Number(summerChungchunSumFlow)!=0?Number(summerChungchunSumFlow / summerChungchunDay):0;
winterAll = winterSumFlow&&Number(winterSumFlow)!=0?Number(winterSumFlow / winterDay):0;
winterSunnyMin = minWinterChungchunSumFlow;
winterSunnyAvg = winterChungchunSumFlow&&Number(winterChungchunSumFlow)!=0?(winterChungchunSumFlow / winterChungchuDay):0;
winterSunnyMax = maxWinterChungchunSumFlow;
// 지하수유입량
const usage = chungcunSumFlow / calData.length;
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
const summerUsage = sumSummerChungcunFlow / summerChungchunDay;
const winterUsage = sumWinterChungcunFlow / winterChungchuDay;
operationalStatusList[0].groundWaterAvg = Math.round((usage-(usage*0.65*0.8)) * 100) / 100;
operationalStatusList[0].groundWaterSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100;
@@ -1227,19 +1341,19 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[0].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[0].rdi = winterAvgBod===0?0:roundUp(summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod), 2);
operationalStatusList[0].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[0]);
}
if(operationalStatusList[0] && operationalStatusList[7]){
operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : data.yearData && data.yearData.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterAvg) / (data.yearData && data.yearData.AVG_INFL_AMNT ? Number(data.yearData.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : data.summer && data.summer.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterSummer) / (data.summer && data.summer.AVG_INFL_AMNT ? Number(data.summer.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : data.winter && data.winter.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterWinter) / (data.winter && data.winter.AVG_INFL_AMNT ? Number(data.winter.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].rdi = operationalStatusList[0].rdi === null ? '' : data.summerBod && data.summerBod.INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].rdi) / (data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0) * 100) * 10) / 10+'%';
/* operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : Number(Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT)) * 100;
operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : data.yearData && data.yearData.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterAvg.toString().replaceAll(',', '')) / (data.yearData && data.yearData.AVG_INFL_AMNT ? Number(data.yearData.AVG_INFL_AMNT.toString().replaceAll(',','')) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : data.summer && data.summer.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterSummer.toString().replaceAll(',','')) / (data.summer && data.summer.AVG_INFL_AMNT ? Number(data.summer.AVG_INFL_AMNT.toString().replaceAll(',','')) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : data.winter && data.winter.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterWinter.toString().replaceAll(',','')) / (data.winter && data.winter.AVG_INFL_AMNT ? Number(data.winter.AVG_INFL_AMNT.toString().replaceAll(',','')) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].rdi = operationalStatusList[0].rdi === null ? '' : data.summerBod && data.summerBod.INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].rdi.toString().replaceAll(',','')) / (data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT.toString().replaceAll(',','')):0) * 100) * 10) / 10+'%';
/* operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : Number(Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT)) * 100;
operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : Number(Number(operationalStatusList[0].groundWaterSummer) / Number(data.summer.AVG_INFL_AMNT)) * 100;
operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : Number(Number(operationalStatusList[0].groundWaterWinter) / Number(data.winter.AVG_INFL_AMNT)) * 100;*/
dataFormSetting(operationalStatusList[0]);
}
for(let i=1; i<operationalStatusList.length; i++){
@@ -1247,44 +1361,37 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
if(operationalStatusList[i]){
if(i < 7){
changeValue(operationalStatusList[i], data, txtArray[i]);
dataFormSetting(operationalStatusList[i]!);
if(i < 5){
dataFormSetting(operationalStatusList[i]!);
}else{
dataFormSettingWqlty(operationalStatusList[i]!);
}
}else{
calcValue(operationalStatusList[i], data, txtArray[i]);
}
}
}
if(operationalStatusList[2]){
operationalStatusList[2].yearAvg = yearAvgSumFlow;
operationalStatusList[2].yearMax = yearMaxSumFlow;
operationalStatusList[2].yearMin = yearMinSumFlow;
operationalStatusList[2].summerAll = summerAll;
operationalStatusList[2].summerThree = summerThree;
operationalStatusList[2].summerRain = summerRain;
operationalStatusList[2].winterAll = winterAll;
operationalStatusList[2].winterSunnyMin = winterSunnyMin;
operationalStatusList[2].winterSunnyAvg = winterSunnyAvg;
operationalStatusList[2].winterSunnyMax = winterSunnyMax;
dataFormSetting(operationalStatusList[2]);
}
}
//
if(data.yearData.TP_INFL_WQLT_TP === null || data.yearData.TP_INFL_WQLT_TP === undefined || data.yearData.TP_INFL_WQLT_TP === 'null') {
operationalStatusList = operationalStatusList.slice(0, 10);
}
//const excelDownList: RainManageExcelType[] = [];
/* if(isExcel){
res.data.forEach(item => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
excelDownList.push({
시설코드: item.bscFctCd,
시설이름: item.bscFctNm,
측정일자: item.msrDt,
시도: item.sidoNm,
시군구: item.sggNm,
주소: item.addr,
용량: item.fctCpc,
유입BOD: item.inflAssctBfrWqltBod,
유입TN: item.inflAssctBfrWqltTn,
유입TP: item.inflAssctBfrWqltTp,
유출BOD: item.efflWqltBod,
유출TN: item.efflWqltTn,
유출TP: item.efflWqltTp,
환경청: item.rgnNm,
유역: item.rvbsn,
대유역: item.lgbsn,
중유역: item.mdmbsn,
});
});
}else{ */
/* data.forEach((item: OperationalStatusListProps) => {
}); */
/* } */
set((state: DashBoardType) => ({
...state,
OperationStatus: {
@@ -1295,7 +1402,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
},
}))
},
searchMainGraph: async (searchYear: string, fcltyCd: string) => {
set((state: DashBoardType) => ({
...state,
@@ -1449,7 +1556,31 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const rainEffectList = calRainEffectDayRainManage(res.data.wqltObjs);
// Process the data and create rain management list
const totItemCnt = rainEffectList?rainEffectList.length : 1;
let totInflAssctBfrWqltBod = 0;
let totInflAssctBfrWqltToc = 0;
let totInflAssctBfrWqltSs = 0;
let totInflAssctBfrWqltTn = 0;
let totInflAssctBfrWqltTp = 0;
let totEfflWqltBod = 0;
let totEfflWqltToc = 0;
let totEfflWqltSs = 0;
let totEfflWqltTn = 0;
let totEfflWqltTp = 0;
rainEffectList.forEach((item: RainManageListProps) => {
totInflAssctBfrWqltBod += item.inflAssctBfrWqltBod ? Number(item.inflAssctBfrWqltBod.toString().trim()) : 0;
totInflAssctBfrWqltToc += item.inflAssctBfrWqltToc ? Number(item.inflAssctBfrWqltToc.toString().trim()) : 0;
totInflAssctBfrWqltSs += item.inflAssctBfrWqltSs ? Number(item.inflAssctBfrWqltSs.toString().trim()) : 0;
totInflAssctBfrWqltTn += item.inflAssctBfrWqltTn ? Number(item.inflAssctBfrWqltTn.toString().trim()) : 0;
totInflAssctBfrWqltTp += item.inflAssctBfrWqltTp ? Number(item.inflAssctBfrWqltTp.toString().trim()) : 0;
totEfflWqltBod += item.efflWqltBod ? Number(item.efflWqltBod.toString().trim()) : 0;
totEfflWqltToc += item.efflWqltToc ? Number(item.efflWqltToc.toString().trim()) : 0;
totEfflWqltSs += item.efflWqltSs ? Number(item.efflWqltSs.toString().trim()) : 0;
totEfflWqltTn += item.efflWqltTn ? Number(item.efflWqltTn.toString().trim()) : 0;
totEfflWqltTp += item.efflWqltTp ? Number(item.efflWqltTp.toString().trim()) : 0;
if(Number(item.infoRnDay) >= 3 && Number(item.infoRnDay) < 10){
rainDate[1] = Number(rainDate[1] || 0) + 1;
inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1;
@@ -1537,7 +1668,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAssctBfrWqltSsCnt[4] = Number(inflAssctBfrWqltSsCnt[4] || 0) + 1;
inflAssctBfrWqltSs[4] = Number(inflAssctBfrWqltSs[4] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[4] = Number(inflAssctBfrWqltTnCnt[4] || 0) + 1;
inflAssctBfrWqltTn[4] = Number(inflAssctBfrWqltTn[5] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTn[4] = Number(inflAssctBfrWqltTn[4] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[4] = Number(inflAssctBfrWqltTpCnt[4] || 0) + 1;
inflAssctBfrWqltTp[4] = Number(inflAssctBfrWqltTp[4] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[4] = Number(efflWqltBodCnt[4] || 0) + 1;
@@ -1546,9 +1677,9 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltToc[4] = Number(efflWqltToc[4] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[4] = Number(efflWqltSsCnt[4] || 0) + 1;
efflWqltSs[4] = Number(efflWqltSs[4] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[4] = Number(efflWqltTnCnt[5] || 0) + 1;
efflWqltTnCnt[4] = Number(efflWqltTnCnt[4] || 0) + 1;
efflWqltTn[4] = Number(efflWqltTn[4] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[4] = Number(efflWqltTpCnt[5] || 0) + 1;
efflWqltTpCnt[4] = Number(efflWqltTpCnt[4] || 0) + 1;
efflWqltTp[4] = Number(efflWqltTp[4] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 40 && Number(item.infoRnDay) < 50){
rainDate[5] = Number(rainDate[5] || 0) + 1;
@@ -1683,7 +1814,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
// 평균 및 합계 계산
const calculateAverage = (value: number, count: number) => {
return count > 0 ? Number((value / count).toFixed(1)) : 0;
return count > 0 ? Number((value / count)) : 0;
};
// 데이터 있는 항목만 계산
@@ -1710,44 +1841,44 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
// 합계 계산 (index 0)
const calculateTotal = (arr: number[]) => {
return Number((arr.slice(1).reduce((sum, val) => sum + Number(val), 0)).toFixed(1));
return Number((arr.slice(1).reduce((sum, val) => sum + Number(val), 0)));
};
inflAmnt[0] = calculateAverage(calculateTotal(inflAmnt), dataIsCount);
fcltyCpct[0] = calculateTotal(fcltyCpct);
inflAssctBfrWqltBod[0] = Number((calculateTotal(inflAssctBfrWqltBod)/7).toFixed(1));
inflAssctBfrWqltToc[0] = Number((calculateTotal(inflAssctBfrWqltToc)/7).toFixed(1));
inflAssctBfrWqltSs[0] = Number((calculateTotal(inflAssctBfrWqltSs)/7).toFixed(1));
inflAssctBfrWqltTn[0] = Number((calculateTotal(inflAssctBfrWqltTn)/7).toFixed(3));
inflAssctBfrWqltTp[0] = Number((calculateTotal(inflAssctBfrWqltTp)/7).toFixed(3));
efflWqltBod[0] = Number((calculateTotal(efflWqltBod)/7).toFixed(1));
efflWqltToc[0] = Number((calculateTotal(efflWqltToc)/7).toFixed(1));
efflWqltSs[0] = Number((calculateTotal(efflWqltSs as number[])/7).toFixed(1));
efflWqltTn[0] = Number((calculateTotal(efflWqltTn as number[])/7).toFixed(3));
efflWqltTp[0] = Number((calculateTotal(efflWqltTp as number[])/7).toFixed(3));
inflAssctBfrWqltBod[0] = Number((Math.round((totInflAssctBfrWqltBod / totItemCnt) * 10) / 10).toFixed(1));
inflAssctBfrWqltToc[0] = Number((Math.round((totInflAssctBfrWqltToc / totItemCnt) * 10) / 10).toFixed(1));
inflAssctBfrWqltSs[0] = Number((Math.round((totInflAssctBfrWqltSs / totItemCnt) * 10) / 10).toFixed(1));
inflAssctBfrWqltTn[0] = Number((Math.round((totInflAssctBfrWqltTn / totItemCnt) * 1000) / 1000).toFixed(3));
inflAssctBfrWqltTp[0] = Number((Math.round((totInflAssctBfrWqltTp / totItemCnt) * 1000) / 1000).toFixed(3));
efflWqltBod[0] = Number((Math.round((totEfflWqltBod / totItemCnt) * 10) / 10).toFixed(1));
efflWqltToc[0] = Number((Math.round((totEfflWqltToc / totItemCnt) * 10) / 10).toFixed(1));
efflWqltSs[0] = Number((Math.round((totEfflWqltSs / totItemCnt) * 10) / 10).toFixed(1));
efflWqltTn[0] = Number((Math.round((totEfflWqltTn / totItemCnt) * 1000) / 1000).toFixed(3));
efflWqltTp[0] = Number((Math.round((totEfflWqltTp / totItemCnt) * 1000) / 1000).toFixed(3));
// 최종 리스트
const filteredData = itemList.map((item, index) => ({
rainItem: item,
rainRate: rainRate[index] || '0',
rainDay: rainDate[index] ? Number(rainDate[index].toFixed(1)) : '',
inflAmnt: inflAmnt[index] ? Number(inflAmnt[index].toFixed(1)) : '',
fctCpc: inflAmnt[index] ? Number((inflAmnt[index] / fcltyCpcValue).toFixed(1)) : '',
dsInflWqltBod: dsInflWqltBod[index] ? Number(dsInflWqltBod[index].toFixed(1)) : '',
dsInflWqltCod: dsInflWqltCod[index] ? Number(dsInflWqltCod[index].toFixed(1)) : '',
dsInflWqltSs: dsInflWqltSs[index] ? Number(dsInflWqltSs[index].toFixed(1)) : '',
dsInflWqltTn: dsInflWqltTn[index] ? dsInflWqltTn[index].toFixed(3) : '',
dsInflWqltTp: dsInflWqltTp[index] ? dsInflWqltTp[index].toFixed(3) : '',
inflAssctBfrWqltBod: inflAssctBfrWqltBod[index] ? Number(inflAssctBfrWqltBod[index].toFixed(1)) : '',
inflAssctBfrWqltToc: inflAssctBfrWqltToc[index] ? Number(inflAssctBfrWqltToc[index].toFixed(1)) : '',
inflAssctBfrWqltSs: inflAssctBfrWqltSs[index] ? Number(inflAssctBfrWqltSs[index].toFixed(1)) : '',
inflAssctBfrWqltTn: inflAssctBfrWqltTn[index] ? inflAssctBfrWqltTn[index].toFixed(3) : '',
inflAssctBfrWqltTp: inflAssctBfrWqltTp[index] ? inflAssctBfrWqltTp[index].toFixed(3) : '',
efflWqltBod: efflWqltBod[index] ? Number(efflWqltBod[index].toFixed(1)) : '',
efflWqltToc: efflWqltToc[index] ? Number(efflWqltToc[index].toFixed(1)) : '',
efflWqltSs: efflWqltSs[index] ? Number(efflWqltSs[index].toFixed(1)) : '',
efflWqltTn: efflWqltTn[index] ? efflWqltTn[index].toFixed(3) : '',
efflWqltTp: efflWqltTp[index] ? efflWqltTp[index].toFixed(3) : ''
rainDay: rainDate[index] ? Number(rainDate[index].toFixed(1)) : '0',
inflAmnt: inflAmnt[index] ? Number((Math.round(inflAmnt[index] * 1) / 1)) : '',
fctCpc: inflAmnt[index] ? (Math.round((inflAmnt[index] / fcltyCpcValue) * 10) / 10).toFixed(1) : '',
dsInflWqltBod: dsInflWqltBod[index] ? (Math.round(dsInflWqltBod[index] * 10) / 10).toFixed(1) : '',
dsInflWqltCod: dsInflWqltCod[index] ? (Math.round(dsInflWqltCod[index] * 10) / 10).toFixed(1) : '',
dsInflWqltSs: dsInflWqltSs[index] ? (Math.round(dsInflWqltSs[index] * 10) / 10).toFixed(1) : '',
dsInflWqltTn: dsInflWqltTn[index] ? (Math.round(dsInflWqltTn[index] * 1000) / 1000).toFixed(3) : '',
dsInflWqltTp: dsInflWqltTp[index] ? (Math.round(dsInflWqltTp[index] * 1000) / 1000).toFixed(3) : '',
inflAssctBfrWqltBod: inflAssctBfrWqltBod[index] ? (Math.round(inflAssctBfrWqltBod[index] * 10) / 10).toFixed(1) : '',
inflAssctBfrWqltToc: inflAssctBfrWqltToc[index] ? (Math.round(inflAssctBfrWqltToc[index] * 10) / 10).toFixed(1) : '',
inflAssctBfrWqltSs: inflAssctBfrWqltSs[index] ? (Math.round(inflAssctBfrWqltSs[index] * 10) / 10).toFixed(1) : '',
inflAssctBfrWqltTn: inflAssctBfrWqltTn[index] ? (Math.round(inflAssctBfrWqltTn[index] * 1000) / 1000).toFixed(3) : '',
inflAssctBfrWqltTp: inflAssctBfrWqltTp[index] ? (Math.round(inflAssctBfrWqltTp[index] * 1000) / 1000).toFixed(3) : '',
efflWqltBod: efflWqltBod[index] ? (Math.round(efflWqltBod[index] * 10) / 10).toFixed(1): '',
efflWqltToc: efflWqltToc[index] ? (Math.round(efflWqltToc[index] * 10) / 10).toFixed(1) : '',
efflWqltSs: efflWqltSs[index] ? (Math.round(efflWqltSs[index] * 10) / 10).toFixed(1) : '',
efflWqltTn: efflWqltTn[index] ? (Math.round(efflWqltTn[index] * 1000) / 1000).toFixed(3) : '',
efflWqltTp: efflWqltTp[index] ? (Math.round(efflWqltTp[index] * 1000) / 1000).toFixed(3) : ''
}));
const excelList : RainManageExcelType[] = [];
@@ -1756,24 +1887,24 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
excelList.push({
강우량: item.rainItem,
강우조건비율: item.rainRate ? Number(Number(item.rainRate).toFixed(1)) : '',
일수: item.rainDay ? Number(Number(item.rainDay).toFixed(1)) : '',
유입유량: item.inflAmnt ? Number(Number(item.inflAmnt).toFixed(1)) : '',
시설용량대비: item.fctCpc ? Number(Number(item.fctCpc).toFixed(1)) : '',
설계유입수질BOD: item.dsInflWqltBod ? Number(Number(item.dsInflWqltBod).toFixed(1)) : '',
설계유입수질TOC: item.dsInflWqltCod ? Number(Number(item.dsInflWqltCod).toFixed(1)) : '',
설계유입수질SS: item.dsInflWqltSs ? Number(Number(item.dsInflWqltSs).toFixed(1)) : '',
설계유입수질TN: item.dsInflWqltTn ? Number(item.dsInflWqltTn).toFixed(3) : '',
설계유입수질TP: item.dsInflWqltTp ? Number(item.dsInflWqltTp).toFixed(3) : '',
유입수질BOD: item.inflAssctBfrWqltBod ? Number(Number(item.inflAssctBfrWqltBod).toFixed(1)) : '',
유입수질TOC: item.inflAssctBfrWqltToc ? Number(Number(item.inflAssctBfrWqltToc).toFixed(1)) : '',
유입수질SS: item.inflAssctBfrWqltSs ? Number(Number(item.inflAssctBfrWqltSs).toFixed(1)) : '',
유입수질TN: item.inflAssctBfrWqltTn ? Number(item.inflAssctBfrWqltTn).toFixed(3) : '',
유입수질TP: item.inflAssctBfrWqltTp ? Number(item.inflAssctBfrWqltTp).toFixed(3) : '',
방류수질BOD: item.efflWqltBod ? Number(Number(item.efflWqltBod).toFixed(1)) : '',
방류수질TOC: item.efflWqltToc ? Number(Number(item.efflWqltToc).toFixed(1)) : '',
방류수질SS: item.efflWqltSs ? Number(Number(item.efflWqltSs).toFixed(1)) : '',
방류수질TN: item.efflWqltTn ? Number(item.efflWqltTn).toFixed(3) : '',
방류수질TP: item.efflWqltTp ? Number(item.efflWqltTp).toFixed(3) : '',
일수: item.rainDay ? Number(Number(item.rainDay).toFixed(1)) : 0,
유입유량: item.inflAmnt ? Number((Math.round(Number(item.inflAmnt) * 1) / 1)) : '',
시설용량대비: item.fctCpc ? (Math.round(Number(item.fctCpc) * 10) / 10).toFixed(1) : '',
설계유입수질BOD: item.dsInflWqltBod ? (Math.round(Number(item.dsInflWqltBod) * 10) / 10).toFixed(1) : '',
설계유입수질TOC: item.dsInflWqltCod ? (Math.round(Number(item.dsInflWqltCod) * 10) / 10).toFixed(1) : '',
설계유입수질SS: item.dsInflWqltSs ? (Math.round(Number(item.dsInflWqltSs) * 10) / 10).toFixed(1) : '',
설계유입수질TN: item.dsInflWqltTn ?(Math.round(Number(item.dsInflWqltTn) * 1000) / 1000).toFixed(3) : '',
설계유입수질TP: item.dsInflWqltTp ? (Math.round(Number(item.dsInflWqltTp) * 1000) / 1000).toFixed(3) : '',
유입수질BOD: item.inflAssctBfrWqltBod ? (Math.round(Number(item.inflAssctBfrWqltBod) * 10) / 10).toFixed(1) : '',
유입수질TOC: item.inflAssctBfrWqltToc ? (Math.round(Number(item.inflAssctBfrWqltToc) * 10) / 10).toFixed(1) : '',
유입수질SS: item.inflAssctBfrWqltSs ? (Math.round(Number(item.inflAssctBfrWqltSs) * 10) / 10).toFixed(1) : '',
유입수질TN: item.inflAssctBfrWqltTn ? (Math.round(Number(item.inflAssctBfrWqltTn) * 1000) / 1000).toFixed(3) : '',
유입수질TP: item.inflAssctBfrWqltTp ? (Math.round(Number(item.inflAssctBfrWqltTp) * 1000) / 1000).toFixed(3) : '',
방류수질BOD: item.efflWqltBod ? (Math.round(Number(item.efflWqltBod) * 10) / 10).toFixed(1) : '',
방류수질TOC: item.efflWqltToc ? (Math.round(Number(item.efflWqltToc) * 10) / 10).toFixed(1) : '',
방류수질SS: item.efflWqltSs ? (Math.round(Number(item.efflWqltSs) * 10) / 10).toFixed(1) : '',
방류수질TN: item.efflWqltTn ? (Math.round(Number(item.efflWqltTn) * 1000) / 1000).toFixed(3) : '',
방류수질TP: item.efflWqltTp ? (Math.round(Number(item.efflWqltTp) * 1000) / 1000).toFixed(3) : '',
});
});
}
@@ -1782,12 +1913,12 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
...state,
RainManage: isExcel ? {
...state.RainManage,
rainManageList: filteredData as RainManageListProps[],
rainManageList: filteredData as any[],
excelList: excelList,
isLoadingRainManage : false,
} : {
...state.RainManage,
rainManageList: filteredData as RainManageListProps[],
rainManageList: filteredData as any[],
isLoadingRainManage : false,
}
}));
@@ -68,36 +68,33 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row: 1 },
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row: 1 },
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
];
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row: 1} ,
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row: 1},
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row: 1},
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
];
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row: 1},
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row: 1},
@@ -108,11 +105,11 @@ const upHeadList3:TableUpperProps[] = [
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row: 1},
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2, align:"right"},
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2, align:"right"},
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2, align:"right"}
];
const facilityPrecipitation:FacilityPrecipitationProps[] = [
@@ -124,9 +121,9 @@ const facilityPrecipitation:FacilityPrecipitationProps[] = [
// 강수현황 (헤더)
const upHeadListPrecipitationDetail:TableUpperProps[] = [
{ id: "rainDt", title: "날짜"},
{ id: "infoRnDay", title: "강수량(mm/일)"},
{ id: "rainDay", title: "강우일(일)"},
{ id: "rainEffectDay", title: "강우영향일(일)"}
{ id: "infoRnDay", title: "강수량(mm/일)", align:"right"},
{ id: "rainDay", title: "강우일(일)", align:"right"},
{ id: "rainEffectDay", title: "강우영향일(일)", align:"right"}
]
// 강수현황 (리스트)
const gridListPrecipitationDetail:PrecipitationPropsDetailProps[] = [
@@ -122,7 +122,6 @@ const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별',
// 시설수질리스트 헤더(행정별)
const upHeadList1: TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", rowSpan: 2, row:0 },
{ id: "C", title: "행정명", colSpan: 2, row: 0 },
{ id: "sidoNm", title: "시도", row: 1 },
{ id: "sggNm", title: "시군구", row: 1 },
@@ -145,7 +144,6 @@ const upHeadList1: TableUpperProps[] = [
// 시설수질리스트 헤더(권역별)
const upHeadList2: TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "C", title: "유역", colSpan: 3, row: 0 },
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1 },
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1 },
@@ -169,7 +167,6 @@ const upHeadList2: TableUpperProps[] = [
// 시설수질리스트 헤더(환경청별)
const upHeadList3: TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "C", title: "유역", colSpan: 3, row: 0 },
{ id: "rvbsn", title: "권역", row:1 },
{ id: "lgbsn", title: "단위유역", row:1 },
@@ -269,7 +266,7 @@ const fetchFacilityWaterQltyTmsList = async (facilityCd: string|undefined) => {
};
// 시설정보 수질 리스트 데이터 호출(모달-이력)
const fetchFacilityWaterQltyListHist = async (searchYear: string|undefined, facilityCd: string|undefined): Promise<WaterQualityHistoryResponse | null> => {
export const fetchFacilityWaterQltyListHist = async (searchYear: string|undefined, facilityCd: string|undefined): Promise<WaterQualityHistoryResponse | null> => {
try {//
const res = await getFetch('fo', '/fclt/qlty/hist/' + searchYear + '/' + facilityCd);
return res;
@@ -452,6 +449,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.inflAssctBfrWqltToc = Number(searchYear)<2021? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear)<2021? "("+item.efflWqltToc+")" : item.efflWqltToc;
excelDownList.push({
시설코드: item.bscFctCd,
권역: item.rvbsn,
@@ -481,6 +480,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.inflAssctBfrWqltToc = Number(searchYear)<2021? "("+item.inflAssctBfrWqltToc+")" : item.inflAssctBfrWqltToc;
item.efflWqltToc = Number(searchYear)<2021? "("+item.efflWqltToc+")" : item.efflWqltToc;
});
}
set((state: FacilityWaterQltyType) => ({
@@ -603,12 +604,12 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) > 3) {
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) > 3) {
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
@@ -659,7 +660,6 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
}else{
item.tpInflWqltBod = '';
}
if(item.tpInflWqltTp){
item.tpInflWqltTp = item.tpInflWqltTp?Number(Math.round(Number(item.tpInflWqltTp) * 1000)/1000).toFixed(3): Number(item.tpInflWqltTp)===0?'0.000':'';
}else{
+9 -12
View File
@@ -91,7 +91,6 @@ export type FlowRateModalProps = {
*/
// 리스트 (행정별)
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
{ id: "A", title: "행정명", row: 0 ,colSpan: 2 },
{ id: "sido", title: "시도", upName:"upChangeRe", row:1 },
{ id: "gugun", title: "시군구", upName:"upChangeRe", row:1 },
@@ -107,7 +106,6 @@ const upHeadList1:TableUpperProps[] = [
// 리스트 (권역별)
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
{ id: "A", title: "유역", row: 0, colSpan: 3},
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1 },
@@ -124,7 +122,6 @@ const upHeadList2:TableUpperProps[] = [
// 리스트 (환경청별별)
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row: 0, colSpan: 3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1 },
@@ -157,7 +154,7 @@ const upHeadListFlowRateModal:TableUpperProps[] = [
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
/* { id: "infoRnDay", title: "강우량(mm/일)", align:"right"} */
{ id: "infoRnDay", title: "강우량(mm/일)", align:"right"}
]
const modalFlowRateListYear:FlowRateModalProps[] = [
@@ -233,12 +230,12 @@ export type FlowRateSearchStore = FlowRateSearchType & FlowRateSearchActions;
const dataFormSetting=(item : flowRateListProps | FlowRateModalProps)=> {
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'totInflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'sumFlow', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'efflWqltBod', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'returnAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'efflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'totInflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'sumFlow', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'efflWqltBod', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'returnAmnt', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'efflAmnt', item: item as unknown as Record<string, unknown>});
}
export const flowRateSearchInitState:FlowRateSearchType = {
@@ -351,12 +348,12 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
+6 -9
View File
@@ -44,7 +44,6 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "행정구역", upSequnce:1, row:0, colSpan:2 },
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
@@ -52,12 +51,11 @@ const upHeadList1:TableUpperProps[] = [
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
];
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1},
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1},
@@ -66,12 +64,11 @@ const upHeadList2:TableUpperProps[] = [
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
];
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1},
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1},
@@ -84,7 +81,7 @@ const upHeadList3:TableUpperProps[] = [
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
{ id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' },
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
];
@@ -122,9 +119,9 @@ export type ExcelType = {
}
const dataFormSetting=(item : PlanSewageProps)=> {
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'spareCapacity', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'spareCapacity', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'classifiedSewerPercent', item: item as unknown as Record<string, unknown>});
};
+76 -77
View File
@@ -19,12 +19,12 @@ export type ProcessAreaProps = {
location : string,
fctCpc : number | '',
ruse : boolean,
yrDt4 : string,
yr : string,
yrDc1 : string,
yrDc2 : string,
yrDc3 : string,
yrDc4 : string,
planYrDt4 : string,
planYr : string,
planYrDc1 : string,
planYrDc2 : string,
planYrDc3 : string,
planYrDc4 : string,
/**
* 증설계획
*/
@@ -128,7 +128,6 @@ const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용
// 리스트 헤더(행정별)
const upHeadList1:TableUpperProps[] = [
{ id: "swtrmtFcltCd", title: "시설코드", rowSpan:3, row:0},
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0},
{ id: "sido", title: "시도", upName:"upChangeRe", row:2 },
{ id: "sigungo", title: "시군구", upName:"upChangeRe", row:2 },
@@ -137,26 +136,26 @@ const upHeadList1:TableUpperProps[] = [
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0},
{ id: "B", title: "시설계획", colSpan:19, row:0},
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row:1},
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2},
{ id: "planSwageQntSum", title: "현재", row:2},
{ id: "planSwageQntSumDc1", title: "1단계", row:2},
{ id: "planSwageQntSumDc2", title: "2단계", row:2},
{ id: "planSwageQntSumDc3", title: "3단계", row:2},
{ id: "planSwageQntSumDc4", title: "4단계", row:2},
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2, align:"right"},
{ id: "planSwageQntSum", title: "현재", row:2, align:"right"},
{ id: "planSwageQntSumDc1", title: "1단계", row:2, align:"right"},
{ id: "planSwageQntSumDc2", title: "2단계", row:2, align:"right"},
{ id: "planSwageQntSumDc3", title: "3단계", row:2, align:"right"},
{ id: "planSwageQntSumDc4", title: "4단계", row:2, align:"right"},
{ id: "D", title: "처리인구(인)", colSpan:6, row:1},
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2},
{ id: "swtrmtPpltnCnt", title: "현재", row:2},
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2},
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2},
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2},
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2},
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2, align:"right"},
{ id: "swtrmtPpltnCnt", title: "현재", row:2, align:"right"},
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2, align:"right"},
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2, align:"right"},
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2, align:"right"},
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2, align:"right"},
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1},
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2},
{ id: "swtrmtZoneArea", title: "현재", row:2},
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2},
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2},
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2},
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2},
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2, align:"right"},
{ id: "swtrmtZoneArea", title: "현재", row:2, align:"right"},
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2, align:"right"},
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2, align:"right"},
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2, align:"right"},
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2, align:"right"},
{ id: "trtDstr", title: "처리구역", row:2}
];
@@ -168,13 +167,13 @@ const processAreaList:ProcessAreaProps[] = [
*/
// 시설증설 계획 (헤더)
const upHeadListFcltyImproveInfo:TableUpperProps[] = [
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan:2, row:0},
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "증설계획(m³/일)", colSpan:5, row:0},
{ id: "planSwageQntSum", title: "현재", row:1},
{ id: "planSwageQntSumDc1", title: "1단계", row:1},
{ id: "planSwageQntSumDc2", title: "2단계", row:1},
{ id: "planSwageQntSumDc3", title: "3단계", row:1},
{ id: "planSwageQntSumDc4", title: "4단계", row:1},
{ id: "planSwageQntSum", title: "현재", row:1, align:"right"},
{ id: "planSwageQntSumDc1", title: "1단계", row:1, align:"right"},
{ id: "planSwageQntSumDc2", title: "2단계", row:1, align:"right"},
{ id: "planSwageQntSumDc3", title: "3단계", row:1, align:"right"},
{ id: "planSwageQntSumDc4", title: "4단계", row:1, align:"right"},
];
// 시설증설 계획 (리스트)
@@ -183,13 +182,13 @@ const gridListFcltyImproveInfo:FcltyImproveInfoProps[] = [
// 처리인구 계획 (헤더)
const upHeadListProcessPopulation:TableUpperProps[] = [
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan:2, row:0},
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "처리인구(인)", colSpan:5, row:0},
{ id: "swtrmtPpltnCnt", title: "현재", row:1},
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:1},
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:1},
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:1},
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:1},
{ id: "swtrmtPpltnCnt", title: "현재", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:1, align:"right"},
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:1, align:"right"},
];
// 처리인구 계획 (리스트)
@@ -198,13 +197,13 @@ const gridListProcessPopulation:ProcessPopulationProps[] = [
// 처리구역 계획 (헤더)
const upHeadListProcessAreaPlan:TableUpperProps[] = [
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan:2, row:0},
{ id: "A", title: "처리면적(km²)", colSpan:6, row:0},
{ id: "swtrmtZoneArea", title: "현재", row:1},
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:1},
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:1},
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:1},
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:1},
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan:2, row:0, align:"right"},
{ id: "A", title: "처리면적(km²)", colSpan:6, row:0, align:"right"},
{ id: "swtrmtZoneArea", title: "현재", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:1, align:"right"},
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:1, align:"right"},
{ id: "trtDstr", title: "처리구역", row:1}
];
@@ -236,17 +235,17 @@ const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm :
res.map(async (item: ProcessAreaProps) => {
upHeadList1.forEach((head:TableUpperProps) => {
/* if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재\n(' + item.yr + '년)';
head.title = '현재\n(' + item.planYr + '년)';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계\n(' + item.yrDc1 + '년)';
head.title = '1단계\n(' + item.planYrDc1 + '년)';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계\n(' + item.yrDc2 + '년)';
head.title = '2단계\n(' + item.planYrDc2 + '년)';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계\n(' + item.yrDc3 + '년)';
head.title = '3단계\n(' + item.planYrDc3 + '년)';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계\n(' + item.yrDc4 + '년)';
head.title = '4단계\n(' + item.planYrDc4 + '년)';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + item.yrDt4 + '년)';
head.title = '기승인\n4단계(' + item.planYrDt4 + '년)';
} */
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재';
@@ -432,51 +431,51 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
set((state: ProcessAreaType) => {
const rtnData = state.ProcessArea.processAreaList.find((item: ProcessAreaProps) => item.swtrmtFcltCd === swtrmtFcltCd);
if (rtnData) {
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.yrDc1? '1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.yrDc2? '2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.yrDc4? '4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.yrDt4? '기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
}
});
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.planYr? '현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.planYrDc1? '1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.planYrDc2? '2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.planYrDc3? '3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.planYrDc4? '4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.planYrDt4? '기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
}
});
upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재';
head.title = rtnData.planYr? '현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
head.title = rtnData.planYrDc1?'1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
head.title = rtnData.planYrDc2?'2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
head.title = rtnData.planYrDc3? '3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
head.title = rtnData.planYrDc4?'4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
head.title = rtnData.planYrDt4?'기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
}
});
upHeadListProcessPopulation.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.yr?'현재\n(' + rtnData.yr + '년)':head.title = '현재';
head.title = rtnData.planYr?'현재\n(' + rtnData.planYr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
head.title = rtnData.planYrDc1?'1단계\n(' + rtnData.planYrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
head.title = rtnData.planYrDc2?'2단계\n(' + rtnData.planYrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.yrDc3?'3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
head.title = rtnData.planYrDc3?'3단계\n(' + rtnData.planYrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
head.title = rtnData.planYrDc4?'4단계\n(' + rtnData.planYrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
head.title = rtnData.planYrDt4?'기승인\n4단계(' + rtnData.planYrDt4 + '년)':head.title = '기승인\n4단계';
}
});
+37 -12
View File
@@ -117,7 +117,8 @@ export type fcltyHistInfoProps = {
rnDt : string,
sitArea : number,
trtDstrArea : number,
swrTrtPopl : number
swrTrtPopl : number,
fcltCpc : number | ''
}
// 시설 수질정보
@@ -161,7 +162,6 @@ const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드"},
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1 },
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2 },
{ id: "bscFctNm", title: "시설명"},
@@ -177,7 +177,6 @@ const upHeadList1:TableUpperProps[] = [
// 처리시설 리스트 (유역)
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드"},
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1},
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2},
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3},
@@ -194,7 +193,6 @@ const upHeadList2:TableUpperProps[] = [
// 처리시설 리스트 (환경청청)
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드"},
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1},
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2},
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3},
@@ -330,6 +328,7 @@ const upHeadListFcltyHistInfo:TableUpperProps[] = [
{ id: "cmplDt", title: "준공일"},
{ id: "trlrnCmplDt", title: "시운전완료일"},
{ id: "rnDt", title: "가동개시일"},
{ id: "fctCpc", title: "시설용량(m³/일)", align: 'right' },
];
// 시설 이력관리 (리스트)
@@ -346,6 +345,7 @@ const gridListFcltyHistInfo:fcltyHistInfoProps[] = [
sitArea : 0,
trtDstrArea : 0,
swrTrtPopl : 0,
fcltCpc : 860000
}
];
@@ -601,7 +601,7 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
res.data.forEach((item:facilityListProps) => {
DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record<string, unknown>});
DataForm({ type: 'date', column: 'rnDt', item:item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
})
res.data.forEach(item => {
@@ -613,7 +613,6 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
if(pageSize>5000){
res.data.forEach(item => {
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
excelDownList.push({
시설코드: item.bscFctCd,
권역: item.rvbsn,
@@ -633,10 +632,6 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
관리대행업자: item.mnstr,
})
})
}else{
res.data.forEach(item => {
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
})
}
set((state:ProcessFacilityType) => ({
...state,
@@ -676,7 +671,6 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
item.plInflWqltBod = item.plInflWqltBod ? Number(item.plInflWqltBod).toFixed(1) : '';
item.dsInflWqltBod = item.dsInflWqltBod ? Number(item.dsInflWqltBod).toFixed(1) : '';
}) */
console.log(res.data);
set((state:ProcessFacilityType) => ({
...state,
ProcessFacilityList: {
@@ -783,6 +777,29 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
}
});
sortedWaterQltyInfo.forEach(item => {
DataForm({ type: 'float1', column: 'plInflWqltBod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plInflWqltToc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plInflWqltCod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plInflWqltSs', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'plInflWqltTn', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'plInflWqltTp', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'dsInflWqltBod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'dsInflWqltToc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'dsInflWqltCod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'dsInflWqltSs', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'dsInflWqltTn', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'dsInflWqltTp', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plEfflWqltBod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plEfflWqltToc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plEfflWqltCod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'plEfflWqltSs', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'plEfflWqltTn', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'plEfflWqltTp', item: item as unknown as Record<string, unknown> });
});
// 법적수질정보 초기화 및 push
gridListLegalWaterQlty = [];
@@ -795,6 +812,14 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
totClfgrpcnt : Number(facilityWaterQltyInfo[0]?.totClfgrpcnt ?? 0),
});
gridListLegalWaterQlty.forEach(item => {
DataForm({ type: 'float1', column: 'bod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'cod', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'ss', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'tn', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float3', column: 'tp', item: item as unknown as Record<string, unknown> });
});
// 마지막 수질 데이터의 값을 gridListPlanInfo에 업데이트
if (sortedWaterQltyInfo.length > 0) {
const lastWaterQltyInfo = sortedWaterQltyInfo[sortedWaterQltyInfo.length - 1];
@@ -818,7 +843,7 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
plInflWqltSs: lastWaterQltyInfo?.plInflWqltSs === 'NULL' || lastWaterQltyInfo?.plInflWqltSs === undefined ? '' : lastWaterQltyInfo.plInflWqltSs,
plInflWqltTn: lastWaterQltyInfo?.plInflWqltTn === 'NULL' || lastWaterQltyInfo?.plInflWqltTn === undefined ? '' : lastWaterQltyInfo.plInflWqltTn,
plInflWqltTp: lastWaterQltyInfo?.plInflWqltTp === 'NULL' || lastWaterQltyInfo?.plInflWqltTp === undefined ? '' : lastWaterQltyInfo.plInflWqltTp
}]
}],
}
}));
} else {
+58 -22
View File
@@ -1,6 +1,8 @@
import { getFetch } from "@/app/components/api";
import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty";
import { calRainEffectDay } from "../underWaterInput";
export type { TableUpperProps };
/**====================================
* Store - 타입
@@ -19,7 +21,7 @@ export type RdiProps = {
daddr : string,
fctCpc : number,
summerMinBodValue : number,
inflAmnt : number,
inflAmnt : number | string | '',
winterAvgBodLowRainfall : number,
rdiiValue : number,
infoRnDay : number,
@@ -27,6 +29,7 @@ export type RdiProps = {
rvbsn : string,
lgbsn : string,
mdmbsn : string,
rainEffectDay : number, // 강우영향일
}
export interface RdiInterface {
@@ -78,7 +81,7 @@ export interface ExcelType {
주소: string,
시설용량: number,
하절기강우일최저유입BOD: number | '',
하절기최저유입BOD유입유량: number | '',
하절기최저유입BOD유입유량: number | string | '',
동절기청천시유입BOD: number | '',
RDII추정 : number | '',
RDII추정시일강수량 : number | '',
@@ -86,7 +89,6 @@ export interface ExcelType {
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "행정구역", row:0, colSpan:2 },
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "sigungo", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
@@ -95,15 +97,14 @@ const upHeadList1:TableUpperProps[] = [
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2 },
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중 최저 유입BOD\n(mg/L)", align:"right", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1, align:"right" },
{ id: "C", title: "동절기 운영현황(1~2월)", row:0 },
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1 },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
{ id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2 },
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right" },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
{ id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2, align:"right" },
];
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
@@ -113,15 +114,14 @@ const upHeadList2:TableUpperProps[] = [
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" },
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" },
];
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
@@ -135,11 +135,11 @@ const upHeadList3:TableUpperProps[] = [
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
{ id: "C", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" },
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" },
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" },
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" },
];
const rdiList:RdiProps[] = [
@@ -206,11 +206,12 @@ export const rdiInitState: RdiType = {
}
const dataFormSetting=(item : RdiProps)=> {
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'summerMinBodValue', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'winterAvgBodLowRainfall', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'rdiiValue', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'infoRnDay', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'rdiiValue', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float1', column: 'infoRnDay', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
}
// Add type definitions for state setter function
@@ -238,10 +239,45 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
...item,
sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '',
sigungo: item.lclgvrnmntNm.split(' ')[1]?.toString() || '',
inflAmnt: item.inflAmnt?item.inflAmnt.toFixed(1) : ''
inflAmnt: item.inflAmnt?Number(item.inflAmnt).toFixed(1): ''
}
})
// 청천히 동절기 유입bod를 새로 구하기 위해서 재 호출
for (const item of rtnData) {
const fcltyCd = item.bscFctCd;
let winterInflBod = 0;
const res: any = await fetchFacilityWaterQltyListHist(searchYear, fcltyCd);
if (res?.data) {
const rtnWqltData = res.data.wqltObjs;
rtnWqltData.forEach((dataItem: any) => {
dataItem.rainEffectDay = 0;
});
calRainEffectDay(rtnWqltData, 'SUNNY');
const rtnWqltWinterData = rtnWqltData.filter((dataItem: any) =>
(dataItem.msrDt.substring(4, 6) === '01' ||
dataItem.msrDt.substring(4, 6) === '02') &&
dataItem.rainEffectDay == 0
);
rtnWqltWinterData.forEach((dataItem: any) => {
winterInflBod += dataItem.inflAssctBfrWqltBod
? Number(dataItem.inflAssctBfrWqltBod)
: 0;
});
if (rtnWqltWinterData.length > 0) {
winterInflBod = winterInflBod / rtnWqltWinterData.length;
}
}
item.winterAvgBodLowRainfall = winterInflBod;
}
rtnData.forEach((item: RdiProps) => {
dataFormSetting(item)
})
+30 -32
View File
@@ -1,3 +1,4 @@
import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
export type { TableUpperProps };
@@ -59,7 +60,6 @@ export interface ExcelType {
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
@@ -74,7 +74,6 @@ const upHeadList1:TableUpperProps[] = [
];
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
@@ -90,7 +89,6 @@ const upHeadList2:TableUpperProps[] = [
];
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
@@ -111,9 +109,9 @@ const upHeadList3:TableUpperProps[] = [
const upHeadListSewageOccurDetail:TableUpperProps[] = [
{ id: "msrDt", title: "년월" },
{ id: "waterUsage", title: "물사용량(m³/일)" },
{ id: "swageChangePercent", title: "오수전환율(%)" },
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row:0, rowSpan:2 },
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right" },
{ id: "swageChangePercent", title: "오수전환율(%)", align:"right" },
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row:0, rowSpan:2, align:"right" },
];
const sewageOccurList:SewageOccurProps[] = []
@@ -129,7 +127,6 @@ const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
const res = await getFetch('fo', url);
console.log("res", res.data);
return { data: res.data, count: res.count }
/*
@@ -229,7 +226,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.swageChangePercent = 80;
item.swageChangePercent = 90;
const bscFctCd = item.bscFctCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
@@ -237,10 +234,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
let sumChungcunDay = 0;
let chungcunSumFlow = 0;
let totWaterUsage = 0;
if(bscFctCd === '11200PB001R'){
console.log('res2.data : ',res2.data);
}
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
for(let idx = 0; idx < res2.data.length; idx++) {
const item = res2.data[idx];
@@ -270,21 +264,17 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
for(let idx = 0; idx < res2.data.length; idx++) {
if(res2.data[idx] && res2.data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.infoRnDay = res2.data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.infoRnDay = res2.data[idx-2]!.infoRnDay;
}
}
}
}
if(bscFctCd === '11200PB001R'){
console.log('calData : ',res2.data);
}
res2.data.forEach((item: FlowDataItem) => {
@@ -303,6 +293,15 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
return item;
}));
calData.forEach((item: SewageOccurProps) => {
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'waterUsage', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'swageChangePercent', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'estimationSewage', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'sewageInputYear', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'sewageInputChungchun', item: item as unknown as Record<string, unknown> });
});
if(pageSize>5000){
calData.forEach((item: SewageOccurProps) => {
excelDownList.push({
@@ -312,8 +311,8 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
중권역: item.mdmbsn,
환경청: item.rgnNm,
시설명: item.bscFctNm,
시도: item.sidoNm, // sido ?? 타입에러 나서 수정함
시군구: item.sggNm, //sgg ??
시도: item.sidoNm,
시군구: item.sggNm,
주소: item.daddr,
시설용량: item.fctCpc,
물사용량: item.waterUsage,
@@ -345,7 +344,6 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt= 0;
console.log('startYearMonth : ', startYearMonth, 'endYearMonth : ', endYearMonth);
if(startYearMonth) {
res.data = res.data.filter((item: FlowDataItem) => {
const month = item.msrDt?.substring(0, 6);
@@ -373,7 +371,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
tot += Number(item.inflAmnt)
cnt++
})
console.log('tot', tot, cnt, tot/cnt, tot/cnt*0.65);
const tableData:modalTableType[] = []
let maxWaterUsage = 0;
@@ -383,9 +381,9 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
item.usege = item.sum/item.cnt *0.65
tableData.push({
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
waterUsage: Math.round(item.usege*100) /100,
swageChangePercent: (Math.round((item.usege/item.usege*0.8) * 100) / 100) * 100,
estimationSewage: Math.round(item.usege*0.8 * 100) / 100
waterUsage: Math.round(item.usege*1) /1,
swageChangePercent: (Math.round((item.usege/item.usege*0.9) * 100) / 100) * 100,
estimationSewage: Math.round(item.usege*0.9 * 1) / 1
})
if (item.usege > maxWaterUsage) {
maxWaterUsage = item.usege;
@@ -401,21 +399,21 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
const newData= [
{
msrDt: '평균',
waterUsage: Math.round(avgWaterUsage*100) /100,
swageChangePercent: 80,
estimationSewage: Math.round(avgWaterUsage*0.8*100) /100,
waterUsage: Math.round(avgWaterUsage*1) /1,
swageChangePercent: 90,
estimationSewage: Math.round(avgWaterUsage*0.9*1) /1,
},
{
msrDt: '최대',
waterUsage: Math.round(maxWaterUsage*100) /100,
swageChangePercent: 80,
estimationSewage: Math.round(maxWaterUsage*0.8*100) /100,
swageChangePercent: 90,
estimationSewage: Math.round(maxWaterUsage*0.9*1) /1,
},
{
msrDt: '최소',
waterUsage: Math.round(minWaterUsage*100) /100,
swageChangePercent: 80,
estimationSewage: Math.round(minWaterUsage*0.8*100) /100,
swageChangePercent: 90,
estimationSewage: Math.round(minWaterUsage*0.9*1) /1,
},
...tableData
]
+53 -45
View File
@@ -1,6 +1,6 @@
import { getFetch } from "@/app/components/api";
import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types";
export type { TableUpperProps };
@@ -32,7 +32,6 @@ const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
@@ -46,7 +45,6 @@ const upHeadList1:TableUpperProps[] = [
];
const upHeadList2:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
@@ -61,7 +59,6 @@ const upHeadList2:TableUpperProps[] = [
];
const upHeadList3:TableUpperProps[] = [
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
@@ -82,9 +79,9 @@ const upHeadList3:TableUpperProps[] = [
// 모달
const upHeadListUnderWaterDetail:TableUpperProps[] = [
{ id: "msrDt", title: "날짜" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)", align:"right" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)", align:"right" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)", align:"right" },
];
const underWaterList:UnderWaterProps[] = [
@@ -201,7 +198,7 @@ const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear:
====================================*/
export type UnderWaterActions = {
searchUnderWaterList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
unserWaterModal:(bscFctCd:string, searchYear:string)=>void
unserWaterModal:(bscFctCd:string, searchYear:string, startYm:string, endYm:string)=>void
}
export type UnderWaterType = {
@@ -253,15 +250,21 @@ export const underWaterInitState: UnderWaterType = {
}
const dataFormSetting=(item : UnderWaterProps)=> {
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float0', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
}
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
export const calRainEffectDay = (data: FlowDataItem[], weather: string) => {
/**
*
* @param data
* @param weather ('ALL' | 'SUNNY' | 'RAINY')
* @returns
*/
export const calRainEffectDay = (data: any, weather: string) => {
// 강우영향일 계산 (강우량이 3 이상이면 무조건 강우영향일)
for(let idx = 0; idx < data.length; idx++) {
const item = data[idx];
@@ -291,12 +294,12 @@ export const calRainEffectDay = (data: FlowDataItem[], weather: string) => {
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
@@ -359,9 +362,14 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
item.underWaterInputYear = Math.round((usage-(usage*0.65*0.8)) * 100) / 100;
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100;
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100;
if(bscFctCd === '11200PB001R') {
console.log('calData.length : ', calData.length);
console.log('usage : ', usage, 'summerUsage : ', summerUsage, 'winterUsage : ', winterUsage);
}
item.underWaterInputYear = Math.round((usage-(usage*0.65*0.9)) * 1) / 1;
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.9)) * 1) / 1;
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.9)) * 1) / 1;
return item;
}));
@@ -412,25 +420,19 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
},
}))
},
unserWaterModal:async (bscFctCd, searchYear)=>{
console.log('searchYear : ', searchYear);
unserWaterModal:async (bscFctCd, searchYear, startYm, endYm)=>{
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
const calData = calRainEffectDay(res.data, 'SUNNY');
let tot = 0, cnt= 0;
let tmpTot = 0;
calData.forEach((item: FlowDataItem) => {
tmpTot += Number(item.inflAmnt);
})
console.log('tmpTot : ', tmpTot/calData.length);
let tot = 0;
let cnt = 0;
calData.forEach((item: FlowDataItem) => {
const month = item.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
if (monthIdx >= 0) {
if (monthIdx >= 0 && (monthIdx>=Number(startYm.substring(4,6))-1 && monthIdx <= Number(endYm.substring(4, 6))-1)) {
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sum += Number(item.inflAmnt);
monthData[monthIdx].cnt++;
@@ -438,9 +440,12 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4), usege:0};
}
}
tot += Number(item.inflAmnt)
cnt++
})
if(month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){
cnt++;
tot += item.inflAmnt && item.inflAmnt !== 'x' ? Number(item.inflAmnt.toString().trim()) : 0;
}
});
const tableData:UnderWaterInputModalProps[] = []
let maxWaterUsage = 0;
@@ -450,9 +455,9 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
item.usege = item.sum/item.cnt
tableData.push({
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
realSewageInput:Math.round(item.usege*100) /100,
sewageOccur:Math.round(item.usege*0.65*0.8 * 100) / 100,
underWaterInput:Math.round((item.usege-(item.usege*0.65*0.8)) * 100) / 100,
realSewageInput:Math.round(item.usege*1) /1,
sewageOccur:Math.round(item.usege*0.65*0.9 * 1) / 1,
underWaterInput:Math.round((item.usege-(item.usege*0.65*0.9)) * 1) / 1,
})
if (item.usege > maxWaterUsage) {
maxWaterUsage = item.usege;
@@ -463,25 +468,28 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
}
});
avgWaterUsage = tot/cnt
console.log('tot', tot, 'calData.length', calData.length);
avgWaterUsage = tot/cnt;
console.log(avgWaterUsage);
const newData= [
{
msrDt: '평균',
realSewageInput:Math.round(avgWaterUsage*100) /100,
sewageOccur:Math.round(avgWaterUsage*0.65*0.8 * 100) / 100,
underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
realSewageInput:Math.round(avgWaterUsage*1) /1,
sewageOccur:Math.round(avgWaterUsage*0.65*0.9 * 1) / 1,
underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.9)) * 1) / 1
//underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
},
{
msrDt: '최대',
realSewageInput: Math.round(maxWaterUsage*100) /100,
sewageOccur: Math.round(maxWaterUsage*0.65*0.8 * 100) / 100,
underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*0.8)) * 100) / 100,
realSewageInput: Math.round(maxWaterUsage*1) /1,
sewageOccur: Math.round(maxWaterUsage*0.65*0.9 * 1) / 1,
underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*0.9)) * 1) / 1,
},
{
msrDt: '최소',
realSewageInput: Math.round(minWaterUsage*100) /100,
sewageOccur: Math.round(minWaterUsage*0.65*0.8 * 100) / 100,
underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*0.8)) * 100) / 100,
realSewageInput: Math.round(minWaterUsage*1) /1,
sewageOccur: Math.round(minWaterUsage*0.65*0.9 * 1) / 1,
underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*0.9)) * 1) / 1,
},
...tableData
]
+2
View File
@@ -4,6 +4,7 @@ import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const isProd = process.env.NODE_ENV === "production";
const compat = new FlatCompat({
baseDirectory: __dirname,
@@ -14,6 +15,7 @@ const eslintConfig = [
{rules:{
// other rules..
"@typescript-eslint/no-explicit-any": "off",
...(isProd ? { "react-hooks/exhaustive-deps": "off" } : {}),
}},
];
+6 -8
View File
@@ -1,15 +1,13 @@
NEXT_PUBLIC_SITE_ID = SN
NEXT_PUBLIC_PORT = 11302
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
# NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PORT = 11302
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api
+6 -8
View File
@@ -1,16 +1,14 @@
NEXT_PUBLIC_SITE_ID = SN
NEXT_PUBLIC_PORT = 3002
NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
# NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PORT = 3002
NEXT_PUBLIC_PROXY_HOST = http://localhost:3002
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api
+3 -5
View File
@@ -6,10 +6,8 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = https://sn.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver
# NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com
NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC
NEXT_PUBLIC_SEWERAGE_API_URL = http://con.mind-one.co.kr:11083/sewerage-service/api
NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/sewerage-service/api
+3 -2
View File
@@ -19,10 +19,11 @@ export default function MapLayout({
const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo);
const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore();
const { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore();
useEffect(() => {
fetchCtpvSggData();
fetchCtpv();
fetchSgg();
fetchBIZ_SE_CD();
fetchBIZ_TY_CD();
}, []);
@@ -43,7 +43,7 @@ export const codeMapper = ({ layerName, data }: CodeMapperProps): any => {
// usg_cd 값 변환 (용도코드)
if (processedData.usg_cd) {
const usageCodeItem = MS_SWAGE_MHL_USE_CODES.find(
code => code.val === processedData.usg_cd.trim()
code => code.val.trim() === processedData.usg_cd.trim()
);
if (usageCodeItem) {
processedData.usg_cd = usageCodeItem.text;
@@ -31,17 +31,21 @@ export const MsSwagePplCol2 = [
{ id: 'rowNumber', title: '일련\n번호' },
{ id: 'fcltMngNo', title: '시설\n관리번호' },
{ id: 'instMngNo', title: '기관\n관리번호' },
{ id: 'ctpvNm', title: '시도' },
{ id: 'sggNm', title: '시군구' },
{ id: "swtrmt_zone_nm", title: "처리구역" },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'mapshtNo', title: '도엽번호' },
{ id: 'usgCd', title: '용도' },
{ id: 'pdmtVl', title: '관경\n(mm)' },
{ id: 'prlgVl', title: '연장\n(m)' },
{ id: 'avgGrdn', title: '평균구배\n(m/m)' },
// { id: 'avgGrdn', title: '평균구배\n(m/m)' },
{ id: 'tmptDpth', title: '시점깊이\n(m)' },
{ id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' },
{ id: 'scendDpth', title: '종점깊이\n(m)' },
{ id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' },
{ id: 'vrtcLen', title: '세로길이\n(m)' },
{ id: 'wdthLen', title: '가로길이\n(m)' },
// { id: 'vrtcLen', title: '세로길이\n(m)' },
// { id: 'wdthLen', title: '가로길이\n(m)' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
// { id: 'fid', title: 'FID' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
@@ -51,6 +55,21 @@ export const MsSwagePplCol2 = [
// { id: 'usgCd', title: '용도코드' },
// { id: 'lyrTypeNm', title: '레이어타입명' },
]
export const MsSwagePplExcelCol = {
'fcltMngNo': '시설 관리번호',
'instMngNo': '기관 관리번호',
'ctpvNm': '시도',
'sggNm': '시군구',
'swtrmt_zone_nm': '처리구역',
'instlYmd': '설치일자',
'usgCd': '용도',
'pdmtVl': '관경(mm)',
'prlgVl': '연장(m)',
'tmptDpth': '시점 깊이(m)',
'tmptMhlMngNo': '시점맨홀 관리번호',
'scendDpth': '종점 깊이(m)',
'scendMhlMngNo': '종점맨홀 관리번호',
};
// 하수관로 용도 코드표
export const MS_SWAGE_PPL_USE_CODES = [
{ val: "SBA000", text: "미분류" },
@@ -335,6 +354,18 @@ export const SwtrmtFcltCol2 = [
// { id: 'bsnNm', title: '유역명' },
// { id: 'obsrvnSptCd', title: '관측지점코드' },
];
export const SwtrmtFcltExcelCol = {
'swtrmtFcltNm': '하수처리시설명',
'fcltCpct': '시설 용량(㎥/d)',
'rgnExpln': '지역설명',
'oprtngStrtYmd': '가동개시 일자',
'laeNm': '지자체명',
'sareaNm': '권역명',
'rvrNm': '하천명',
'dschgWtstNm': '방류수계명',
'swtrmtPpltnCnt': '하수 처리 인구수(인)',
'rprsMsrcCn': '대표 공법 내용'
};
// 하수처리구역
export const SwtrmtPrcsZoneCol = [
@@ -358,6 +389,12 @@ export const SwtrmtPrcsZoneCol2 = [
{ id: 'sggNm', title: '시군구' },
{ id: 'swtrmtFcltNm', title: '하수처리시설명' },
];
export const SwtrmtPrcsZoneExcelCol = {
'swtrmtZoneNm': '하수처리구역명',
'ctpvNm': '시도',
'sggNm': '시군구',
'swtrmtFcltNm': '하수처리시설명'
};
// 하수맨홀
export const MsSwageMhlCol = [
@@ -388,16 +425,18 @@ export const MsSwageMhlCol2 = [
// { id: 'geom', title: 'geometry' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
{ id: 'fcltMngNo', title: '시설관리번호' },
{ id: 'ctpvNm', title: '시도' },
{ id: 'sggNm', title: '시군구' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
// { id: 'mapshtNo', title: '도엽번호' },
// { id: 'mngInstCd', title: '관리기관코드' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'lastDrdgnYmd', title: '최종준설일자' },
// { id: 'usgCd', title: '용도코드' },
{ id: 'usgCd', title: '용도' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
// { id: 'mhlKndCd', title: '맨홀종류코드' },
{ id: 'swageMhlDiamVl', title: '하수맨홀구경(mm)' },
{ id: 'mqltCd', title: '재질코드' },
// { id: 'mqltCd', title: '재질코드' },
{ id: 'wdthLen', title: '가로길이(m)' },
{ id: 'vrtcLen', title: '세로길이(m)' },
// { id: 'angDir', title: '표고' },
@@ -405,6 +444,18 @@ export const MsSwageMhlCol2 = [
{ id: 'dpthlVl', title: '심도(m)' },
// { id: 'instMngNo', title: '기관관리번호' }
];
export const MsSwageMhlExcelCol = {
'fcltMngNo': '시설관리번호',
'ctpvNm': '시도',
'sggNm': '시군구',
'instlYmd': '설치일자',
'usgCd': '용도',
'swageMhlDiamVl': '하수맨홀구경(mm)',
'wdthLen': '가로길이(m)',
'vrtcLen': '세로길이(m)',
'altdVl': '표고(EL.m)',
'dpthlVl': '심도(m)'
};
// 하수맨홀 뚜껑재질 코드표
export const MS_SWAGE_MHL_CODES = [
{ val: "SBC000", text: "미분류" },
@@ -442,31 +493,31 @@ export const MS_SWAGE_MHL_CODES = [
];
// 하수맨홀 용도 코드표
export const MS_SWAGE_MHL_USE_CODES = [
{ val: "SMU000", text: "미분류" },
{ val: "SMU001", text: "우수" },
{ val: "SMU002", text: "오수" },
{ val: "SMU003", text: "집수" },
{ val: "SMU004", text: "합류" },
{ val: "SMU005", text: "차집" },
{ val: "SMU999", text: "기타" },
{ val: "SMU900", text: "1호" },
{ val: "SMU901", text: "2호" },
{ val: "SMU902", text: "3호" },
{ val: "SMU903", text: "4호" },
{ val: "SMU904", text: "5호" },
{ val: "SMU905", text: "6호" },
{ val: "SMU906", text: "7호" },
{ val: "SMU907", text: "8호" },
{ val: "SMU908", text: "구거용맨홀" },
{ val: "SMU909", text: "부관부착맨홀" },
{ val: "SMU910", text: "조립식맨홀" },
{ val: "SMU911", text: "특1호" },
{ val: "SMU912", text: "특2호" },
{ val: "SMU913", text: "특3호" },
{ val: "SMU914", text: "특4호" },
{ val: "SMU915", text: "특5호" },
{ val: "SMU916", text: "하수맨홀용도" },
{ val: "SMU917", text: "현장타설관거용" }
{ val: "SMU000 ", text: "미분류" },
{ val: "SMU001 ", text: "우수" },
{ val: "SMU002 ", text: "오수" },
{ val: "SMU003 ", text: "집수" },
{ val: "SMU004 ", text: "합류" },
{ val: "SMU005 ", text: "차집" },
{ val: "SMU999 ", text: "기타" },
{ val: "SMU900 ", text: "1호" },
{ val: "SMU901 ", text: "2호" },
{ val: "SMU902 ", text: "3호" },
{ val: "SMU903 ", text: "4호" },
{ val: "SMU904 ", text: "5호" },
{ val: "SMU905 ", text: "6호" },
{ val: "SMU906 ", text: "7호" },
{ val: "SMU907 ", text: "8호" },
{ val: "SMU908 ", text: "구거용맨홀" },
{ val: "SMU909 ", text: "부관부착맨홀" },
{ val: "SMU910 ", text: "조립식맨홀" },
{ val: "SMU911 ", text: "특1호" },
{ val: "SMU912 ", text: "특2호" },
{ val: "SMU913 ", text: "특3호" },
{ val: "SMU914 ", text: "특4호" },
{ val: "SMU915 ", text: "특5호" },
{ val: "SMU916 ", text: "하수맨홀용도" },
{ val: "SMU917 ", text: "현장타설관거용" }
];
// 우수펌프장
@@ -496,12 +547,14 @@ export const ExclnSewagePumpCol2 = [
// { id: 'geom', title: 'geometry' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
{ id: 'fcltMngNo', title: '시설관리번호' },
{ id: 'ctpvNm', title: '시도' },
{ id: 'sggNm', title: '시군구' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
// { id: 'mapshtNo', title: '도엽번호' },
// { id: 'mngInstCd', title: '관리기관코드' },
{ id: 'instlYmd', title: '설치일자' },
{ id: 'swagePmstnNm', title: '하수펌프장명' },
{ id: 'pllnArea', title: '부지면적(m²)' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'pllnArea', title: '부지면적(m²)' },
// { id: 'opngSttsCd', title: '개통상태코드' },
// { id: 'usgCd', title: '용도코드' },
{ id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' },
@@ -511,6 +564,18 @@ export const ExclnSewagePumpCol2 = [
{ id: 'exclnWpmpAbltVl', title: '우수양수능력(m²/d)' },
// { id: 'instMngNo', title: '기관관리번호' },
]
export const ExclnSewagePumpExcelCol = {
'fcltMngNo': '시설관리번호',
'ctpvNm': '시도',
'sggNm': '시군구',
'swagePmstnNm': '하수펌프장명',
'instlYmd': '설치일자',
'dailyPrcsCpct': '일일처리용량(㎥)',
'maxImpndCpct': '최대저수용량(㎥)',
'altdVl': '표고(EL.m)',
'wtlvVl': '수위(m)',
'exclnWpmpAbltVl': '우수양수능력(m²/d)'
};
// 오수펌프장
export const DrtwSewagePumpCol = [
// { id: 'fid', title: 'FID' },
@@ -539,11 +604,13 @@ export const DrtwSewagePumpCol2 = [
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
{ id: 'fcltMngNo', title: '시설관리번호' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
{ id: 'mapshtNo', title: '도엽번호' },
// { id: 'mapshtNo', title: '도엽번호' },
{ id: 'ctpvNm', title: '시도' },
{ id: 'sggNm', title: '시군구' },
// { id: 'mngInstCd', title: '관리기관코드' },
{ id: 'instlYmd', title: '설치일자' },
{ id: 'swagePmstnNm', title: '하수펌프장명' },
{ id: 'pllnArea', title: '부지면적(m²)' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'pllnArea', title: '부지면적(m²)' },
// { id: 'opngSttsCd', title: '개통상태코드' },
// { id: 'usgCd', title: '용도코드' },
{ id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' },
@@ -585,6 +652,8 @@ export const stofcbrCol2 = [
{ id: 'fcltMngNo', title: '시설관리번호' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
{ id: 'mapshtNo', title: '도엽번호' },
{ id: 'ctpvNm', title: '시도' },
{ id: 'sggNm', title: '시군구' },
// { id: 'mngInstCd', title: '관리기관코드' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
@@ -594,6 +663,16 @@ export const stofcbrCol2 = [
{ id: 'swageMhlMngNo', title: '하수맨홀관리번호' },
{ id: 'drtnAngl', title: '방향각도(°)' },
]
export const stofcbrExcelCol = {
'fcltMngNo': '시설관리번호',
'mapshtNo': '도엽번호',
'ctpvNm': '시도',
'sggNm': '시군구',
'instlYmd': '설치일자',
'worflwWallHgt': '월류벽높이(m)',
'swageMhlMngNo': '하수맨홀관리번호',
'drtnAngl': '방향각도(°)'
};
// 중점우수토실 측정지점
export const untrtSwgRainCol1 = [
@@ -657,7 +736,7 @@ export const dateFields = [
// 🎯 camelCase 버전 추가
'instlYmd', 'lastDrdgnYmd', 'cmcnYmd', 'oprtngStrtYmd', 'clsgYmd',
'mesureBeginDt', 'mesureEndDt', 'qltwtrBeginDt', 'qltwtrEndDt',
'rainBeginDt', 'rainEndDt',
'rainBeginDt', 'rainEndDt',
'flfmtBgngYmd', 'flfmtEndYmd', 'flfmtYr'
];
@@ -275,7 +275,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// API에서 상세 데이터 가져오기
if (apiEndpoint) {
try {
console.log(`API 호출: ${apiEndpoint}`);
const result = await getData(apiEndpoint);
if (result) {
@@ -386,7 +385,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
const ContentComponent = layerNm ? getLayerContentComponent(layerNm) : null;
return (
<div id="popup" className="absolute top-0 right-0 w-[350px] h-[calc(100vh-10rem)] bg-white border-r border-gray-300 flex flex-col overflow-hidden transition-all duration-300 z-[50]">
<div id="popup" className="absolute top-0 right-0 w-[350px] h-[calc(100vh-5rem)] bg-white border-r border-gray-300 flex flex-col overflow-hidden transition-all duration-300 z-[50]">
<LoadingOverlay isLoading={isLoading} />
<div className="card-header bg-primary flex items-center justify-between relative p-4">
<div className="flex items-center space-x-4 flex-1">
@@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react'
const exclnInputColumn = [
{ id: "swtrmtZoneNm", title: "배수구역", type: "input" },
{ id: "mltvDtdvNm", title: "배수분구", type: "input" },
{ id: "designFrqYr", title: "설계빈도(년)", type: "input" },
{ id: "designFrqYr", title: "설계빈도(년)", type: "input", placeholder: "예: 10", isNumber: true, length: 4 },
]
// 오수펌프장 자체 입력 정보
const drtwInputColumn = [
+29 -27
View File
@@ -1,6 +1,6 @@
"use client";
import Gis, { useGisContext } from "@common/business_components/ui/map/Gis";
import Gis from "@common/business_components/ui/map/Gis";
import { getData } from "../../components/lib/api";
import { useCallback, useEffect, useRef, useState } from "react";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
@@ -43,7 +43,6 @@ const Map = () => {
const [showWaterDepth, setShowWaterDepth] = useState(false); // WaterDepth 표시 여부
const [isPlaying, setIsPlaying] = useState(false);
useEffect(() => {
fetchData();
}, []);
@@ -96,6 +95,7 @@ const Map = () => {
});
}
// 3. 피처 선택
if (foundFeature) {
let geometry = foundFeature.getGeometry();
@@ -138,31 +138,33 @@ const Map = () => {
return (
<div className="bg-container">
<Gis
treeData={treeData}
isSearch={true}
gisMaps={gisMaps}
isMiniMap={false}
searchView={SearchModal}
detailView={FeatureClickEventPopup}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
searchBar={<ProcSearchBar gisMaps={gisMaps} facilityTypes={facilityTypes} />}
waterDepth={showWaterDepth ? WaterDepth : undefined}
isPlaying={isPlaying}
setIsPlaying={setIsPlaying as any}
targetLayerTypes={WATER_DEPTH_LAYER_TYPES as any}
orderedLayers={ORDERED_LAYERS as any}
checkInterval={2500}
/>
</div>
<>
<div className="bg-container">
<Gis
treeData={treeData}
isSearch={true}
gisMaps={gisMaps}
isMiniMap={false}
searchView={SearchModal}
detailView={FeatureClickEventPopup}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
searchBar={<ProcSearchBar gisMaps={gisMaps} facilityTypes={facilityTypes} />}
waterDepth={showWaterDepth ? WaterDepth : undefined}
isPlaying={isPlaying}
setIsPlaying={setIsPlaying as any}
targetLayerTypes={WATER_DEPTH_LAYER_TYPES as any}
orderedLayers={ORDERED_LAYERS as any}
checkInterval={2500}
/>
</div>
</>
);
};
@@ -1,12 +1,13 @@
import React from 'react';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import { Button, Label } from '@common/components';
import SwagePpl from './swagePpl';
import SwagePrcsFclt from './swagePrcsFclt';
import SwagePrcsZone from './swagePrcsZone';
import SwageMhl from './swageMhl';
import SwagePmstn from './swagePmstn';
import Stofcbr from './stofcbr';
// 기본정보 '구분' 선택 목록
export const BASIC_TYPES = [
@@ -20,8 +21,8 @@ export const BASIC_TYPES = [
interface BasicTabProps {
basicType: string;
city: number;
sgg: number;
city: string;
sgg: string;
start1: string;
start2: string;
end1: string;
@@ -31,9 +32,9 @@ interface BasicTabProps {
yearFilter: { start: string; end: string; };
handleSearch: () => void;
setBasicType: (type: string) => void;
setCity: (city: number) => void;
setCity: (city: string) => void;
setCtpvName: (name: string) => void;
setSgg: (sgg: number) => void;
setSgg: (sgg: string) => void;
setSggName: (name: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setStart1: (value: string) => void;
@@ -97,6 +98,8 @@ const BasicTab: React.FC<BasicTabProps> = ({
start2={start2}
end1={end1}
end2={end2}
city={city}
sgg={sgg}
yearFilter={yearFilter}
setVar1={setVar1}
setVar2={setVar2}
@@ -104,6 +107,8 @@ const BasicTab: React.FC<BasicTabProps> = ({
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
@@ -152,10 +157,14 @@ const BasicTab: React.FC<BasicTabProps> = ({
var1={var1}
start1={start1}
end1={end1}
city={city}
sgg={sgg}
yearFilter={yearFilter}
setVar1={setVar1}
setStart1={setStart1}
setEnd1={setEnd1}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
@@ -167,33 +176,30 @@ const BasicTab: React.FC<BasicTabProps> = ({
start2={start2}
end1={end1}
end2={end2}
city={city}
sgg={sgg}
yearFilter={yearFilter}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 우수토실 */}
{basicType === "tb_ms_stofcbr" && (
<div className="mb-3">
{/* 설치년도 */}
<div className="flex items-center mb-2">
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
<Stofcbr
city={city}
sgg={sgg}
yearFilter={yearFilter}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
</div>
);
@@ -24,7 +24,10 @@ export const operationTableHeadlist = [
export const operationMaintenanceTableHeadlist = [
{ id: 'rowNumber', title: '일련번호' },
{ id: "fcltMngNo", title: "관리번호" },
{ id: "swtrmt_zone_nm", title: "처리구역" },
{ id: "usgCd", title: "용도" },
// { id: "lgalDrblyr", title: "내용연수" },
// { id: "acqsPrmpc", title: "취득금액" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmtVl", title: "관경(mm)" },
{ id: "prlgVl", title: "연장(m)" },
@@ -35,7 +38,10 @@ export const operationMaintenanceTableHeadlist = [
export const operationCleaningTableHeadlist = [
{ id: 'rowNumber', title: '일련번호' },
{ id: "fcltMngNo", title: "관리번호" },
{ id: "swtrmt_zone_nm", title: "처리구역" },
{ id: "usgCd", title: "용도" },
// { id: "lgalDrblyr", title: "내용연수" },
// { id: "acqsPrmpc", title: "취득금액" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmtVl", title: "관경(mm)" },
{ id: "prlgVl", title: "연장(m)" },
@@ -45,13 +51,18 @@ export const operationCleaningTableHeadlist = [
export const operationInspectionTableHeadlist = [
{ id: 'rowNumber', title: '일련번호' },
{ id: "fcltMngNo", title: "관리번호" },
{ id: "swtrmt_zone_nm", title: "처리구역" },
{ id: "usgCd", title: "용도" },
// { id: "riskEval", title: "위험평가" },
// { id: "acqsPrmpc", title: "취득금액" },
// { id: "lgalDrblyr", title: "내용연수" },
// { id: "remLife", title: "잔존수명" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmtVl", title: "관경(mm)" },
{ id: "prlgVl", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
{ id: "strct_stat_grd", title: "구조적 상태등급" },
{ id: "oper_stat_grd", title: "운영적 상태등급" },
{ id: "strc_stts_grd", title: "구조적 상태등급" },
{ id: "oper_stts_grd", title: "운영적 상태등급" },
];
interface OperationTabProps {
@@ -128,7 +139,7 @@ const OperationTab: React.FC<OperationTabProps> = ({
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label=""
selectArray={BIZ_TY_CD_SELECT_ARRAY}
selectArray={[{ val: "0", text: "전체" }, ...BIZ_TY_CD_SELECT_ARRAY]}
value={var2}
onSelectValue={(val) => {
setVar2(String(val));
@@ -0,0 +1,108 @@
'use client'
import React, { useEffect, useState } from 'react';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { getFileDownload, getDcFiles, useDcFiles } from './searchModalReportApi';
import { type ReportDataFile } from './searchModalReportApi';
import { useReportFileModalStore } from './searchModalReportApi'; // 모달 상태 관리 스토어
import { UiTable } from '@common/business_components/ui';
import { UiModal } from "@common/business_components";
type ModalOpenProp = {
clsfSystmSn: string, // 자료관 기본계획 일련번호
}
// 하수도정비 기본계획 보고서 파일목록
export const headlist = [
{ id: "no", title: "NO" },
{ id: "fileTitle", title: "파일명" },
{ id: "regDt", title: "등록일자" },
];
const ReportFiles: React.FC<ModalOpenProp> = ({ clsfSystmSn }: ModalOpenProp) => {
const [isLoading, setIsLoading] = useState(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useReportFileModalStore(); // 모달 상태 관리 스토어
const [files, setFiles] = useState<ReportDataFile[]>([]);
const [curPage, setCurPage] = useState(1);
const filesOrigin = useDcFiles(clsfSystmSn); // 자료관 기본계획 일련번호에 해당하는 파일 목록을 가져오기 위한 훅
useEffect(() => {
if (isModalOpen === true) {
getFiles(); // 파일 목록 조회
} else {
setFiles([]); // 모달이 닫힐 때 파일 목록 초기화
setCurPage(1); // 페이지를 1로 초기화
setIsResetPage(true); // 페이지를 초기화
setIsResetSelection(true); // 선택 초기화
}
}, [filesOrigin, isModalOpen, curPage]);
// 파일 목록 조회
const getFiles = async () => {
setIsLoading(true); // 로딩 시작
try {
//let data = await getDcFiles(clsfSystmSn);
let data = filesOrigin;
data = data?.slice((curPage - 1) * 10, curPage * 10); // paging
data = data?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
setFiles(data);
} catch (error) {
console.error("파일 목록 조회 에러:", error);
} finally {
setIsLoading(false); // 로딩 종료
}
};
// cellClick 핸들러
const handleCellClick = (index: number|undefined) => {
if (typeof index === "number" && files[index]) {
const fileName = files[index].fileTitle;
const filePath = files[index].filePath;
if (files[index].fileSn !== "") {
getFileDownload(files[index].fileSn, fileName, filePath);
}
}
};
const renderBody = () => (
<>
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
return (<>조회 결과 ({filesOrigin.length.toLocaleString('ko-KR')})건</>);
})()
}
tableData={files}
headlist={headlist}
pageSize={10}
total={filesOrigin.length}
cellClick={handleCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
/>
</div>
</>
);
return (
<UiModal
open={isModalOpen}
onOpenChange={setIsModalOpen}
headerTitle=""
bodyClass={`
min-h-[50vh] h-[570px]
min-w-[35vw] w-[400px]
max-w-none max-h-none
overflow-visible
z-[5000]
flex items-start
`}
body={renderBody()}
noFooterYn='Y'
/>
);
};
export default React.memo(ReportFiles);
@@ -4,9 +4,11 @@ import { Button, Label } from '@common/components';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox, UiTable } from '@common/business_components/ui';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { addFileName, flattenFolders, getFileDownload, getDcTree, useDcTree, reportGubuns } from './searchModalReportApi';
import { addFileName, flattenFolders, getFileDownload, useDcTree, reportGubuns } from './searchModalReportApi';
import useStore from '../../../store/useStore';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
import { useReportFileModalStore } from './searchModalReportApi'; // 모달 상태 관리 스토어
import ReportFiles from './reportFiles'; // 파일목록모달
// 하수도정비 기본계획 보고서
@@ -37,11 +39,12 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
const [tableCount, setTableCount] = useState(0);
const [curPage, setCurPage] = useState(1);
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
const [ctpvCd, setCtpvCd] = useState(0);
const [sggCd, setSggCd] = useState(0);
const [ctpvCd, setCtpvCd] = useState('0');
const [sggCd, setSggCd] = useState('0');
const [reportGubun, setReportGubun] = useState("0");
// const [gubun, setGubun] = useState("");
const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useReportFileModalStore(); // 모달 상태 관리 스토어
const [clsfSystmSn, setClsfSystmSn] = useState(''); // 자료관 기본계획 일련번호
const { ctpv, sgg } = useStore();
// 하수정비기본계획 report
@@ -49,8 +52,8 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
useEffect(() => {
// filterParams 초기화
setCtpvCd(0);
setSggCd(0);
setCtpvCd('0');
setSggCd('0');
setReportGubun('0');
setYearFilter({ start: "", end: "" });
setShowTable(false);
@@ -62,8 +65,8 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
}, [open]);
useEffect(() => {
let newCtpvCd = ctpv.find((n) => n.name === ctpvNm)?.id || 0;
let newSggCd = sgg.find((n) => n.name === sggNm)?.id || 0;
const newCtpvCd = ctpv.find((n) => n.text === ctpvNm)?.val || '0';
const newSggCd = sgg.find((n) => n.text === sggNm)?.val || '0';
setCtpvCd(newCtpvCd);
setSggCd(newSggCd);
@@ -84,9 +87,9 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
if (showTable) fetchFilteredData();
}, [curPage]);
const handleCtpvCdChange = (sidoId: number) => {
const handleCtpvCdChange = (sidoId: string) => {
setCtpvCd(sidoId);
setSggCd(0);
setSggCd('0');
}
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
@@ -100,13 +103,14 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
// 하수도정비기본계획 테이블 cellClick 핸들러
const handleReportCellClick = (index: number | undefined) => {
console.log(index);
if (typeof index === "number" && tableData[index]) {
const reportData = tableData[index];
const fileName = reportData.fileName;
const filePath = reportData.filePath;
if (reportData.fileSn !== "") {
getFileDownload(reportData.fileSn, fileName, filePath);
//getFileDownload(reportData.fileSn, fileName, filePath);
setIsModalOpen(true); // 모달 열기
setClsfSystmSn(reportData.clsfSystmSn); // 자료관 기본계획 일련번호 설정
}
}
};
@@ -119,21 +123,14 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
try {
const reportData = flattenFolders(reportOriginData);
let filterReportData = reportData;
console.log("필터링 전 보고서 데이터:", filterReportData);
console.log('ctpv, sgg, ctpvCd, sggCd', ctpv, sgg, ctpvCd, sggCd);
if (ctpvCd) { // 시도검색
console.log('시도 실행되나');
const sidoOption = ctpv.find((n) => String(n.id) === String(ctpvCd));
console.log('sidoOption', sidoOption)
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.name);
console.log('시도 필터링 후:', filterReportData);
if (ctpvCd !== '0') { // 시도검색
const sidoOption = ctpv.find((n) => n.val.trim() === ctpvCd.trim());
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text);
}
if (sggCd) { // 시군구검색
console.log('시군구 실행되나');
const sigunguOption = sgg.find((n) => String(n.id) === String(sggCd));
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.name);
console.log('시군구 필터링 후:', filterReportData);
if (sggCd !== '0') { // 시군구검색
const sigunguOption = sgg.find((n) => String(n.val) === String(sggCd));
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text);
}
if (reportGubun !== "0") { // 보고서구분검색
const reportGubunOption = reportGubuns.find((n) => n.val === reportGubun);
@@ -186,7 +183,7 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
<CtpvSggPrcsFcltSelectBox
sido={ctpvCd}
sigungu={sggCd}
onSidoChange={(sidoId: number) => { handleCtpvCdChange(sidoId) }}
onSidoChange={(sidoId: string) => { handleCtpvCdChange(sidoId) }}
onSigunguChange={setSggCd}
setIsLoading={setIsLoading}
/>
@@ -236,6 +233,8 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
/>
</div>
</div>
{/* 모달 컴포넌트 */}
{isModalOpen && <ReportFiles clsfSystmSn={clsfSystmSn} />}
</>
);
};
@@ -1,15 +1,22 @@
import LoadingOverlay from '@/components/ui/LoadingBar';
import { UiModal, UITab, UiTable } from '@common/business_components/ui';
import axios from 'axios';
import React, { useEffect, useMemo, useState } from 'react';
import { ExclnSewagePumpCol2, MsSwageMhlCol2, MsSwagePplCol2, stofcbrCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2 } from '../components/common/table';
import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES } from '../components/common/table';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { UiModal, UITab, UiTable, downloadExcelWithKoreanHeaders } from '@common/business_components/ui';
import { Button } from '@common/components/ui';
import axios from 'axios';
import {
ExclnSewagePumpCol2, MsSwageMhlCol2, MsSwagePplCol2, stofcbrCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2,
MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES,
MsSwagePplExcelCol, SwtrmtFcltExcelCol, SwtrmtPrcsZoneExcelCol, MsSwageMhlExcelCol, ExclnSewagePumpExcelCol, stofcbrExcelCol
} from '../components/common/table';
import { getData } from "@/components/lib/api";
import BasicTab, { BASIC_TYPES } from './basicTab';
import OperationTab, { operationCleaningTableHeadlist, operationInspectionTableHeadlist, operationMaintenanceTableHeadlist, operationTableHeadlist, WORK_TYPES } from './operationTab';
import ReportTab from './reportTab';
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
import useStore from '../../../store/useStore';
import GisApp from "@common/business_components/ui/map/lib/gis.core";
import { confirmToast } from '@/components/ui/toast'
import { toast, Toaster } from "react-hot-toast";
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`;
@@ -19,6 +26,8 @@ const TABS = [
{ val: "report", text: "하수도정비기본계획보고서" },
];
const OPERATION_TABLE_SIZE = 5;
// 날짜 조합 함수
const getDateString = (
year: string,
@@ -61,9 +70,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const [isResetDetailSelection, setIsResetDetailSelection] = useState<boolean>(false);
const [detailBizId, setDetailBizId] = useState(0);
const [city, setCity] = useState<number>(0);
const [ctpvCd, setCtpvCd] = useState<string>("0");
const [ctpvName, setCtpvName] = useState<string>('');
const [sgg, setSgg] = useState<number>(0);
const [sggCd, setSggCd] = useState<string>("0");
const [sggName, setSggName] = useState<string>('');
const [start1, setStart1] = useState("");
const [start2, setStart2] = useState("");
@@ -76,7 +85,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 시작, 종료
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
const { BIZ_TY_CD } = useStore();
const { ctpv, sgg, BIZ_TY_CD, BIZ_SE_CD } = useStore();
// 오늘 날짜 구하기
@@ -87,12 +96,12 @@ const SearchModal: React.FC<SearchModalProps> = ({
const dynamicHeadlist: { id: string, title: string }[] = useMemo(() => {
if (activeTab === 'basic') {
if (basicType === 'tb_ms_swage_ppl') return MsSwagePplCol2;
if (basicType === 'tb_il_swage_prcs_fclt') return SwtrmtFcltCol2;
if (basicType === 'tb_ms_swage_prcs_zone') return SwtrmtPrcsZoneCol2;
if (basicType === 'tb_ms_swage_mhl') return MsSwageMhlCol2;
if (basicType === 'tb_ms_swage_pmstn') return ExclnSewagePumpCol2;
if (basicType === 'tb_ms_stofcbr') return stofcbrCol2;
if (basicType === 'tb_ms_swage_ppl') return MsSwagePplCol2; // 하수관로
if (basicType === 'tb_il_swage_prcs_fclt') return SwtrmtFcltCol2; // 하수처리시설
if (basicType === 'tb_ms_swage_prcs_zone') return SwtrmtPrcsZoneCol2; // 하수처리구역
if (basicType === 'tb_ms_swage_mhl') return MsSwageMhlCol2; // 하수맨홀
if (basicType === 'tb_ms_swage_pmstn') return ExclnSewagePumpCol2; // 하수펌프장
if (basicType === 'tb_ms_stofcbr') return stofcbrCol2; // 우수토실
return [];
}
@@ -104,8 +113,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
const dynamicHeadlist2: { id: string, title: string }[] = useMemo(() => {
if (activeTab === 'operation') {
if (workType === WORK_TYPES[0]?.val) return operationMaintenanceTableHeadlist;
if (workType === WORK_TYPES[1]?.val) return operationCleaningTableHeadlist;
if (workType === WORK_TYPES[2]?.val) return operationInspectionTableHeadlist;
if (workType === WORK_TYPES[1]?.val) return operationInspectionTableHeadlist;
if (workType === WORK_TYPES[2]?.val) return operationCleaningTableHeadlist;
}
return [];
@@ -121,8 +130,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
setVar2("");
setVar3("");
setVar4("");
setCity(0);
setSgg(0);
setCtpvCd("0");
setSggCd("0");
setYearFilter({
start: "",
end: "",
@@ -138,6 +147,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
setIsResetDetailPage(true); // 디테일 페이지를 초기화
setIsResetSelection(true); // 선택 초기화
setIsResetDetailSelection(true); // 선택 초기화
setDetailBizId(0);
// queryParams는 fetchFilteredData 내에서 매번 새로 생성되므로 별도 상태 초기화는 필요 없음
}, [activeTab, basicType, workType, open]);
@@ -149,6 +159,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
setTableData([]);
setDetailTableCount(0);
setDetailTableData([]);
setDetailBizId(0);
}, [open]);
// 페이지 변경 시마다 데이터 fetch
@@ -156,6 +167,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
// showTable이 true일 때만 fetch (최초 렌더 방지)
setIsResetPage(false);
setIsResetDetailPage(true);
setDetailBizId(0);
if (showTable) fetchFilteredData();
}, [curPage]);
@@ -184,7 +196,6 @@ const SearchModal: React.FC<SearchModalProps> = ({
size: '10',
sort: 'string',
});
console.log('basicType', basicType);
if (basicType === 'tb_ms_swage_prcs_zone') cqlFilters = zoneCqlFilters(); // 하수처리구역
else if (basicType === 'tb_il_swage_prcs_fclt') cqlFilters = facilityCqlFilters(); // 하수처리시설
@@ -195,34 +206,50 @@ const SearchModal: React.FC<SearchModalProps> = ({
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
console.log('API URL:', `${API_URL}/v1/fclts?${queryParams.toString()}`);
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
console.log('필터링된 API 결과(개수):', res.data.count);
console.log('필터링된 API 결과(데이터):', res.data.data);
console.log('api:', `${API_URL}/v1/fclts?${queryParams.toString()}`);
// 🎯 각 아이템을 개별적으로 포맷팅하면서 일련번호 추가
const dataWithRowNumber = (res.data.data || []).map((item: any, index: number) => {
// 🎯 먼저 각 아이템을 포맷팅
const formattedItem = formatDisplayData(item);
const matched = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim());
let ctpvCd = item?.ctpvNm ?? formattedItem?.ctpvNm ?? '';
let sggCd = item?.sggNm ?? formattedItem?.sggNm ?? '';
if (!ctpvCd || !sggCd) {
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
if (!sggCd && code) sggCd = code.slice(0, 5);
}
const matchedMhlCode = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim());
const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find(code => code.val === item?.usgCd);
const ctpvNm = ctpv.find(code => code.val.trim() === ctpvCd)?.text || ctpvCd;
const sggNm = sgg.find(code => code.val.trim() === sggCd)?.text || '-';
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
// 추가 처리 및 일련번호 추가
return {
...formattedItem,
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn, // scsYn이 null이면 'N'으로 변경
mqltCd: matched ? matched.text : item.mqltCd,
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item?.scsYn, // scsYn이 null이면 'N'으로 변경
mqltCd: matchedMhlCode ? matchedMhlCode.text : item?.mqltCd,
usgCd: matchedMhlUsgCode ? matchedMhlUsgCode.text : (usgCdObj ? usgCdObj.text : item?.usgCd),
ctpvNm,
sggNm,
swtrmt_zone_nm: item.swtrmtZoneNm || item.swtrmt_zone_nm || '-',
};
});
console.log("dataWithRowNumber: ", dataWithRowNumber)
setTableData(dataWithRowNumber);
setTableCount(res.data.count || []);
console.log('tableCount 상태 업데이트 후:', res.data.count); // tableCount 로그 추가
} else if (activeTab === 'operation') {
const RequestDTO: Record<string, string> = {
page: `${curPage - 1}`,
size: '5',
size: `${OPERATION_TABLE_SIZE}`,
};
if (var1) RequestDTO.bizInfoNm = var1;
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
@@ -247,18 +274,15 @@ const SearchModal: React.FC<SearchModalProps> = ({
const params = new URLSearchParams(RequestDTO).toString();
console.log('API URL:', `/v1/bizInfo?${params}`);
const res = await getData(`v1/bizInfo?${params}`);
console.log('필터링된 API 결과(개수):', res.totalElements);
console.log('필터링된 API 결과(데이터):', res.content);
console.log('운영정보 사업 데이터:', res.content);
const mappedContent = (res.content || []).map((item: any, index: number) => {
console.log("item:", item);
const formattedItem = formatDisplayData(item);
const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTypeCd);
return {
...formattedItem,
rowNumber: (curPage - 1) * 5 + index + 1, // 1부터 시작하는 일련번호 추가
rowNumber: (curPage - 1) * OPERATION_TABLE_SIZE + index + 1, // 1부터 시작하는 일련번호 추가
bizTypeCd: matched ? matched.lwpoCdNm : item.bizTypeCd,
};
});
@@ -270,12 +294,14 @@ const SearchModal: React.FC<SearchModalProps> = ({
}
setShowTable(true);
setIsResetSelection(false);
} catch (err) {
console.error('API ERROR:', err);
setTableData([]);
setIsResetSelection(false);
} finally {
setIsLoading(false); // 로딩 종료
// setIsResetSelection(false);
setIsResetSelection(false);
// setIsResetDetailSelection(false);
}
};
@@ -286,7 +312,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 추후 작성 예정
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
if (var2) cqlFilters.push(`mqlt_cd='${var2}'`);
if (var3) cqlFilters.push(`pbadms_emd_cd='${var3}'`);
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
@@ -304,13 +331,13 @@ const SearchModal: React.FC<SearchModalProps> = ({
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
);
// 관경(mm) 범위
if (start1 && end1) cqlFilters.push(`pdmt BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`pdmt >= ${start1}`);
else if (end1) cqlFilters.push(`pdmt <= ${end1}`);
if (start1 && end1) cqlFilters.push(`pdmt_vl BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`pdmt_vl >= ${start1}`);
else if (end1) cqlFilters.push(`pdmt_vl <= ${end1}`);
// 연장(m) 범위
if (start2 && end2) cqlFilters.push(`prlg BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`prlg >= ${start2}`);
else if (end2) cqlFilters.push(`prlg <= ${end2}`);
if (start2 && end2) cqlFilters.push(`prlg_vl BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`prlg_vl >= ${start2}`);
else if (end2) cqlFilters.push(`prlg_vl <= ${end2}`);
return cqlFilters;
};
@@ -354,8 +381,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 하수처리구역용 CQL 필터 생성
const zoneCqlFilters = () => {
const cqlFilters: string[] = [];
if (city) cqlFilters.push(`ctpv_cd='${city}'`);
if (sgg) cqlFilters.push(`sgg_cd='${sgg}'`);
if (ctpvCd !== '' && ctpvCd !== '0') cqlFilters.push(`ctpv_cd='${ctpvCd?.trim()}'`);
if (sggCd !== '' && sggCd !== '0') cqlFilters.push(`sgg_cd='${sggCd}'`);
if (var1) cqlFilters.push(`swtrmt_zone_nm ILIKE '%${var1}%'`);
if (var2) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var2}%'`);
return cqlFilters;
@@ -363,6 +390,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 하수맨홀용 CQL 필터 생성
const mhCqlFilters = () => {
const cqlFilters: string[] = [];
// 시도, 시군구
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
// // 설치년도 범위
const startDate = getDateString(
yearFilter.start,
@@ -381,15 +411,18 @@ const SearchModal: React.FC<SearchModalProps> = ({
);
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
// 구경(mm) 범위
if (start1 && end1) cqlFilters.push(`swage_mh_diam BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`swage_mh_diam >= ${start1}`);
else if (end1) cqlFilters.push(`swage_mh_diam <= ${end1}`);
if (start1 && end1) cqlFilters.push(`swage_mhL_diam_vl BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`swage_mhL_diam_vl >= ${start1}`);
else if (end1) cqlFilters.push(`swage_mhL_diam_vl <= ${end1}`);
return cqlFilters;
};
// 하수펌프장용 CQL 필터 생성
const psmtnCqlFilters = () => {
const cqlFilters: string[] = [];
// 시도, 시군구
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
@@ -413,15 +446,18 @@ const SearchModal: React.FC<SearchModalProps> = ({
else if (end1) cqlFilters.push(`daily_prcs_cpct <= ${end1}`);
// 양수능력 범위
if (start2 && end2)
cqlFilters.push(`excln_wpmp_ablt BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`excln_wpmp_ablt >= ${start2}`);
else if (end2) cqlFilters.push(`excln_wpmp_ablt <= ${end2}`);
cqlFilters.push(`excln_wpmp_ablt_vl BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`excln_wpmp_ablt_vl >= ${start2}`);
else if (end2) cqlFilters.push(`excln_wpmp_ablt_vl <= ${end2}`);
return cqlFilters;
};
// 우수토실용 CQL 필터 생성
const otflCqlFilters = () => {
const cqlFilters: string[] = [];
// 시도, 시군구
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
@@ -456,7 +492,12 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 기본정보 테이블 cellClick 핸들러
const handleBasicCellClick = (index?: number | undefined, headId?: String) => {
if (typeof index === "number") {
onFeatureSelect(tableData[index % 10]); // 10은 page size 하드 코딩한 숫자
const row = tableData[index];
const layerNm = row.lyrTypeNm;
const fid = row.fid;
const core = GisApp.Module.layer as any;
core.showSearchResultsFromGeoJSON(layerNm, fid);
onOpenChange(false); // SearchModal 닫기
}
};
@@ -473,31 +514,30 @@ const SearchModal: React.FC<SearchModalProps> = ({
try {
const RequestDTO: Record<string, string> = {
page: `${detailCurPage - 1}`,
size: '5',
bizId: tableData[index % 5].bizId,
size: `${OPERATION_TABLE_SIZE}`,
bizId: tableData[index % OPERATION_TABLE_SIZE].bizId,
};
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
console.log('운영정보 cellClick 데이터:', res);
console.log('운영정보 cellClick.data:', res.data);
console.log('운영정보 length:', res.data.length);
console.log('운영정보 cellClick 데이터1:', res);
console.log('운영정보 cellClick 데이터2:', res.data);
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
const formattedItem = formatDisplayData(item);
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item.usgCd.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
return {
...formattedItem,
rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1,
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
};
});
console.log('운영정보 cellClick mappedData:', mappedData);
console.log('운영정보 cellClick 데이터:', mappedData);
setDetailTableData(mappedData);
setDetailTableCount(res.count || 0);
@@ -517,7 +557,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
try {
const RequestDTO: Record<string, string> = {
page: `${detailCurPage - 1}`,
size: '5',
size: `${OPERATION_TABLE_SIZE}`,
bizId: String(detailBizId),
};
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
@@ -525,15 +565,17 @@ const SearchModal: React.FC<SearchModalProps> = ({
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
const formattedItem = formatDisplayData(item);
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item.usgCd.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
return {
...formattedItem,
rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1,
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
};
});
console.log('운영정보 PageNation 데이터:', mappedData);
setDetailTableData(mappedData);
setDetailTableCount(res.count || 0);
@@ -545,6 +587,420 @@ const SearchModal: React.FC<SearchModalProps> = ({
}
};
// 기본정보 Excel 다운로드 핸들러
const BasicExcelDownload = async () => {
if (tableData.length === 0) {
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
return;
}
toast.dismiss("global-confirm-toast");
confirmToast(
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
onAnalysis ?? (() => { }),
"text-xl font-medium text-gray-800"
);
async function onAnalysis() {
setIsLoading(true);
try {
const queryParams = new URLSearchParams({
lyrTypeNm: basicType,
size: '10000',
});
let cqlFilters: string[] = [];
let headerMapping: { [key: string]: string } = {};
let headerRange: string = "A1:F1";
switch (basicType) {
case 'tb_ms_swage_ppl': {
// 하수관로
cqlFilters = pplCqlFilters()
headerMapping = MsSwagePplExcelCol;
headerRange = "A1:M1";
break;
}
case 'tb_il_swage_prcs_fclt': {
// 하수처리시설
cqlFilters = facilityCqlFilters();
headerMapping = SwtrmtFcltExcelCol;
headerRange = "A1:J1";
break;
}
case 'tb_ms_swage_prcs_zone': {
// 하수처리구역
cqlFilters = zoneCqlFilters();
headerMapping = SwtrmtPrcsZoneExcelCol;
headerRange = "A1:D1";
break;
}
case 'tb_ms_swage_mhl': {
// 하수맨홀
cqlFilters = mhCqlFilters();
headerMapping = MsSwageMhlExcelCol;
headerRange = "A1:J1";
break;
}
case 'tb_ms_swage_pmstn': {
// 하수펌프장
cqlFilters = psmtnCqlFilters();
headerMapping = ExclnSewagePumpExcelCol;
headerRange = "A1:J1";
break;
}
case 'tb_ms_stofcbr': {
// 우수토실
cqlFilters = otflCqlFilters();
headerMapping = stofcbrExcelCol;
headerRange = "A1:H1";
break;
}
}
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
console.log('res.data.data', res.data.data);
// const mhlCdMap = new Map(MS_SWAGE_MHL_CODES.map(code => [code.val?.trim(), code.text]));
const mhlUsgCdMap = new Map(MS_SWAGE_MHL_USE_CODES.map(code => [code.val?.trim(), code.text]));
const pplUsgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val?.trim(), code.text]));
const ctpvMap = new Map(ctpv.map(code => [code.val?.trim(), code.text]));
const sggMap = new Map(sgg.map(code => [code.val?.trim(), code.text]));
const mappedContent = (res.data.data || []).map((item: any) => {
const formattedItem = formatDisplayData(item);
let ctpvCd = item?.ctpvCd ?? formattedItem?.ctpvCd ?? '';
let sggCd = item?.sggCd ?? formattedItem?.sggCd ?? '';
if (!ctpvCd || !sggCd) {
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
if (!sggCd && code) sggCd = code.slice(0, 5);
}
// trim 한 번만 수행
const trimmedUsgCd = item?.usgCd?.trim();
// const trimmedMqltCd = item?.mqltCd?.trim();
switch (basicType) {
case 'tb_ms_swage_ppl': {
// 하수관로
return {
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
instMngNo: formattedItem.instMngNo ?? item.instMngNo ?? '-',
ctpvNm: ctpvMap.get(ctpvCd) ?? item.ctpvNm ?? '-',
sggNm: sggMap.get(sggCd) ?? item.sggNm ?? '-',
swtrmt_zone_nm: formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '-',
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
usgCd: pplUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '-',
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '-',
tmptDpth: formattedItem.tmptDpth ?? item.tmptDpth ?? '-',
tmptMhlMngNo: formattedItem.tmptMhlMngNo ?? item.tmptMhlMngNo ?? '-',
scendDpth: formattedItem.scendDpth ?? item.scendDpth ?? '-',
scendMhlMngNo: formattedItem.scendMhlMngNo ?? item.scendMhlMngNo ?? '-',
};
}
case 'tb_il_swage_prcs_fclt': {
// 하수처리시설
return {
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-',
fcltCpct: formattedItem.fcltCpct ?? item.fcltCpct ?? '-',
rgnExpln: formattedItem.rgnExpln ?? item.rgnExpln ?? '-',
oprtngStrtYmd: formattedItem.oprtngStrtYmd ?? item.oprtngStrtYmd ?? '-',
laeNm: formattedItem.laeNm ?? item.laeNm ?? '-',
sareaNm: formattedItem.sareaNm ?? item.sareaNm ?? '-',
rvrNm: formattedItem.rvrNm ?? item.rvrNm ?? '-',
dschgWtstNm: formattedItem.dschgWtstNm ?? item.dschgWtstNm ?? '-',
swtrmtPpltnCnt: formattedItem.swtrmtPpltnCnt ?? item.swtrmtPpltnCnt ?? '-',
rprsMsrcCn: formattedItem.rprsMsrcCn ?? item.rprsMsrcCn ?? '-'
};
}
case 'tb_ms_swage_prcs_zone': {
// 하수처리구역
return {
swtrmtZoneNm: formattedItem.swtrmtZoneNm ?? item.swtrmtZoneNm ?? '-',
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-'
};
}
case 'tb_ms_swage_mhl': {
// 하수맨홀
return {
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
usgCd: mhlUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
swageMhlDiamVl: formattedItem.swageMhlDiamVl ?? item.swageMhlDiamVl ?? '-',
wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? '-',
vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? '-',
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
dpthlVl: formattedItem.dpthlVl ?? item.dpthlVl ?? '-'
};
}
case 'tb_ms_swage_pmstn': {
// 하수펌프장
return {
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
swagePmstnNm: formattedItem.swagePmstnNm ?? item.swagePmstnNm ?? '-',
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
dailyPrcsCpct: formattedItem.dailyPrcsCpct ?? item.dailyPrcsCpct ?? '-',
maxImpndCpct: formattedItem.maxImpndCpct ?? item.maxImpndCpct ?? '-',
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
wtlvVl: formattedItem.wtlvVl ?? item.wtlvVl ?? '-',
exclnWpmpAbltVl: formattedItem.exclnWpmpAbltVl ?? item.exclnWpmpAbltVl ?? '-'
};
}
case 'tb_ms_stofcbr': {
// 우수토실
return {
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
mapshtNo: formattedItem.mapshtNo ?? item.mapshtNo ?? '-',
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
worflwWallHgt: formattedItem.worflwWallHgt ?? item.worflwWallHgt ?? '-',
swageMhlMngNo: formattedItem.swageMhlMngNo ?? item.swageMhlMngNo ?? '-',
drtnAngl: formattedItem.drtnAngl ?? item.drtnAngl ?? '-'
};
}
}
});
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
const excelData = mappedContent; // 배열로 감싸서 전달
console.log('excelData', excelData);
// 파일명 생성 (분석번호 기반)
const label = BASIC_TYPES.find((type) => type.val === basicType)?.text
const fileName = `${label} 조회 결과_${todayYear}${todayMonth}${todayDate}`;
await downloadExcelWithKoreanHeaders({
data: excelData as JSON[],
fileName: fileName,
sheetNameArray: [fileName],
headerRange: headerRange,
headerMapping: headerMapping
});
setIsLoading(false);
} catch (error) {
setIsLoading(false);
console.error("Excel 다운로드 중 오류 발생:", error);
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
}
}
};
// 운영정보 Excel 다운로드 핸들러 추가
const OperationExcelDownload = async () => {
if (tableData.length === 0) {
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
return;
}
toast.dismiss("global-confirm-toast");
confirmToast(
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
onAnalysis ?? (() => { }),
"text-xl font-medium text-gray-800"
);
async function onAnalysis() {
setIsLoading(true);
try {
const RequestDTO: Record<string, string> = {
size: '10000',
};
if (var1) RequestDTO.bizInfoNm = var1;
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
// 수행기간 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
RequestDTO.fromflfmtEndYmd = startDate;
RequestDTO.toflfmtEndYmd = endDate;
// JSON.parse 사용으로 문자열 -> 배열 변환
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
const params = new URLSearchParams(RequestDTO).toString();
const res = await getData(`v1/bizInfo?${params}`);
// 헤더 매핑 정의
const headerMapping: { [key: string]: string } = {
'bizInfoNm': '사업명',
'flfmtBgngYmd': '수행시작일자',
'flfmtEndYmd': '수행종료일자',
'flfmtYr': '수행년도',
'bizTypeCd': '사업유형',
'bizAmt': '사업금액(원)',
};
const bizTyCdMap = new Map(BIZ_TY_CD.map(code => [code.lwpoCd, code.lwpoCdNm]));
const mappedContent = (res.content || []).map((item: any) => {
const formattedItem = formatDisplayData(item);
return {
bizInfoNm: formattedItem.bizInfoNm ?? item.bizInfoNm ?? '',
flfmtBgngYmd: formattedItem.flfmtBgngYmd ?? item.flfmtBgngYmd ?? '',
flfmtEndYmd: formattedItem.flfmtEndYmd ?? item.flfmtEndYmd ?? '',
flfmtYr: formattedItem.flfmtYr ?? item.flfmtYr ?? '',
bizTypeCd: bizTyCdMap.get(item.bizTypeCd) || item.bizTypeCd || formattedItem.bizTypeCd || '',
bizAmt: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.bizAmt ?? item.bizAmt),
};
});
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
const excelData = mappedContent; // 배열로 감싸서 전달
// 파일명 생성 (분석번호 기반)
const label = WORK_TYPES.find((type) => type.val === workType)?.text
const fileName = `${label} 사업 현황_${todayYear}${todayMonth}${todayDate}`;
await downloadExcelWithKoreanHeaders({
data: excelData as JSON[],
fileName: fileName,
sheetNameArray: [fileName],
headerRange: "A1:F1",
headerMapping: headerMapping
});
setIsLoading(false);
} catch (error) {
setIsLoading(false);
console.error("Excel 다운로드 중 오류 발생:", error);
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
}
}
};
// 운영정보 Excel 다운로드 핸들러 추가
const OperationResultExcelDownload = async () => {
if (detailTableData.length === 0) {
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
return;
}
toast.dismiss("global-confirm-toast");
confirmToast(
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
onAnalysis ?? (() => { }),
"text-xl font-medium text-gray-800"
);
async function onAnalysis() {
setIsLoading(true);
try {
const RequestDTO: Record<string, string> = {
size: '10000',
bizId: String(detailBizId),
};
const apiStartTime = performance.now();
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
const apiEndTime = performance.now();
console.log(`🚀 1. API 호출 시간: ${(apiEndTime - apiStartTime).toFixed(2)}ms`);
console.log('운영정보 결과 다운로드.data:', res.data);
const mappingStartTime = performance.now();
// 헤더 매핑 정의
const headerMapping: { [key: string]: string } = {
'fcltMngNo': '관리번호',
'swtrmt_zone_nm': '처리구역',
'usgCd': '용도',
'mqltCd': '재질',
'pdmtVl': '관경(mm)',
'prlgVl': '연장(m)',
'instlYmd': '설치일자',
'strc_stts_grd': '구조적 상태등급',
'oper_stts_grd': '운영적 상태등급',
};
const usgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val, code.text]));
const mqltCdMap = new Map(MS_SWAGE_PPL_CODES.map(code => [code.val, code.text]));
// 🎯 단일 반복문으로 최적화 - 각 아이템마다 필요한 필드만 직접 매핑
const mappedData = (res.data || []).map((item: any) => {
const formattedItem = formatDisplayData(item);
// trim 한 번만 수행
const trimmedUsgCd = item?.usgCd?.trim();
const trimmedMqltCd = item?.mqltCd?.trim();
// zone 값 한 번만 계산
const zone = item.swtrmtZoneNm ?? formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '';
// 직접 매핑 - 반복문 없이 한 번에 객체 생성
return {
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '',
swtrmt_zone_nm: (zone === null || zone === '') ? '-' : zone,
usgCd: usgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '',
mqltCd: mqltCdMap.get(trimmedMqltCd) || item.mqltCd || formattedItem.mqltCd || '',
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '',
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '',
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '',
strc_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.strc_stts_grd ?? item.strc_stts_grd),
oper_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.oper_stts_grd ?? item.oper_stts_grd),
};
});
const mappingEndTime = performance.now();
console.log(`🔄 2. 데이터 매핑 시간: ${(mappingEndTime - mappingStartTime).toFixed(2)}ms`);
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
const excelData = mappedData; // 배열로 감싸서 전달
console.log('excelData', excelData);
const excelStartTime = performance.now();
// 파일명 생성 (분석번호 기반)
const label = WORK_TYPES.find((type) => type.val === workType)?.text
const fileName = `${label} 결과표_${todayYear}${todayMonth}${todayDate}`;
await downloadExcelWithKoreanHeaders({
data: excelData as JSON[],
fileName: fileName,
sheetNameArray: [fileName],
headerRange: "A1:I1",
headerMapping: headerMapping
});
const excelEndTime = performance.now();
console.log(`📊 3. Excel 다운로드 시간: ${(excelEndTime - excelStartTime).toFixed(2)}ms`);
setIsLoading(false);
} catch (error) {
setIsLoading(false);
console.error("Excel 다운로드 중 오류 발생:", error);
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
}
}
};
const renderBody = () => (
<>
@@ -556,15 +1012,13 @@ const SearchModal: React.FC<SearchModalProps> = ({
label: tab.text
}))}
onValueChange={(value: string) => setActiveTab(value)}
>
</UITab>
{/* 각각의 탭 영역 */}
/>
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<BasicTab
basicType={basicType}
city={city}
sgg={sgg}
city={ctpvCd}
sgg={sggCd}
start1={start1}
start2={start2}
end1={end1}
@@ -574,9 +1028,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
yearFilter={yearFilter}
handleSearch={handleSearch}
setBasicType={setBasicType}
setCity={setCity}
setCity={setCtpvCd}
setCtpvName={setCtpvName}
setSgg={setSgg}
setSgg={setSggCd}
setSggName={setSggName}
setYearFilter={setYearFilter}
setStart1={setStart1}
@@ -607,11 +1061,10 @@ const SearchModal: React.FC<SearchModalProps> = ({
open={open}
/>
)}
{/* </UITab2> */}
{/* 📋 결과 리스트 */}
{/* 하수도정비기본계획보고서 탭 */}
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
<div className="flex-1 px-2 pb-2">
@@ -630,6 +1083,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={BasicExcelDownload}>파일 다운로드</Button>
}
/>
</div>
</div>
@@ -649,12 +1105,15 @@ const SearchModal: React.FC<SearchModalProps> = ({
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={5}
pageSize={OPERATION_TABLE_SIZE}
total={tableCount}
cellClick={handleOperationCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={OperationExcelDownload}>파일 다운로드</Button>
}
/>
</div>
</div>
@@ -672,12 +1131,15 @@ const SearchModal: React.FC<SearchModalProps> = ({
}
tableData={detailTableData}
headlist={dynamicHeadlist2}
pageSize={5}
pageSize={OPERATION_TABLE_SIZE}
total={detailTableCount}
cellClick={undefined}
onPageChange={setDetailCurPage}
resetPageNo={isResetDetailPage}
resetSelection={isResetDetailSelection}
headButton={
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={OperationResultExcelDownload}>파일 다운로드</Button>
}
/>
</div>
</div>
@@ -687,20 +1149,23 @@ const SearchModal: React.FC<SearchModalProps> = ({
);
return (
<UiModal
open={open}
onOpenChange={onOpenChange}
bodyClass={`
h-[100vh]
w-[60vw]
max-w-[60vw]
max-h-[100vh]
<>
<UiModal
open={open}
onOpenChange={onOpenChange}
bodyClass={`
h-[100dvh]
w-[60dvw]
max-w-[100dvw]
max-h-[100dvh]
overflow-hidden
z-[101]
`}
body={renderBody()}
useDirectRender={true}
/>
body={renderBody()}
useDirectRender={true}
/>
<Toaster position="top-center"></Toaster>
</>
);
};
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { getDcData } from '@/components/lib/api';
import { create } from 'zustand';
export type Folder = {
clsfSystmSn: string;
@@ -16,13 +16,14 @@ export type SelectDataType = {
val: string;
sido?: string; // 시도 코드 (선택 사항)
}
type ReportDataFile = {
export type ReportDataFile = {
no: number;
fileTitle: string;
regDt: string;
fileSn: string;
filePath: string;
}
const isYear = (value: string): boolean => {
return /^[0-9]{4}년$/.test(value);
};
@@ -107,23 +108,53 @@ export const useDcTree = (clsfSystmNm: string) => {
return data;
};
export const getDcFile = async (clsfSystmSn: string) => {
export const getDcFiles = async (clsfSystmSn: string) : Promise<ReportDataFile[]> => {
if (!clsfSystmSn) {
console.error("clsfSystmSn is required to get files.");
return [];
}
const queryString = 'clsfSystmSn=' + clsfSystmSn;
const result = await getDcData(`/api/v1/dc/file${queryString ? `?${queryString}` : ''}`);
return result;
};
export const useDcFiles = (clsfSystmNm: string) => {
const [data, setData] = useState<ReportDataFile[]>([]);
useEffect(() => {
const fetch = async () => {
const result = await getDcFiles(clsfSystmNm);
if (result) {
setData(result);
}
console.log("useDcFiles 호출");
console.log("clsfSystmNm:", clsfSystmNm, "data:", result);
};
fetch();
}, [clsfSystmNm]);
return data;
};
// 파일 이름 추가
export const addFileName = async (data: FlattenedFolder[]) => {
const fileReportData = await Promise.all(
data.map(async (item) => {
const filenameArr: ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const f = filenameArr[0];
const result = { ...item, fileName: f?.fileTitle, regDate: f?.regDt, fileSn: f?.fileSn, filePath: f?.filePath };
const fileArr: ReportDataFile[] = await getDcFiles(String(item.clsfSystmSn));
let result:FlattenedFolder;
if (fileArr.length > 0) {
const f = fileArr[0];
const fCount = fileArr.length;
result = { ...item, fileName: f?.fileTitle+" 외 "+fCount+"건", regDate: f?.regDt, fileSn: f?.fileSn, filePath: f?.filePath };
} else {
result = { ...item, fileName: "", regDate: "", fileSn: "", filePath: "" };
}
return result;
})
);
return fileReportData;
};
export const getDcFileprcs = async (fileSn: string) => {
const queryString = 'fileSn=' + fileSn;
const result = await getDcData(`/api/v1/dc/fileprcs${queryString ? `?${queryString}` : ''}`);
@@ -157,3 +188,11 @@ export const getFileDownload = async (fileSn: string, fileName: string, filePath
fileDownload(blobData, fileName);
}
interface ModalStore {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
}
export const useReportFileModalStore = create<ModalStore>((set) => ({
isOpen: false,
setIsOpen: (open: boolean) => set({ isOpen: open }),
}));
@@ -3,32 +3,53 @@
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button } from '@common/components';
import React from 'react';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
interface StofcbrProps {
city: string;
sgg: string;
yearFilter: { start: string; end: string };
setCity: (value: string) => void;
setSgg: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const Stofcbr: React.FC<StofcbrProps> = ({
city,
sgg,
yearFilter,
setCity,
setSgg,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-3">
{/* 설치년도 */}
<div className="flex items-center mb-2">
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
{/* 시도, 시군구 */}
<CtpvSggPrcsFcltSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId: string) => {
setCity(sidoId);
setSgg("0");
}}
onSigunguChange={setSgg}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
{/* 설치년도 */}
<div className="flex items-center mb-2">
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
</div>
@@ -5,16 +5,21 @@ import { Button, Input, Label } from '@common/components';
import React from 'react';
import { MS_SWAGE_MHL_USE_CODES } from '../components/common/table';
import { SelectBox } from '@common/business_components/ui';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
interface SwageMhlProps {
var1: string;
start1: string;
end1: string;
city: string;
sgg: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setStart1: (value: string) => void;
setEnd1: (value: string) => void;
setCity: (value: string) => void;
setSgg: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
@@ -23,10 +28,14 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
var1,
start1,
end1,
city,
sgg,
yearFilter,
setVar1,
setStart1,
setEnd1,
setCity,
setSgg,
setYearFilter,
handleSearch,
}) => {
@@ -34,6 +43,15 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
return (
<div className="mb-3">
<div className="mb-2 flex items-center">
<CtpvSggPrcsFcltSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId: string) => {
setCity(sidoId);
setSgg("0");
}}
onSigunguChange={setSgg}
/>
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
@@ -51,10 +69,10 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
{/* 용도 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">용도</Label>
<SelectBox
className="w-60 mr-8"
className="w-48 mr-8"
selectClass="rounded-lg bg-white text-xl"
label=""
selectArray={MS_SWAGE_MHL_USE_CODES}
selectArray={[{ val: "0", text: "전체" }, ...MS_SWAGE_MHL_USE_CODES]}
value={var1}
onSelectValue={(val) => {
setVar1(String(val));
@@ -3,17 +3,22 @@
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
interface SwagePmstnProps {
start1: string;
start2: string;
end1: string;
end2: string;
city: string;
sgg: string;
yearFilter: { start: string; end: string };
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setCity: (value: string) => void;
setSgg: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
@@ -23,11 +28,15 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
start2,
end1,
end2,
city,
sgg,
yearFilter,
setStart1,
setStart2,
setEnd1,
setEnd2,
setCity,
setSgg,
setYearFilter,
handleSearch,
}) => {
@@ -35,6 +44,16 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
return (
<div className="mb-3">
<div className="flex items-center mb-2">
{/* 시도, 시군구 */}
<CtpvSggPrcsFcltSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId: string) => {
setCity(sidoId);
setSgg("0");
}}
onSigunguChange={setSgg}
/>
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
@@ -43,7 +62,7 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
startLabel="설치년도"
endLabel=""
/>
{/* 일일처리용량 - 오수맨홀 */}
{/* 일일처리용량 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">일일처리용량(㎥)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
@@ -78,8 +97,8 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
}
}}
/>
{/* 양수능력 - 우수맨홀 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">양수능력(m²/d)</Label>
{/* 양수능력 */}
{/* <Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">양수능력(m²/d)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -112,7 +131,7 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
handleSearch();
}
}}
/>
/> */}
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
@@ -5,6 +5,7 @@ import { SelectBox } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import React from 'react';
import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
interface SwagePplProps {
var1: string;
@@ -13,6 +14,8 @@ interface SwagePplProps {
start2: string;
end1: string;
end2: string;
city: string;
sgg: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setVar2: (value: string) => void;
@@ -20,6 +23,8 @@ interface SwagePplProps {
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setCity: (value: string) => void;
setSgg: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
@@ -31,6 +36,8 @@ const SwagePpl: React.FC<SwagePplProps> = ({
start2,
end1,
end2,
city,
sgg,
yearFilter,
setVar1,
setVar2,
@@ -38,6 +45,8 @@ const SwagePpl: React.FC<SwagePplProps> = ({
setStart2,
setEnd1,
setEnd2,
setCity,
setSgg,
setYearFilter,
handleSearch,
}) => {
@@ -45,6 +54,15 @@ const SwagePpl: React.FC<SwagePplProps> = ({
return (
<div className="mb-6">
<div className="mb-2 flex items-center">
<CtpvSggPrcsFcltSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId: string) => {
setCity(sidoId);
setSgg("0");
}}
onSigunguChange={setSgg}
/>
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
@@ -62,10 +80,10 @@ const SwagePpl: React.FC<SwagePplProps> = ({
{/* 용도 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">용도</Label>
<SelectBox
className="w-40 mr-8"
className="w-32 mr-8"
selectClass="rounded-lg bg-white text-xl"
label=""
selectArray={MS_SWAGE_PPL_USE_CODES}
selectArray={[{val: "0", text: "전체"}, ...MS_SWAGE_PPL_USE_CODES]}
value={var1}
onSelectValue={(val) => {
setVar1(String(val));
@@ -73,7 +91,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
selectContentClass="z-[101]"
/>
{/* 재질 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">재질</Label>
{/* <Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">재질</Label>
<SelectBox
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
@@ -84,7 +102,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
setVar2(String(val));
}}
selectContentClass="z-[101]"
/>
/> */}
{/* 관경 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">관경(mm)</Label>
<Input
@@ -121,7 +139,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
}}
/>
{/* 연장 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">연장(m)</Label>
{/* <Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">연장(m)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -154,7 +172,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
handleSearch();
}
}}
/>
/> */}
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
@@ -12,17 +12,17 @@ interface SwagePrcsFcltProps {
start2: string;
end1: string;
end2: string;
city: number;
sgg: number;
city: string;
sgg: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setCity: (value: number) => void;
setCity: (value: string) => void;
setCtpvName: (name: string) => void;
setSgg: (value: number) => void;
setSgg: (value: string) => void;
setSggName: (name: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
@@ -52,7 +52,7 @@ const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
sigungu={sgg}
onSidoChange={(sidoId) => {
setCity(sidoId);
setSgg(0);
setSgg("0");
}}
onSigunguChange={setSgg}
setCtpvName={setCtpvName}
@@ -7,12 +7,12 @@ import React from 'react';
interface swagePrcsZoneProps {
var1: string;
var2: string;
city: number;
sgg: number;
city: string;
sgg: string;
setVar1: (value: string) => void;
setVar2: (value: string) => void;
setCity: (value: number) => void;
setSgg: (value: number) => void;
setCity: (value: string) => void;
setSgg: (value: string) => void;
handleSearch: () => void;
}
@@ -34,9 +34,9 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
<CtpvSggPrcsFcltSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId: number) => {
onSidoChange={(sidoId: string) => {
setCity(sidoId);
setSgg(0);
setSgg("0");
}}
onSigunguChange={setSgg}
/>
@@ -39,18 +39,18 @@ type BaseLayout = {
firstDivBtn?: boolean
selectBox?: SelectBox
showDatePicker?: boolean;
ctpvCd: number;
sggCd: number;
ctpvCd: string;
sggCd: string;
sggName?: string;
sigungu?: ApiSelectOption
selectedSwagePrcsFclt?: string | number;
onSwagePrcsFcltChange?: (value: string | number) => void;
selectedSwagePrcsFclt?: string;
onSwagePrcsFcltChange?: (value: string) => void;
aplcnYmFrom?: string
setAplcnYmFrom?: (aplcnYmFrom: string) => void;
aplcnYmTo?: string
setAplcnYmTo?: (aplcnYmTo: string) => void;
setCtpvCd: (ctpv: number) => void;
setSggCd: (sgg: number) => void;
setCtpvCd: (ctpv: string) => void;
setSggCd: (sgg: string) => void;
setSggName?: (sggName: string) => void;
setSwtrmtFcltNm?: (swtrmtFcltNm: string) => void;
setIsLoading?: (isLoading: boolean) => void;
@@ -178,9 +178,9 @@ const BaseLayout = ({
sido={ctpvCd}
sigungu={sggCd}
sggName={sggName}
onSidoChange={(sidoId: number) => {
onSidoChange={(sidoId: string) => {
setCtpvCd(sidoId);
setSggCd(0);
setSggCd('0');
}}
onSigunguChange={setSggCd}
setSggName={setSggName}
@@ -9,7 +9,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { excelToFlowRateData, excelToMatchingResultData, excelToTimePatternData } from '@/components/lib/utils'
import { excelToFlowRateData, excelToMatchingResultData, excelToTimePatternData, excelToRcptrInfoData } from '@/components/lib/utils'
import BaseLayout from '../BaseLayout'
import { validateMultipleFiles, FILE_EXTENSIONS, type FileValidationConfig } from '../../fileValidation';
import { validateBasicSelectionsWithAlert } from '../../selectionValidation';
@@ -42,19 +42,14 @@ interface UploadedFileInfo {
// 초기 파일 정보 상태
const initialFileInfo: UploadedFileInfo = { file: null, atflCd: null, atflId: null };
interface ApiSelectOption {
text: string;
val: string;
}
const IrSetting = () => {
const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값
const [input2, setInput2] = useState('');
const [select1, setSelect1] = useState<string | number>('0'); // 하수처리장코드
const [select1, setSelect1] = useState<string>('0'); // 하수처리장코드
const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태
const [isLoadingResult, setIsLoadingResult] = useState<boolean>(false); // 로딩 상태
const [ctpvCd, setCtpvCd] = useState<number>(0); // 시도 코드 상태
const [sggCd, setSggCd] = useState<number>(0); // 시군구 코드 상태
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
const [swtrmtFcltNm, setSwtrmtFcltNm] = useState<string>(''); // 하수처리시설명 상태
@@ -116,7 +111,7 @@ const IrSetting = () => {
setSelectedDate(`${year}${month}`);
setInput1(''); // 입력 필드 초기화
setInput2(''); // 입력 필드 초기화
setSelect1(0);
setSelect1('0');
setSwtrmtFcltNm('');
setFormResetKey(prevKey => prevKey + 1); // FileUploadForm 재마운트를 위해 key 변경
};
@@ -177,12 +172,14 @@ const IrSetting = () => {
const file1 = uploadedFilesData[0]; // 오수관망도
const file2 = uploadedFilesData[1]; // 수용가-맨홀 매칭결과
const file3 = uploadedFilesData[2]; // 오수량 시간패턴
const file4 = uploadedFilesData[3]; // 유량자료
const file4 = uploadedFilesData[3]; // 유량자료
const file5 = uploadedFilesData[4]; // 수용가 상수사용량
console.log("오수관망도 정보:", file1?.file);
console.log("수용가-맨홀 매칭결과 정보:", file2);
console.log("오수량 시간패턴 정보:", file3);
console.log("유량자료 정보:", file4);
console.log("수용가 상수사용량 정보:", file5);
// 모든 필수 파일이 선택되었는지 확인 (UploadedFileInfo 객체와 그 안의 file 객체 모두 확인)
// 유량자료는 선택값
@@ -219,6 +216,14 @@ const IrSetting = () => {
fileDescription: '유량자료'
});
}
// 수용가 상수사용량 파일이 있는 경우 검증 목록에 추가
if (file5?.file) {
validationConfigs.push({
file: file5.file,
allowedExtensions: FILE_EXTENSIONS.EXCEL,
fileDescription: '수용가 상수사용량'
});
}
// 파일 확장자 검증 실행
const validationResult = validateMultipleFiles(validationConfigs);
@@ -247,18 +252,22 @@ const IrSetting = () => {
type MatchingResult = { anlsSn: number; mhlMngNo: string; rcptrNo: string; };
type TimePattern = { hrId: number; rt?: number | null | undefined; };
type FlowRate = { pplMngNo: string; mtrngDt: string; oilq?: number | null | undefined; };
type rcptrInfo = { rcptrNo: string; useYm: string; usqty?: number | null | undefined; };
const filePickers: {
file: UploadedFileInfo;
parser: (excelData: any) => MatchingResult[] | TimePattern[] | FlowRate[];
parser: (excelData: any) => MatchingResult[] | TimePattern[] | FlowRate[] | rcptrInfo[];
}[] = [
{ file: file2, parser: excelToMatchingResultData },
{ file: file3, parser: excelToTimePatternData }
];
if (file4?.file) {
if (file4?.file) { // 유량자료 파일이 있는 경우
filePickers.push({ file: file4, parser: excelToFlowRateData });
}
if (file5?.file) { // 수용가 상수사용량 파일이 있는 경우
filePickers.push({ file: file5, parser: excelToRcptrInfoData });
}
try {
const parsedResults = await Promise.all(
@@ -295,11 +304,14 @@ const IrSetting = () => {
const flowRateData = file4?.file
? parsedResults.find(r => r && r.fileName === file4.file?.name)?.parsedData
: null;
const rcptrInfoData = file5?.file
? parsedResults.find(r => r && r.fileName === file5.file?.name)?.parsedData
: null;
// 새로운 JSON 데이터 생성
const combinedAnalysisData = {
ctpvCd: (ctpvCd ? String(ctpvCd) : null),
sggCd: (sggCd ? String(sggCd) : null), // 시군구코드 (선택값)
ctpvCd: ctpvCd !== '0' ? String(ctpvCd).trim() : null,
sggCd: sggCd !== '0' ? String(sggCd) : null, // 시군구코드 (선택값)
swtrmtFcltNm: swtrmtFcltNm ?? null,
aplcnYm: selectedDate, // 적용연월
drtwSwtcRt: parseFloat(input1) || null, // 오수전환율 (숫자로 변환)
@@ -315,6 +327,7 @@ const IrSetting = () => {
tbSnRcptrMhlMpng: matchingResultData, // 수용가-맨홀 매칭결과
tbSnHrPttn: timePatternData, // 오수량 시간패턴
tbSnOilqData: flowRateData, // 유량자료 (없을 수 있음)
tbSnRcptrInfo: rcptrInfoData, // 수용가 상수사용량 (없을 수 있음)
};
console.log("통합 분석 데이터 (JSON):", combinedAnalysisData);
@@ -329,7 +342,9 @@ const IrSetting = () => {
return;
}
}
// const handleAnalysisClick = () => {
// }
//const rcptrInfoShow = true;
return (
<>
<LoadingOverlay isLoading={isLoadingResult} />
@@ -393,6 +408,15 @@ const IrSetting = () => {
startYear={1900} // 시작 연도 설정
/>
</FormSection>
<FormSection name='rcptrInfo' form={form} titleNm='▷ 수용가 상수사용량'>
<FileUploadForm
key={`file-upload-4-${formResetKey}`} // 폼 초기화를 위한 key
onFileSelect={(file, cd, id) => handleFileSelection(4, file, cd, id)}
showButton={false}
showPreview={true}
accept={".xls, .xlsx, .xlsm, .xltx"}
fileIdx={4} />
</FormSection>
<FormSection name='rtkSource' form={form} titleNm='▷ 오수전환율'>
<Input
value={input1}
@@ -95,11 +95,6 @@ interface UploadedFileInfo {
// 초기 파일 정보 상태
const initialFileInfo: UploadedFileInfo = { file: null, atflCd: null, atflId: null };
interface ApiSelectOption {
text: string;
val: string;
}
export default function RTKForm() {
const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태
const [isLoadingResult, setIsLoadingResult] = useState<boolean>(false); // 로딩 상태
@@ -112,9 +107,9 @@ export default function RTKForm() {
initialFileInfo, // 2: 강우자료
]);
const [select1, setSelect1] = useState<string | number>('0'); // 하수처리장 (swtrmtFcltCd)
const [ctpvCd, setCtpvCd] = useState<number>(0); // 시도 코드 상태
const [sggCd, setSggCd] = useState<number>(0); // 시군구 코드 상태
const [select1, setSelect1] = useState<string>('0'); // 하수처리장 (swtrmtFcltCd)
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
const [swtrmtFcltNm, setSwtrmtFcltNm] = useState<string>(''); // 하수처리시설명 상태
@@ -290,8 +285,8 @@ export default function RTKForm() {
// 새로운 JSON 데이터 생성
const combinedAnalysisData = {
aplcnYm: formData.date, // 적용연월 (YYYYMM 형식)
ctpvCd: ctpvCd ? String(ctpvCd) : null, // 시도코드 (선택값)
sggCd: sggCd ? String(sggCd) : null, // 시군구코드 (선택값)
ctpvCd: ctpvCd !== '0' ? String(ctpvCd).trim() : null, // 시도코드 (선택값)
sggCd: sggCd !== '0' ? String(sggCd) : null, // 시군구코드 (선택값)
swtrmtFcltNm: swtrmtFcltNm ?? null,
atflCd: file1?.atflCd, // 첨부파일CD (오수관망도)
atflId: file1?.atflId, // 첨부파일ID (오수관망도)
@@ -357,10 +352,6 @@ export default function RTKForm() {
name: "initialDepths"
})
const onSubmit = (data: z.infer<typeof formSchema>) => {
console.log("✅ 제출 데이터:", data)
}
// 단위도 계수 테이블 설정 (EditableTableHeadItem 타입 사용 및 id 수정)
const unitFactorHeadlist: EditableTableHeadItem<FormSchemaType['unitFactors'][number]>[] = [
{ id: 'response', title: 'Response', editable: false, width: '150px' }, // width 속성 추가
@@ -377,11 +368,6 @@ export default function RTKForm() {
{ id: 'Do', title: 'Do', editable: true, inputProps: { type: 'text' } }
];
// 테이블 페이지 변경 핸들러
const handlePageChange = (page: number) => {
console.log('Page changed:', page)
}
return (
<>
<LoadingOverlay isLoading={isLoadingResult} />
@@ -77,8 +77,8 @@ const Result = () => {
const [resetSelection, setResetSelection] = useState<boolean>(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [curPage, setCurPage] = useState(1); // 현재 페이지
const [ctpvCd, setCtpvCd] = useState<number>(0); // 시도 코드 상태
const [sggCd, setSggCd] = useState<number>(0); // 시군구 코드 상태
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
const {ctpv, sgg} = useStore();
@@ -112,8 +112,8 @@ const Result = () => {
const inftwtAnlsSearchDto = {
aplcnYmFrom: formValues.aplcnYmFrom?.trim() ? formValues.aplcnYmFrom : null,
aplcnYmTo: formValues.aplcnYmTo?.trim() ? formValues.aplcnYmTo : null,
ctpvCd: ctpvCd || null,
sggCd: sggCd || null,
ctpvCd: ctpvCd !== '0' ? ctpvCd.trim() : null,
sggCd: sggCd !== '0' ? sggCd : null,
swtrmtFcltNm: formValues.swtrmtFcltNm?.trim() ? formValues.swtrmtFcltNm : null,
auth: AUTH,
};
@@ -140,15 +140,15 @@ const Result = () => {
const dataWithRowNumber = (data.content || []).map((item: any, index: number) => {
// 🎯 먼저 각 아이템을 포맷팅
const formattedItem = formatDisplayData(item);
const ctpvOne = ctpv.find(code => code.id === item.ctpvCd);
const sggOne = sgg.find(code => code.id === item.sggCd);
const ctpvOne = ctpv.find(code => code.val.trim() === item?.ctpvCd?.trim());
const sggOne = sgg.find(code => code.val === item.sggCd);
// 추가 처리 및 일련번호 추가
return {
...formattedItem,
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn, // scsYn이 null이면 'N'으로 변경
ctpvNm: ctpvOne ? ctpvOne.name : item.ctpvCd,
sggNm: sggOne ? sggOne.name : item.sggCd,
ctpvNm: ctpvOne ? ctpvOne.text.trim() : item?.ctpvCd?.trim(),
sggNm: sggOne ? sggOne.text : item.sggCd,
};
})
.filter((item: any) => item.scsYn === 'Y');
@@ -74,8 +74,8 @@ const Result = () => {
const [resetSelection, setResetSelection] = useState<boolean>(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [curPage, setCurPage] = useState(1); // 현재 페이지
const [ctpvCd, setCtpvCd] = useState<number>(0); // 시도 코드 상태
const [sggCd, setSggCd] = useState<number>(0); // 시군구 코드 상태
const [ctpvCd, setCtpvCd] = useState<string>('0'); // 시도 코드 상태
const [sggCd, setSggCd] = useState<string>('0'); // 시군구 코드 상태
const [sggName, setSggName] = useState<string>(''); // 시군구 이름 상태
const {ctpv, sgg} = useStore();
@@ -106,8 +106,8 @@ const Result = () => {
let inftwtAnlsSearchDto = {
"aplcnYmFrom": formValues.aplcnYmFrom && formValues.aplcnYmFrom !== '' ? formValues.aplcnYmFrom : null,
"aplcnYmTo": formValues.aplcnYmTo && formValues.aplcnYmTo !== '' ? formValues.aplcnYmTo : null,
"ctpvCd": ctpvCd === 0 ? null : ctpvCd,
"sggCd": sggCd === 0 ? null : sggCd,
"ctpvCd": ctpvCd === '0' ? null : ctpvCd.trim(),
"sggCd": sggCd === '0' ? null : sggCd,
"swtrmtFcltNm": formValues.swtrmtFcltNm?.trim() ? formValues.swtrmtFcltNm : null,
"auth": AUTH,
};
@@ -135,15 +135,15 @@ const Result = () => {
const dataWithRowNumber = (data.content || []).map((item: any, index: number) => {
// 🎯 먼저 각 아이템을 포맷팅
const formattedItem = formatDisplayData(item);
const ctpvOne = ctpv.find(code => code.id === item.ctpvCd);
const sggOne = sgg.find(code => code.id === item.sggCd);
const ctpvOne = ctpv.find(code => code.val.trim() === item?.ctpvCd?.trim());
const sggOne = sgg.find(code => code.val === item.sggCd);
// 추가 처리 및 일련번호 추가
return {
...formattedItem,
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn, // scsYn이 null이면 'N'으로 변경
ctpvNm: ctpvOne ? ctpvOne.name : item.ctpvCd,
sggNm: sggOne ? sggOne.name : item.sggCd,
ctpvNm: ctpvOne ? ctpvOne.text : item.ctpvCd,
sggNm: sggOne ? sggOne.text : item.sggCd,
};
})
.filter((item: any) => item.scsYn === 'Y');
+3 -2
View File
@@ -20,10 +20,11 @@ export default function WithBaseLayout({
const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo);
const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore();
const { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore();
useEffect(() => {
fetchCtpvSggData();
fetchCtpv();
fetchSgg();
fetchBIZ_SE_CD();
fetchBIZ_TY_CD();
}, []);
@@ -157,6 +157,25 @@ export const excelToFlowRateData = (excelData: any) => {
return flowRateData;
};
// 수용가 물사용량
export const rcptrInfoZod = z.object({
rcptrNo: z.string(), // 수용가번호
useYm: z.string(), // 사용연월
usqty: z.number().nullish(), // 사용량(㎥)
});
export type rcptrInfoZodType = z.infer<typeof rcptrInfoZod>;
export const excelToRcptrInfoData = (excelData: any) => {
const flowRateData: rcptrInfoZodType[] = excelData.map((item: any) => {
return {
rcptrNo: String(item["수용가번호"]),
useYm: String(item["사용연월"]),
usqty: Number(item["사용량(㎥)"]),
};
}).filter((el: any) => el !== undefined);
return flowRateData;
};
// 강우자료 (수정 필요)
export const rainZod = z.object({
@@ -72,7 +72,7 @@ export function YearRangeSelectBox({
(maxYear - i).toString()
).filter(y => !end || parseInt(y) <= parseInt(end));
return [
{ val: "0", text: "년" },
{ val: "0", text: "전체" },
...years.map(y => ({ val: y, text: y })),
];
};
@@ -82,7 +82,7 @@ export function YearRangeSelectBox({
(maxYear - i).toString()
).filter(y => !start || parseInt(y) >= parseInt(start));
return [
{ val: "9999", text: "년" },
{ val: "9999", text: "전체" },
...years.map(y => ({ val: y, text: y })),
];
};
@@ -1,4 +1,4 @@
import React, { useState, useMemo, useEffect } from "react";
import React, { useState, useEffect } from "react";
import { SelectBox } from '@common/business_components/ui'
import { Label } from '@common/components';
import useStore from '../../store/useStore';
@@ -10,16 +10,16 @@ interface ApiSelectOption {
val: string;
}
interface CtpvSggPrcsFcltSelectBoxProps {
sido: number;
sigungu: number;
sido: string;
sigungu: string;
sggName?: string;
onSidoChange: (id: number) => void;
onSigunguChange: (id: number) => void;
onSidoChange: (id: string) => void;
onSigunguChange: (id: string) => void;
setCtpvName?: (name: string) => void;
setSggName?: (name: string) => void;
className?: string;
selectedSwagePrcsFclt?: string | number;
onSwagePrcsFcltChange?: (value: string | number) => void;
selectedSwagePrcsFclt?: string;
onSwagePrcsFcltChange?: (value: string) => void;
setSwtrmtFcltNm?: (name: string) => void;
setIsLoading?: (isLoading: boolean) => void;
}
@@ -43,11 +43,13 @@ export function CtpvSggPrcsFcltSelectBox({
const [prcsFcltOptions, setPrcsFcltOptions] = useState<ApiSelectOption[]>([]);
const { ctpv, sgg } = useStore();
const sidoStr = String(sido ?? '');
const sidoPrefix = sidoStr.slice(0, 2);
useEffect(() => {
(async () => {
onSidoChange(0);
onSigunguChange(0);
onSidoChange("0");
onSigunguChange("0");
if (setCtpvName && setSggName) {
setCtpvName("");
setSggName("");
@@ -109,18 +111,14 @@ export function CtpvSggPrcsFcltSelectBox({
<div className={`flex items-center justify-center ${className} mr-8`}>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시도</Label>
<SelectBox
className="w-60 mr-8"
className="w-48 mr-8"
selectClass="rounded-lg bg-white"
label=""
selectArray={
[defaultOption,
...ctpv.map(opt => ({ val: opt.id, text: opt.name }))
]
}
selectArray={[defaultOption, ...ctpv]}
value={sido}
onSelectValue={val => {
onSidoChange(Number(val));
if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || "");
onSidoChange(String(val));
if (setCtpvName) setCtpvName(ctpv.find(opt => String(opt.val) === String(val))?.text || "");
if (setSwtrmtFcltNm) setSwtrmtFcltNm("");
}}
selectContentClass="z-[101]"
@@ -130,17 +128,11 @@ export function CtpvSggPrcsFcltSelectBox({
className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label=""
selectArray={
[defaultOption,
...sgg
.filter(opt => String(opt.id).slice(0, 2) === String(sido))
.map(opt => ({ val: opt.id, text: opt.name }))
]
}
selectArray={[defaultOption, ...sgg.filter(opt => opt.val.startsWith(sidoPrefix))]}
value={sigungu}
onSelectValue={val => {
onSigunguChange(Number(val))
if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || "");
onSigunguChange(String(val))
if (setSggName) setSggName(sgg.find(opt => String(opt.val) === String(val))?.text || "");
if (setSwtrmtFcltNm) setSwtrmtFcltNm("")
}}
selectContentClass="z-[101]"
@@ -155,7 +147,7 @@ export function CtpvSggPrcsFcltSelectBox({
selectArray={[defaultOption, ...prcsFcltOptions]}
value={selectedSwagePrcsFclt}
onSelectValue={(val) => {
onSwagePrcsFcltChange?.(val)
onSwagePrcsFcltChange?.(String(val))
if (setSwtrmtFcltNm) setSwtrmtFcltNm(prcsFcltOptions.find(opt => String(opt.val) === String(val))?.text || "")
}}
selectContentClass="z-[101]"
+123 -19
View File
@@ -1,6 +1,8 @@
import UiPageNations from "@common/business_components/ui/table/uiPageNations";
import { Table, TableBody, TableCell, TableRow, Button } from "@common/components";
import { useEffect, useState } from "react";
import { confirmToast, showConfirmToast } from '@/components/ui/toast'
import { toast, Toaster } from "react-hot-toast";
type UiTableProps = {
headName: React.ReactNode | undefined;
@@ -38,6 +40,9 @@ type UiHeadProps = {
align?: string;
type?: string;
options?: string[];
placeholder?: string;
isNumber?: boolean;
length?: number;
};
export function VerticalTable({
@@ -62,6 +67,8 @@ export function VerticalTable({
}: UiTableProps) {
const [cur, setCur] = useState<number>(1);
const [formData, setFormData] = useState<{ [key: string]: string | number | boolean }>({});
const [errors, setErrors] = useState<{ [key: string]: string }>({});
useEffect(() => {
if (resetPageNo) {
setCur(1);
@@ -71,32 +78,44 @@ export function VerticalTable({
useEffect(() => {
if (tableData.length > 0 && tableData[0]) {
// 깊은 복사를 통해 새로운 객체 생성
const newData = JSON.parse(JSON.stringify(tableData[0]));
setFormData(newData);
console.log("Form data initialized:", newData); // 디버깅용
setErrors({});
}
}, [tableData]);
const handleInputChange = (id: string, value: string | number | boolean) => {
console.log(`Input change: ${id} = ${value}`); // 디버깅용
const newFormData = {
...formData,
[id]: value,
};
console.log("New form data:", newFormData); // 디버깅용
setFormData(newFormData);
// 폼 데이터가 변경될 때마다 부모에게 알림
if (errors[id]) {
setErrors(prev => {
const newErrors = { ...prev };
delete newErrors[id];
return newErrors;
});
}
if (onFormDataChange) {
onFormDataChange(newFormData);
}
};
const handlePageChange = (page: number) => {
setCur(page);
onPageChange(page);
};
const showError = (fieldId: string, message: string) => {
setErrors(prev => ({
...prev,
[fieldId]: message
}));
};
return (
<>
{headName ? (
@@ -141,13 +160,55 @@ export function VerticalTable({
))}
</select>
) : head.type === "input" ? (
<input
id={head.id}
type="text"
value={String(formData[head.id] ?? "")}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
/>
<div className="w-full">
<input
id={head.id}
type="text"
value={String(formData[head.id] ?? "")}
onChange={(e) => {
if (head.isNumber) {
const newValue = e.target.value;
if (newValue === "") {
handleInputChange(head.id, newValue);
return;
}
const isValidNumber = /^[0-9]+$/.test(newValue);
if (!isValidNumber) {
showError(head.id, `${head.title}는 숫자만 입력 가능합니다.`);
return;
}
if (head.length && newValue.length > head.length) {
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
return;
}
const numericValue = parseInt(newValue);
if (isNaN(numericValue) || numericValue < 0) return;
handleInputChange(head.id, numericValue);
} else {
const newValue = e.target.value;
if (head.length && newValue.length > head.length) {
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
return;
}
handleInputChange(head.id, e.target.value);
}
}}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
placeholder={head.placeholder}
/>
{errors[head.id] && (
<div className="text-red-500 font-bold text-xl mt-1 text-left">
{errors[head.id]}
</div>
)}
</div>
) : (
<span>{formData[head.id] ?? "-"}</span>
)
@@ -188,13 +249,55 @@ export function VerticalTable({
))}
</select>
) : head.type === "input" ? (
<input
id={head.id}
type="text"
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
/>
<div className="w-full">
<input
id={head.id}
type={head.isNumber ? "number" : "text"}
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
onChange={(e) => {
if (head.isNumber) {
const newValue = e.target.value;
if (newValue === "") {
handleInputChange(head.id, newValue);
return;
}
const isValidNumber = /^[0-9]+$/.test(newValue);
if (!isValidNumber) {
showError(head.id, `${head.title}는 숫자만 입력 가능합니다.`);
return;
}
if (head.length && newValue.length > head.length) {
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
return;
}
const numericValue = parseInt(newValue);
if (isNaN(numericValue) || numericValue < 0) return;
handleInputChange(head.id, numericValue);
} else {
const newValue = e.target.value;
if (head.length && newValue.length > head.length) {
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
return;
}
handleInputChange(head.id, e.target.value);
}
}}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
placeholder={head.placeholder}
/>
{errors[head.id] && (
<div className="text-red-500 font-bold text-xl mt-1 text-left">
{errors[head.id]}
</div>
)}
</div>
) : (
<span>{formData[head.id] ?? "-"}</span>
)
@@ -216,6 +319,7 @@ export function VerticalTable({
/>
)}
</div>
<Toaster position="top-center"></Toaster>
</>
);
}
+65 -23
View File
@@ -1,8 +1,6 @@
import { getCmsData } from "@/components/lib/api";
export interface Option { id: number, name: string }
export type BIZ_CD_TYPE = {
lwpoCd: string,
upCd: string,
@@ -11,28 +9,69 @@ export type BIZ_CD_TYPE = {
prntLwpoCd: null
};
export const fetchCtpvSggData = async (set: (state: any) => void) => {
try {
const ctpvData = await getCmsData('/api/v1/code/cache/ADSTDSTRCD/Y');
const ctpvList: Option[] = ctpvData
.filter((item: any) => typeof item.lwpoCd === 'string' && item.lwpoCd.length === 2)
.map((feature: any) => ({
id: feature.lwpoCd,
name: feature.lwpoCdNm
}));
export const fetchCtpv = async (set: (state: any) => void) => {
const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
const res = await fetch(url).then(res => res.json());
const sggList: Option[] = ctpvData
.filter((item: any) => typeof item.lwpoCd === 'string' && item.lwpoCd.length !== 2)
.map((item: any) => ({
id: item.lwpoCd,
name: item.lwpoCdNm
}));
const list = res.features
.map((f: any) => ({
text: f.properties.mctpv_korn_nm,
val: f.properties.mctpv_cd,
}))
.sort((a:any, b:any) => {
// 커스텀 순서 정의
const customOrder = [
"서울특별시",
"부산광역시",
"대구광역시",
"인천광역시",
"광주광역시",
"대전광역시",
"울산광역시",
"세종특별자치시",
"경기도",
"강원특별자치도", // 경기도 다음에 배치
"충청북도",
"충청남도",
"전북특별자치도", // 충청남도 다음에 배치
"전라남도",
"경상북도",
"경상남도",
"제주특별자치도"
];
set({ ctpv: ctpvList, sgg: sggList });
} catch (e: any) {
// alert("시도, 시군구 데이터 로드 실패: " + e.message);
console.error("CTPV 데이터 로드 실패:", e);
}
const indexA = customOrder.indexOf(a.text);
const indexB = customOrder.indexOf(b.text);
// 둘 다 커스텀 순서에 있으면 해당 순서로
if (indexA !== -1 && indexB !== -1) {
return indexA - indexB;
}
// 하나만 커스텀 순서에 있으면 그것을 앞으로
if (indexA !== -1) return -1;
if (indexB !== -1) return 1;
// 둘 다 커스텀 순서에 없으면 기본 알파벳 순서
return a.text.localeCompare(b.text, 'ko');
});
console.log('시도 데이터', list);
set({ ctpv: list });
};
export const fetchSgg = async (set: (state: any) => void) => {
const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`;
const res = await fetch(url).then(res => res.json());
const list = res.features
.map((f: any) => ({
text: f.properties.sgg_korn_nm,
val: f.properties.sgg_cd,
}))
.sort((a:any, b:any) => a.text.localeCompare(b.text, 'ko'));
set({ sgg: list });
};
export const fetchBIZ_SE_CD = async (set: (state: any) => void) => {
@@ -48,7 +87,10 @@ export const fetchBIZ_SE_CD = async (set: (state: any) => void) => {
export const fetchBIZ_TY_CD = async (set: (state: any) => void) => {
try {
const res = await getCmsData(`/api/v1/code/cache/BIZTYCD`);
set({ BIZ_TY_CD: res });
const filtered: BIZ_CD_TYPE[] = Array.isArray(res)
? (res as BIZ_CD_TYPE[]).filter(item => item?.lwpoCd !== "AQAAA")
: [];
set({ BIZ_TY_CD: filtered });
} catch (e: any) {
// alert("BIZ_TY_CD 데이터 로드 실패: " + e.message);
console.error("BIZ_TY_CD 데이터 로드 실패:", e);
+8 -8
View File
@@ -1,8 +1,6 @@
import { create } from "zustand";
import { getGeoData, getCmsData } from "@/components/lib/api";
import { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } from "./index";
interface Option { id: number, name: string }
import { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } from "./index";
import { type SelectDataType } from "@common/business_components";
export type BIZ_CD_TYPE = {
lwpoCd: string,
@@ -13,11 +11,12 @@ export type BIZ_CD_TYPE = {
};
interface SnStoreState {
ctpv: Option[];
sgg: Option[];
ctpv: SelectDataType[];
sgg: SelectDataType[];
BIZ_SE_CD: BIZ_CD_TYPE[];
BIZ_TY_CD: BIZ_CD_TYPE[];
fetchCtpvSggData: () => Promise<void>;
fetchCtpv: () => Promise<void>;
fetchSgg: () => Promise<void>;
fetchBIZ_SE_CD: () => Promise<void>;
fetchBIZ_TY_CD: () => Promise<void>;
}
@@ -27,7 +26,8 @@ const useStore = create<SnStoreState>((set) => ({
sgg: [],
BIZ_SE_CD: [],
BIZ_TY_CD: [],
fetchCtpvSggData: () => fetchCtpvSggData(set),
fetchCtpv: () => fetchCtpv(set),
fetchSgg: () => fetchSgg(set),
fetchBIZ_SE_CD: () => fetchBIZ_SE_CD(set),
fetchBIZ_TY_CD: () => fetchBIZ_TY_CD(set),
}));
+2
View File
@@ -4,6 +4,7 @@ import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const isProd = process.env.NODE_ENV === "production";
const compat = new FlatCompat({
baseDirectory: __dirname,
@@ -11,6 +12,7 @@ const compat = new FlatCompat({
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
...(isProd ? { "react-hooks/exhaustive-deps": "off" } : {}),
];
export default eslintConfig;
+4 -1
View File
@@ -34,7 +34,10 @@
"tailwindcss-animate": "^1.0.7",
"tus-js-client": "^4.3.1",
"zod": "^3.24.2",
"zustand": "^5.0.3"
"zustand": "^5.0.3",
"ol": "^7.3.0",
"ol-ext": "^4.0.11",
"proj4": "^2.9.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
@@ -143,6 +143,7 @@ const Map = () => {
}
select.selectFeature(foundFeature, true);
} else {
// toast.error('위치정보를 찾을수 없습니다')
console.warn("OpenLayers Feature를 찾을 수 없습니다:");
console.log("foundFeature :", foundFeature );
console.warn("featureId : ", featureId);
@@ -275,6 +276,8 @@ const Map = () => {
onOpenPopup={(data: any) => {
onOpenPopup(data);
}}
defaultZoom={7.5}
defaultLonLat={[127.75, 36]}
/>
<Toaster position="top-center" />
</div>
@@ -82,6 +82,8 @@ export default function MapDrgtPopUp() {
checkInterval={2500}
height={`h-[100vh]`}
droughtDates={{ startYmd: fromDate, endYmd: toDate }}
defaultZoom={7.5}
defaultLonLat={[127.75, 36]}
/>
</div>
);
@@ -46,7 +46,7 @@ export function SearchBar({ gisMaps, ctpvCode, sggCode }: CtpvSggPrcsFcltSelectB
async function fetchCtpvData() {
try {
const ctpvData = await fetch(`/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson&cql_filter=mctpv_cd=%27${ctpvCd.trim()}%27&srsName=EPSG:5179`)
.then(res => res.json());
.then(res => res.json());
console.log('시도 데이터', ctpvData.features[0]);
const format = new GeoJSON();
@@ -110,10 +110,48 @@ export function SearchBar({ gisMaps, ctpvCode, sggCode }: CtpvSggPrcsFcltSelectB
const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
const res = await fetch(url).then(res => res.json());
const list = res.features.map((f: any) => ({
text: f.properties.mctpv_korn_nm,
val: f.properties.mctpv_cd,
}));
const list = res.features
.map((f: any) => ({
text: f.properties.mctpv_korn_nm,
val: f.properties.mctpv_cd,
}))
.sort((a, b) => {
// 커스텀 순서 정의
const customOrder = [
"서울특별시",
"부산광역시",
"대구광역시",
"인천광역시",
"광주광역시",
"대전광역시",
"울산광역시",
"세종특별자치시",
"경기도",
"강원특별자치도", // 경기도 다음에 배치
"충청북도",
"충청남도",
"전북특별자치도", // 충청남도 다음에 배치
"전라남도",
"경상북도",
"경상남도",
"제주특별자치도"
];
const indexA = customOrder.indexOf(a.text);
const indexB = customOrder.indexOf(b.text);
// 둘 다 커스텀 순서에 있으면 해당 순서로
if (indexA !== -1 && indexB !== -1) {
return indexA - indexB;
}
// 하나만 커스텀 순서에 있으면 그것을 앞으로
if (indexA !== -1) return -1;
if (indexB !== -1) return 1;
// 둘 다 커스텀 순서에 없으면 기본 알파벳 순서
return a.text.localeCompare(b.text, 'ko');
});
console.log('시도 데이터', list);
setCtpv(list);
@@ -126,9 +164,8 @@ export function SearchBar({ gisMaps, ctpvCode, sggCode }: CtpvSggPrcsFcltSelectB
const list = res.features.map((f: any) => ({
text: f.properties.sgg_korn_nm,
val: f.properties.sgg_cd,
}));
})).sort((a, b) => a.text.localeCompare(b.text, 'ko'));
console.log('시군구 데이터', list);
setSgg(list);
};
@@ -82,7 +82,7 @@ export default function MapFeaturePopup() {
return (
<>
{isDetail ? (
<div className="fixed inset-0 w-screen h-screen m-0 p-0 bg-white">
<div className="m-0 bg-white p-4 md:p-6 pb-24 box-border">
{layerNm === "tb_wr_bdst_ruse_fclt" ? (
<RuseDetailPopup bscFctCd={isDetail} />
) : layerNm === "tb_il_swage_prcs_fclt" ? (
@@ -220,6 +220,7 @@ export default function PublicReuseFaciltyInsert() {
setSelectRow(pbnstHasuRes?.[val]);
if (selectRow) {
pbnstRegClick(selectRow);
setIndexMng(0)
} else {
console.error("선택된 행이 없습니다.");
}
@@ -236,6 +237,7 @@ export default function PublicReuseFaciltyInsert() {
}, [indexMng]);
useEffect(() => {
if (pbnst.pbnstRes && pbnst.pbnstRes?.length > 0) {
form.reset({ items: pbnst.pbnstRes });
} else {
@@ -426,6 +428,7 @@ export default function PublicReuseFaciltyInsert() {
}
}}
onInvalid={onInvalid}
newIndexMng={(formWatch?.length -1)}
></PbnstRegModal>
}
bodyClass="w-[68vw] max-w-none h-[90vh]"
@@ -237,11 +237,13 @@ export default function PbnstSttn() {
/>
<UiModal
body={
<PbnstSttnModal
data={pbnDetaileData.data || ({} as customPbnst)}
></PbnstSttnModal>
<div className="flex-1 min-h-0 overflow-auto p-4 md:p-6">
<PbnstSttnModal
data={pbnDetaileData.data || ({} as customPbnst)}
/>
</div>
}
bodyClass="w-[68vw] max-w-none h-[90vh]"
bodyClass="w-[68vw] max-w-none h-[90vh] overflow-hidden flex flex-col min-h-0"
open={pbnDetaileData.isModal}
onOpenChange={(open) => {
//TODO:OPEN 상태 확인필요
@@ -132,7 +132,7 @@ export default function RswtStat() {
}
return item;
});
// 시도별 합계 계산
transformedRswtDetailList.forEach((item: RswtStatProps[]) => {
const sidoText = item[0]?.toString();
@@ -144,18 +144,21 @@ export default function RswtStat() {
sidoData[i] = '합계';
} else if (i == 3) {
// 해당 시도의 데이터 개수를 계산
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
).length;
sidoData[i] = sidoDataCount;
if (typeof sidoData[i] === "number") {
sidoData[i] = (sidoData[i] as number) + 1;
} else if ((sidoData[i] === undefined || isNaN(Number(sidoData[i])))) {
sidoData[i] = 1;
}
} else if (i == 4) {
sidoData[i] = '';
} else if (i == 6) {
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
const bumCnt = rswtDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText
).filter((data: unknown[]) => String(data[6]) === '대상').length;
sidoData[i] = bumCnt;
if (item[i]?.toString() == '대상'&&typeof sidoData[i] === "number") {
sidoData[i] = (sidoData[i] as number) + 1;
} else if (item[i]?.toString() == '대상'&&(sidoData[i] === undefined || isNaN(Number(sidoData[i])))) {
sidoData[i] = 1;
}
} else if (i == 9) {
const value = Number(item[9]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
@@ -256,14 +259,14 @@ export default function RswtStat() {
<Button
className=""
size="sm"
onClick={() => excelClick()}
onClick={excelClick}
>
다운로드
</Button>
<Button
className=""
size="sm"
onClick={() => { excelDetailDownLoad() }}
onClick={excelDetailDownLoad}
>
전체통계다운로드
</Button>
+38 -20
View File
@@ -2,12 +2,15 @@ import { fetchType, getFetch, getFetchWithCount } from "@/components/lib/api";
import type { CommonTableProps } from "../../common/type/header";
import type { customHtdflBdst } from "../../ruseFcltMng/fcltReg/htdflReg";
import { htdflSttHeadListExport, htdflSttNodeListExport } from "../../ruseFcltMng/fcltSttn/htdflSttn/headList";
import type { SelectDataType } from "@common/business_components/ui";
import { excelHtdflSttnParsing } from "../../ruseFcltMng/fcltSttn/htdflSttn/excel";
export const htdfMapSize = 15;
export type htdfMapState = {
htdfMap: {
htdfMapRes: customHtdflBdst[];
htdfMapCount: number;
htdflMapExcelList:[]
isInit: boolean;
htdfSttHeadList: CommonTableProps[];
htdfSttNodeList: CommonTableProps[];
@@ -16,7 +19,9 @@ export type htdfMapState = {
type htdfMapActions = {
htdfMapInit: (page: number, total: number, cityOrSgg: string) => void;
htdfMapSearch: (page: number, total: number, cityOrSgg:string, searchTxt?:string) =>void
htdfMapSearch: (isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]) => void;
htdfMapDetile:(featureCd:string) => Promise<customHtdflBdst | undefined>;
};
@@ -27,6 +32,7 @@ export const htdfMapStateExport: htdfMapState = {
htdfMap: {
isInit: false,
htdfMapRes: [],
htdflMapExcelList:[],
htdfMapCount: 1,
htdfSttHeadList: htdflSttHeadListExport,
htdfSttNodeList: htdflSttNodeListExport,
@@ -62,32 +68,44 @@ export const htdfMapActionsExport: (set: any) => htdfMapActions = (
console.log(e);
}
},
htdfMapSearch: async (
page: number,
total: number,
cityOrSgg: string,
searchTxt?: string
htdfMapSearch: async (isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
) => {
try {
const htdfMapRes = await getFetchWithCount(
fetchType.WR,
`/drain/facilityList` +
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(cityOrSgg ? `/${cityOrSgg}` : "/0") +
(searchTxt ? `/${searchTxt}` : "")
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(con ? `/${con}` : "/0") +
(txt ? `/${txt}` : "")
);
if (isExcel) {
const htdflMapExcelList = excelHtdflSttnParsing(htdfMapRes, sidoCode, sggCode);
set((state: htdfMapState) => {
return {
...state,
htdfMap: {
...state.htdfMap,
htdfMapRes: htdfMapRes.data,
htdfMapCount: htdfMapRes.count,
},
};
});
set((state: htdfMapState) => {
return {
...state,
htdfMap: {
...state.htdfMap,
htdflMapExcelList: htdflMapExcelList
},
};
});
}else{
set((state: htdfMapState) => {
return {
...state,
htdfMap: {
...state.htdfMap,
htdfMapRes: htdfMapRes.data,
htdfMapCount: htdfMapRes.count,
},
};
});
}
} catch (e) {
console.log(e);
}
+21
View File
@@ -0,0 +1,21 @@
export const excelHasuMapParsing = (
excel:{data:any[]}
): string[][] => {
const excelExportData: string[][] = [];
excel.data.forEach((item) => {
excelExportData.push([
item.sido??'',
item.gugun??'',
item.bscFctNm ?? "",
String(item.addr??""),
item.efflWqltStndrdNm ?? "",
String(item.fctCpc ?? ""),
String(item.ruse ?? ""),
String(item.rswtrYn ?? ""),
]);
});
return excelExportData;
};
+54 -2
View File
@@ -1,9 +1,10 @@
import { fetchType, postFectch } from "@/components/lib/api";
import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
import { checkWrRegList } from "../../ruseFcltMng/fcltReg/pbnstReg";
import type { ReturnType } from "@common/business_components/ui";
import type { ReturnType} from "@common/business_components/ui";
import { pubFacHeadListExport } from "../../ruseFcltMng/fcltReg/pbnstReg/headList";
import type { TableUpperProps } from "../../common/type/header";
import { excelHasuMapParsing } from "./excel";
export const pbnMapTableSize = 20;
@@ -61,12 +62,23 @@ export type pbnMapState = {
pbnMapRes: pubHasuType[];
pbnMapCount: number;
pbnMapHeadList: TableUpperProps[];
hasuMapExcelList:[]
};
};
type pbnMapActions = {
pbnMapInit: (page: number, pageTotal: number, reurnValue: ReturnType) => void;
pbnMapDetaile: (featureCd: string, data: string) => Promise<pubHasuType | undefined>;
pbnMapSearch: (
isExcel: boolean,
page: number,
pageTotal: number,
reurnValue: ReturnType,
txt: string,
) => void;
pbnMapDetaile: (
featureCd: string,
data: string
) => Promise<pubHasuType | undefined>;
};
export type pbnMapType = pbnMapState & pbnMapActions;
@@ -77,6 +89,7 @@ export const pbnMapStateExport: pbnMapState = {
pbnMapRes: [],
pbnMapCount: 1,
pbnMapHeadList: pubFacHeadListExport,
hasuMapExcelList:[]
},
};
@@ -124,5 +137,44 @@ export const pbnMapActionsExport: (set: any) => pbnMapActions = (set: any) => {
throw error; // 호출부에서 catch 가능하도록
}
},
pbnMapSearch: async (
isExcel: boolean,
page: number,
pageTotal: number,
reurnValue: ReturnType,
txt: string,
) => {
try {
const hasuMapRes = await hasuListFetch(page, pageTotal, reurnValue, txt);
if (isExcel) {
const hasuMapExcelList = excelHasuMapParsing(
hasuMapRes
);
set((state: pbnMapState) => {
return {
...state,
pbnMap: {
...state.pbnMap,
hasuMapExcelList: hasuMapExcelList
},
};
});
} else {
set((state: pbnMapState) => {
return {
...state,
pbnMap: {
...state.pbnMap,
pbnMapRes: hasuMapRes.data,
pbnMapCount: hasuMapRes.count,
isInit: false,
},
};
});
}
} catch (e) {
console.log(e);
}
},
};
};
+29 -7
View File
@@ -5,12 +5,15 @@ import {
rainSttNodeListExport,
} from "../../ruseFcltMng/fcltSttn/rainSttn/headList";
import type { customRainBdst } from "../../ruseFcltMng/fcltReg/rainReg";
import type { SelectDataType } from "@common/business_components/ui";
import { excelRainSttnParsing } from "../../ruseFcltMng/fcltSttn/rainSttn/excel";
export const rainMapSize = 15
export type rainMapState = {
rainMap: {
rainMapRes: customRainBdst[];
rainMapExcelList: [];
rainMapCount: number;
isInit: boolean;
rainSttHeadList: CommonTableProps[];
@@ -20,7 +23,9 @@ export type rainMapState = {
type rainMapActions = {
rainMapInit: (page: number, total: number, cityOrSgg:string) => void;
rainMapSearch: (page: number, total: number, cityOrSgg:string, searchTxt?:string) =>void
rainMapSearch: (isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]) => void;
rainMapDetile:(featureCd:string) => Promise<customRainBdst | undefined>;
};
@@ -30,6 +35,7 @@ export const rainMapStateExport: rainMapState = {
rainMap: {
isInit: false,
rainMapRes: [],
rainMapExcelList:[],
rainMapCount: 1,
rainSttHeadList: rainSttHeadListExport,
rainSttNodeList: rainSttNodeListExport,
@@ -65,17 +71,31 @@ export const rainMapActionsExport: (set: any) => rainMapActions = (
console.log(e);
}
},
rainMapSearch: async (page: number, total: number, cityOrSgg:string, searchTxt?:string) => {
rainMapSearch: async (isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]) => {
try {
const rainMapRes = await getFetchWithCount(
fetchType.WR,
`/reuseFc/rainyInfoList` +
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(cityOrSgg ? `/${cityOrSgg}` : "/0") +
(searchTxt ? `/${searchTxt}` : "")
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(con ? `/${con}` : "/0") +
(txt ? `/${txt}` : "")
);
if (isExcel) {
const rainMapExcelList = excelRainSttnParsing(rainMapRes, sidoCode, sggCode);
set((state: rainMapState) => {
return {
...state,
rainMap: {
...state.rainMap,
rainMapExcelList: rainMapExcelList,
},
};
});
}else{
set((state: rainMapState) => {
return {
...state,
@@ -86,6 +106,8 @@ export const rainMapActionsExport: (set: any) => rainMapActions = (
},
};
});
}
} catch (e) {
console.log(e);
}
+37 -23
View File
@@ -5,12 +5,15 @@ import {
rswtSttHeadListExport,
rswtSttNodeListExport,
} from "../../ruseFcltMng/fcltSttn/rswtSttn/headList";
import type { SelectDataType } from "@common/business_components/ui";
import { excelRSwtSttnParsing } from "../../ruseFcltMng/fcltSttn/rswtSttn/excel";
export const rswtMapSize = 15;
export type rswtMapState = {
rswtMap: {
rswtMapRes: customRswtBdst[];
rswtMapCount: number;
rswtMapExcelList:[]
isInit: boolean;
rswtSttHeadList: CommonTableProps[];
rswtSttNodeList: CommonTableProps[];
@@ -20,10 +23,9 @@ export type rswtMapState = {
type rswtMapActions = {
rswtMapInit: (page: number, total: number, cityOrSgg: string) => void;
rswtMapSearch: (
page: number,
total: number,
cityOrSgg: string,
searchTxt?: string
isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
) => void;
rswtMapDetile: (featureCd: string) => Promise<customRswtBdst | undefined>;
};
@@ -34,6 +36,7 @@ export const rswtMapStateExport: rswtMapState = {
rswtMap: {
isInit: false,
rswtMapRes: [],
rswtMapExcelList:[],
rswtMapCount: 1,
rswtSttHeadList: rswtSttHeadListExport,
rswtSttNodeList: rswtSttNodeListExport,
@@ -69,32 +72,43 @@ export const rswtMapActionsExport: (set: any) => rswtMapActions = (
console.log(e);
}
},
rswtMapSearch: async (
page: number,
total: number,
cityOrSgg: string,
searchTxt?: string
rswtMapSearch: async (isExcel: boolean, page: number, total: string, con: string, txt: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
) => {
try {
const rswtMapRes = await getFetchWithCount(
fetchType.WR,
`/reuseFc/waterreuseFc` +
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(cityOrSgg ? `/${cityOrSgg}` : "/0") +
(searchTxt ? `/${searchTxt}` : "")
(page ? `/${page}` : "/1") +
(total ? `/${total}` : "/20") +
(con ? `/${con}` : "/0") +
(txt ? `/${txt}` : "")
);
if (isExcel) {
const rswtMapExcelList = excelRSwtSttnParsing(rswtMapRes, sidoCode, sggCode);
set((state: rswtMapState) => {
return {
...state,
rswtMap: {
...state.rswtMap,
rswtMapExcelList:rswtMapExcelList
},
};
});
}else{
set((state: rswtMapState) => {
return {
...state,
rswtMap: {
...state.rswtMap,
rswtMapRes: rswtMapRes.data,
rswtMapCount: rswtMapRes.count,
},
};
});
set((state: rswtMapState) => {
return {
...state,
rswtMap: {
...state.rswtMap,
rswtMapRes: rswtMapRes.data,
rswtMapCount: rswtMapRes.count,
},
};
});
}
} catch (e) {
console.log(e);
}
+58 -2
View File
@@ -8,6 +8,7 @@ import {
import type { ReturnType } from "@common/business_components/ui";
import { hasuListFetch } from "../../ruseFcltMng/fcltSttn/pbnstSttn";
import type { customPbnst } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
import { excelPbnstSttnParsing } from "../../ruseFcltMng/fcltSttn/pbnstSttn/excel";
export const ruseMapSize = 15;
export type ruseMapState = {
@@ -16,6 +17,7 @@ export type ruseMapState = {
ruseMapCount: number;
isInit: boolean;
fclts: string[];
ruseExcelList: [];
ruseDetailList: customPbnst[];
ruseMapHeadList: CommonTableProps[];
ruseMapNodeList: CommonTableProps[];
@@ -31,11 +33,19 @@ type ruseMapActions = {
year: string,
fclts: string[]
) => void;
ruseMapSearch: (
isExcel: boolean,
page: number,
total: number,
reurnValue: ReturnType,
year: string,
fclts: string[],
fcltNm: string
) => void;
ruseMapDetail: (ruseFcltId: string) => Promise<customPbnst | undefined>;
getRuseMaplList: (bscFctCd: string) => void;
};
export type ruseMapType = ruseMapState & ruseMapActions;
export const ruseMapStateExport: ruseMapState = {
@@ -45,6 +55,7 @@ export const ruseMapStateExport: ruseMapState = {
ruseDetailList: [],
fclts: [],
ruseMapCount: 1,
ruseExcelList: [],
ruseMapHeadList: pbnSttHeadListExport,
ruseMapNodeList: pbnstSttNodeListExport,
},
@@ -80,7 +91,6 @@ export const ruseMapActionsExport: (set: any) => ruseMapActions = (
year,
fclts
);
set((state: ruseMapState) => {
return {
...state,
@@ -148,5 +158,51 @@ export const ruseMapActionsExport: (set: any) => ruseMapActions = (
throw errorHasu; // 호출부에서 catch 가능하도록
}
},
ruseMapSearch: async (
isExcel: boolean,
page: number,
total: number,
reurnValue: ReturnType,
year: string,
fclts: string[],
fcltNm: string
) => {
try {
const ruseMapRes = await hasuListFetch(
String(page),
String(total),
reurnValue,
fcltNm,
year,
fclts
);
if (isExcel) {
const ruseMapExcel = excelPbnstSttnParsing(ruseMapRes.data);
set((state: ruseMapState) => {
return {
...state,
ruseMap: {
...state.ruseMap,
ruseExcelList: ruseMapExcel,
},
};
});
} else {
set((state: ruseMapState) => {
return {
...state,
ruseMap: {
...state.ruseMap,
ruseMapRes: ruseMapRes.data,
ruseMapCount: ruseMapRes.count,
isInit: false,
},
};
});
}
} catch (e) {
console.log(e);
}
},
};
};
+44 -44
View File
@@ -61,49 +61,49 @@ export const reUseCaseNames: nameMap = {
"사업비 정산_국고비율(백만원)": "clclnEcqrRt"
}
interface PbnstSttnItem {
rvbsn: string;
lgbsn: number;
mdmbsn?: string;
rgnNm?: string;
sido?: number;
gugun?: number;
bscFctNm?: string;
efflWqltStndrdNm?: string;
fctCpc?: number;
tel?: string;
ruseUtztnFcltNm?: string;
fcltCpct?: number;
splyExtraCpct?: number;
ruseCpct?: number;
usageTotal?: number;
inUsage?: number;
outUsage?: number;
}
// interface PbnstSttnItem {
// rvbsn: string;
// lgbsn: number;
// mdmbsn?: string;
// rgnNm?: string;
// sido?: number;
// gugun?: number;
// bscFctNm?: string;
// efflWqltStndrdNm?: string;
// fctCpc?: number;
// tel?: string;
// ruseUtztnFcltNm?: string;
// fcltCpct?: number;
// splyExtraCpct?: number;
// ruseCpct?: number;
// usageTotal?: number;
// inUsage?: number;
// outUsage?: number;
// }
export const excelPbnstSttnParsing = (data: PbnstSttnItem[]): string[][] => {
const excelExportData: string[][] = [];
// export const excelPbnstSttnParsing = (data: PbnstSttnItem[]): string[][] => {
// const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
item.rvbsn,
String(item.lgbsn),
item.mdmbsn ?? "",
item.rgnNm ?? "",
String(item.sido ?? ""),
String(item.gugun ?? ""),
String(item.bscFctNm ?? ""),
String(item.efflWqltStndrdNm ?? ""),
String(item.fctCpc ?? ""),
String(item.tel ?? ""),
String(item.ruseUtztnFcltNm ?? ""),
String(item.fcltCpct ?? ""),
String(item.splyExtraCpct ?? ""),
String(item.ruseCpct ?? ""),
String(item.usageTotal ?? ""),
String(item.inUsage ?? ""),
String(item.outUsage ?? ""),
])
})
return excelExportData;
};
// data.forEach((item) => {
// excelExportData.push([
// item.rvbsn,
// String(item.lgbsn),
// item.mdmbsn ?? "",
// item.rgnNm ?? "",
// String(item.sido ?? ""),
// String(item.gugun ?? ""),
// String(item.bscFctNm ?? ""),
// String(item.efflWqltStndrdNm ?? ""),
// String(item.fctCpc ?? ""),
// String(item.tel ?? ""),
// String(item.ruseUtztnFcltNm ?? ""),
// String(item.fcltCpct ?? ""),
// String(item.splyExtraCpct ?? ""),
// String(item.ruseCpct ?? ""),
// String(item.usageTotal ?? ""),
// String(item.inUsage ?? ""),
// String(item.outUsage ?? ""),
// ])
// })
// return excelExportData;
// };
@@ -172,9 +172,16 @@ console.log("rainChkgdData", rainChkgdData);
` 연간운영비(원/년): 숫자 형식 아님 /입력값:${rain.anlOperCst}`
);
}
if (rain.oilqMeasMthd.length > 1 && !chkMngType.includes(rain.oilqMeasMthd)) {
if (rain.operMngCd.length > 1 && !chkMngType.includes(rain.operMngCd)) {
issues.push(
defaultMessage + `유량측정방법: 위탁 혹은 자체 만 허용) /입력값:${rain.oilqMeasMthd}`
defaultMessage + `운영관리 형태: 위탁 혹은 자체 만 허용) /입력값:${rain.oilqMeasMthd}`
);
}
if (rain.oilqMeasMthd.length > 1 && !chkSpwtPositnType.includes(rain.oilqMeasMthd)) {
issues.push(
defaultMessage + `유량측정방법: 유량계, 수위계, 펌프적산전력계, 기타) /입력값:${rain.oilqMeasMthd}`
);
}
@@ -2,12 +2,12 @@ import { TEST_UUID } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
isInvalidDate,
isInvalidNumber,
parseCommaRawValue,
parseRawValue,
} from "@/components/lib/func/excelFunc";
import type { SelectDataType } from "@common/business_components/ui";
import type { rswtChkZodType } from ".";
import {
chkSpwtPositnType,
useTypes,
type Buildingtype
} from "../rainChkgdn/excel";
@@ -137,7 +137,6 @@ export const rswtMakeExcelSample = (
export const excelToRswtGuideData = (
excelData: any,
year: string,
issues: string[]
) => {
const rswtChkgdData: rswtChkZodType[] = excelData
.map((item: any) => {
@@ -160,7 +159,7 @@ export const excelToRswtGuideData = (
return {
bdstRuseFcltSn: Number(item["NO"]),
operMngCd: item["운영관리형태"],
anlOperCst: parseRawValue(item[`연간운영비(원/년)`]),
anlOperCst: parseCommaRawValue(item["연간운영비(원/년)"]),
prcsCpct: parseRawValue(item[`처리용량(m³)`]),
spwtPositn: item["채수지점"],
chckYmd: checkYmd,
@@ -174,18 +173,15 @@ export const excelToRswtGuideData = (
})
.filter((el: any) => el !== undefined);
if (rswtChkgdData.length > 0) {
rswtExcelDataCheck(rswtChkgdData, issues);
}
if (issues.length > 0) {
return { data: [], issues };
}
return { data: rswtChkgdData, issues: [] };
return rswtChkgdData
};
export const excelToRswtPolution = (excelData: any, issues: string[]) => {
export const excelToRswtPolution = (excelData: any) => {
const rswtChkgdData: rswtChkZodType[] = excelData
.map((item: any) => {
if (item["점검일"] !== undefined) {
@@ -203,11 +199,11 @@ export const excelToRswtPolution = (excelData: any, issues: string[]) => {
const combResdch = parseRawValue(item[`${quarter}분기_결합잔류염소`]);
const trbt = parseRawValue(item[`${quarter}분기_탁도`]);
const bod = parseRawValue(item[`${quarter}분기_BOD`]);
const smll = parseRawValue(item[`${quarter}분기_냄새`]);
const smll = String(item[`${quarter}분기_냄새`]);
const crmty = parseRawValue(item[`${quarter}분기_색도`]);
const tph = parseRawValue(item[`${quarter}분기_T-P`]);
const tn = parseRawValue(item[`${quarter}분기_T-N`]);
const ph = parseRawValue(item[`${quarter}분기_PH`]);
const ph = String(item[`${quarter}분기_PH`]) ;
const clIonQnt = parseRawValue(item[`${quarter}분기_염화물`]);
return {
node: quarter,
@@ -226,12 +222,13 @@ export const excelToRswtPolution = (excelData: any, issues: string[]) => {
mdfr: TEST_UUID,
};
});
return {
bdstRuseFcltSn: Number(item["NO"]),
chckYmd: checkYmd,
utztnUsgCd: item["이용용도"],
operMngCd: item["운영관리형태"],
anlOperCst: parseRawValue(item["연간운영비(원/년)"]),
anlOperCst: parseCommaRawValue(item["연간운영비(원/년)"]),
prcsCpct: parseRawValue(item["처리용량(m³)"]),
spwtPositn: item["채수지점"],
rswtrPollutions: makePoluttion,
@@ -251,21 +248,22 @@ export const excelToRswtPolution = (excelData: any, issues: string[]) => {
}
})
.filter((el: any) => el !== undefined);
if (rswtChkgdData.length > 0) {
rswtExcelDataCheck(rswtChkgdData, issues);
}
// if (rswtChkgdData.length > 0) {
// rswtExcelDataCheck(rswtChkgdData, issues);
// }
if (issues.length > 0) {
return { data: [], issues };
}
// if (issues.length > 0) {
// return { data: [], issues };
// }
return { data: rswtChkgdData, issues: [] };
return rswtChkgdData
};
const rswtExcelDataCheck = (
export const rswtExcelDataCheck = (
rswtChkgdData: rswtChkZodType[],
issues: string[]
) => {
rswtChkgdData.forEach((rswt: any) => {
const defaultMessage = `*중수도 수질 [NO: ${rswt.bdstRuseFcltSn}, 점검일: ${rswt.chckYmd}, 이용용도: ${rswt.utztnUsgCd}] 항목에서 `;
@@ -273,6 +271,7 @@ const rswtExcelDataCheck = (
issues.push(defaultMessage + `점검일: 날짜 형식 아님 (${rswt.chckYmd})`);
}
if (rswt.anlOperCst.length > 2 && isInvalidNumber(rswt.anlOperCst)) {
issues.push(
defaultMessage +
` 연간운영비(원/년): 숫자 형식 아님 (${rswt.anlOperCst})`
@@ -283,15 +282,15 @@ const rswtExcelDataCheck = (
defaultMessage + ` 처리용량(m³): 숫자 형식 아님 (${rswt.prcsCpct})`
);
}
if (
rswt.spwtPositn.length > 1 &&
!chkSpwtPositnType.includes(rswt.spwtPositn)
) {
issues.push(
defaultMessage +
`측정위치: 유량계, 수위계, 펌프적산전력계, 기타 중 하나만 허용) /입력값:${rswt.spwtPositn}`
);
}
// if (
// rswt.spwtPositn.length > 1 &&
// !chkSpwtPositnType.includes(rswt.spwtPositn)
// ) {
// issues.push(
// defaultMessage +
// `채수지점 : 유량계, 수위계, 펌프적산전력계, 기타 중 하나만 허용) /입력값:${rswt.spwtPositn}`
// );
// }
if (rswt?.rswtrPollutions && rswt?.rswtrPollutions.length > 0) {
rswt.rswtrPollutions.forEach((pol) => {
@@ -318,12 +317,6 @@ const rswtExcelDataCheck = (
defaultMessage + `${pol.node}분기_BOD: 숫자 형식 아님 (${pol.bod})`
);
}
if (isInvalidNumber(pol.smll)) {
issues.push(
defaultMessage +
`${pol.node}분기_냄새: 숫자 형식 아님 (${pol.smll})`
);
}
if (isInvalidNumber(pol.crmty)) {
issues.push(
defaultMessage +
@@ -340,20 +333,16 @@ const rswtExcelDataCheck = (
defaultMessage + `${pol.node}분기_T-N: 숫자 형식 아님 (${pol.tn})`
);
}
if (isInvalidNumber(pol.ph)) {
issues.push(
defaultMessage + `${pol.node}분기_PH: 숫자 형식 아님 (${pol.ph})`
);
if (isInvalidNumber(pol.clIonQnt)) {
issues.push(
defaultMessage +
`${pol.node}분기_PH: 숫자 형식 아님 (${pol.clIonQnt})`
`${pol.node}분기_염소이온량: 숫자 형식 아님 (${pol.clIonQnt})`
);
}
}
});
}
if (rswt?.rswtrDetails && rswt?.rswtrDetails.length > 0) {
rswt?.rswtrDetails.forEach((key) => {
if (key.levyAmt?.length > 1 && isInvalidNumber(key.levyAmt)) {
@@ -285,6 +285,7 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = (
...state.rswtChkgdn,
rswtChkRes: rswtChkRes.data,
rswtChkCount: rswtChkRes.count,
},
}));
} catch (error) {
@@ -361,7 +362,8 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = (
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkRes: rswtChkRes,
rswtChkRes: rswtChkRes.data,
rswtChkCount: rswtChkRes.count,
},
}));
} catch (error) {
@@ -232,16 +232,18 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
if( response.status === 200) {
toast.success(`${pbnstRes.ruseUtztnFcltNm} 하수재이용 시설이 등록되었습니다.`);
}
const pbnstHasuRes = await hasuListFetch('1', '0');
const newPbnstRes = await initFetch(pbnstRes.pbnstRuseFcltId.slice(0, 11));
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstHasuRes: pbnstHasuRes.data,
pbnstHasuResCount:pbnstHasuRes.count,
isInit: false,
pbnstRes: newPbnstRes,
// isInit: false,
},
}));
} catch (error) {
console.error("Error updating pbnst:", error);
}
@@ -22,13 +22,13 @@ export const excelRainSttnParsing = (
String(item.chgBuilding.length > 0 ? "Y" : "N"),
String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""),
String(item.reuseBuilding?.[0]?.instlCst ?? ""),
String(item.reuseBuilding?.[0]?.instlCst === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.instlCst) ?? ""),
item.reuseBuilding?.[0]?.rainyObj?.pntfColKnd ?? "",
String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea) ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctYn ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct) ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct) ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtAmt === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.instlCstSprtAmt) ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""),
@@ -25,7 +25,7 @@ export const excelRSwtSttnParsing = (
String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""), //설치완료일시
String(item.reuseBuilding?.[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding?.[0]?.instlCst ?? ""), //설치비용
item.reuseBuilding?.[0]?.rswtrObj?.orgwtKndCd ?? "", //원수종류
String(item.reuseBuilding?.[0]?.rswtrObj.filtrTrtmfctCpct ?? ""), //처리시설용량
String(item.reuseBuilding?.[0]?.rswtrObj.filtrTrtmfctCpct === -1 ? "확인불가" : item.reuseBuilding?.[0]?.rswtrObj.filtrTrtmfctCpct ?? ""), //처리시설용량
String(item.reuseBuilding?.[0]?.rswtrObj?.filtrTrtmfctProcs ?? ""), //주요처리공정
String(item.reuseBuilding?.[0]?.rswtrObj?.filtrTrtmfctUsgCd ?? ""), //이용용도
String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""), //설치지원비용여부
+10 -4
View File
@@ -50,7 +50,13 @@ const excelDownList: ExcelType[] = [];
const fetchRainStatList = async (year: string) => {
const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`);
return res;
return res.map((item) => ({
...item,
instlCst:item.instlCst<0?0:item.instlCst,
dtfcltCpct:item.dtfcltCpct<0?0:item.dtfcltCpct
}));
};
type rainStatActions = {
@@ -83,7 +89,8 @@ export const rainStatActionsExport = (
searchRainStatList: async (year: string, city: SelectDataType[]) => {
const res = await fetchRainStatList(year);
const cityArr: any[] = [];
console.log('res ', res)
res.filter((resFilter: RainStatProps) =>
city.some((cityCd) =>
@@ -209,6 +216,7 @@ export const rainStatActionsExport = (
utztnUsgCd: utztnUsgArray.join(", "),
});
});
const excelDetailData = excelRainStat(rainDetailList);
/* const rainStatHeadList = data.map((item:RainStatProps) => ({
...item,
@@ -230,8 +238,6 @@ export const rainStatActionsExport = (
yearMoney:item.yearMoney,
})) */
console.log(" cityArr ", cityArr);
console.log(" excelDownList ", excelDownList);
cityArr.unshift(totalObj);
set((state: rainStatState) => ({
+2 -3
View File
@@ -173,7 +173,6 @@ export const getCityOrSgg = (ref: RefObject<ReturnType>) => {
export const safeDate = (value: any): Date | undefined => {
const date = new Date(value);
console.log(' date ', date)
return isNaN(date.getTime()) ? undefined : date;
};
@@ -181,8 +180,8 @@ const currentYear = new Date().getFullYear();
export const yearOptions: { val: string; text: string }[] = Array.from(
{ length: currentYear - 1969 },
(_, i) => ({
val: String(1970 + i),
text: `${1970 + i}년`,
val: String(currentYear - i),
text: `${currentYear - i}년`,
})
);
+19 -2
View File
@@ -12,6 +12,23 @@ export const isInvalidNumber = (val: any) => {
if (val === "" || val === undefined || val === null) return 0;
if (typeof val === "string" && ["보류", "N/A"].includes(val.trim()))
return val;
return !isNaN(val) && val !== " " ? Number(val) : val;
return !isNaN(val) && val !== " " ? Number(val.replaceAll(',','')) : val;
};
export const parseCommaRawValue = (val: any): number | string => {
if (val === "" || val === undefined || val === null) return 0;
// 문자열이고 "보류"나 "N/A"면 그대로 반환
if (typeof val === "string" && ["보류", "N/A"].includes(val.trim())) {
return val;
}
// 문자열에 쉼표가 있으면 제거
if (typeof val === "string" && val.includes(",")) {
val = val.replace(/,/g, "");
}
// 숫자로 변환 가능하면 숫자로, 아니면 그대로
return !isNaN(val) && val !== " " ? Number(val) : val;
};
+12 -6
View File
@@ -9,7 +9,7 @@ const wrLayerList = [
];
const wrFeaturePK = [
{ text: "bscFctCd", val: "tb_il_swage_prcs_fclt" },
{ text: "pbnstRuseFcltId", val: "tb_wr_bdst_ruse_fclt" },
{ text: "searchPk", val: "tb_wr_bdst_ruse_fclt" },
{ text: "bdstInfoSn", val: "tb_wr_rnwtr_utztn_fclt" },
{ text: "bdstInfoSn", val: "tb_wr_rswtr_fclt" },
{ text: "bdstInfoSn", val: "tb_wr_htdfl_fclt" },
@@ -26,11 +26,12 @@ const wrFeaturePK = [
// { text: "잠재수요처", val: "tb_wr_tmpr_dmd_co" },
export const getFeatureCd = (featurePropertise: any, layerNm: string) => {
console.log('featurePropertise ', featurePropertise)
const featureCd =
layerNm === "tb_wr_bdst_ruse_fclt"
? featurePropertise?.swtrmt_fclt_cd
: [
"tb_wr_ruse_fclt_dmd_co",
"tb_wr_rswtr_fclt",
"tb_wr_htdfl_fclt",
"tb_wr_rnwtr_utztn_fclt",
@@ -39,6 +40,8 @@ export const getFeatureCd = (featurePropertise: any, layerNm: string) => {
? featurePropertise?.bdst_nm
: layerNm === "tb_il_swage_prcs_fclt"
? featurePropertise?.swtrmt_fclt_nm
: layerNm === "tb_wr_ruse_fclt_dmd_co"?
featurePropertise?.bdst_info_sn
: null;
return featureCd;
@@ -125,15 +128,18 @@ export function featurePopUpOpen(layerNm:string,featureCd:string,popupDetailRef)
const url = `/mapFeaturePopup?layerNm=${encodeURIComponent(String(layerNm))}&featureCd=${encodeURIComponent(featureCd)} `;
const width =
String(layerNm) === "tb_wr_bdst_ruse_fclt"
? Math.floor(window.innerWidth * 0.8)
? Math.floor(window.innerWidth * 0.6)
: Math.floor(window.innerWidth * 0.4); // 화면 폭의 40%
const height =
String(layerNm) === "tb_wr_bdst_ruse_fclt"
? Math.floor(window.innerHeight - 150)
: Math.floor(window.innerHeight - 450); // 150px 여백 확보; // calc(100% - 70px)
? Math.floor(window.innerHeight - 100)
: String(layerNm) === "tb_wr_ruse_fclt_dmd_co"
?Math.floor(window.innerHeight - 430)
: Math.floor(window.innerHeight - 300); // 150px 여백 확보; // calc(100% - 70px)
const left = (window.screen.availWidth - width) / 2;
const top = (window.screen.availHeight - height) / 2;
const popupOptions = `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
const popupOptions = `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes `;
popupDetailRef.current = window.open(
url,
"지도 시설 상세정보 팝업",
@@ -234,9 +234,6 @@ export default function ConCostForm({
}
};
useEffect(() => {
console.log(" form ", form.formState.errors);
}, [form.formState]);
useEffect(() => {
const origin = window.location.origin;
@@ -580,9 +577,6 @@ export default function ConCostForm({
<Button
size={"sm"}
onClick={(e) => {
console.log(e);
setLastSub(null) // 빌드오류때문에 넣은거 삭제필요
searchCandidate(e);
//splyList => 해당객체가 대민에서 선택한 후보처 리스트
@@ -23,9 +23,9 @@ export default function BdstAdd({ form, readonly }: { form: any; readonly?: bool
const plusHist = () => {
append({
bdstNm: "",
daddr: "",
bdstUsgCd: "",
bdstChgNm: code.chBuCd[0]?.val,
archChgPrmsnDt: new Date(),
archChgArea: "",
});
};
const [selectedIds, setSelectedIds] = useState<string[]>([]);
@@ -75,7 +75,7 @@ export default function BdstAdd({ form, readonly }: { form: any; readonly?: bool
} gap-2 mt-4 items-center`}
>
{!readonly && (
<div className="col-span-1 flex justify-center mr-4">
<div className="mt-9 col-span-1 flex justify-center mr-4 ">
<Checkbox
checked={selectedIds.includes(field.id)}
onCheckedChange={() => toggleSelect(field.id)}
@@ -127,7 +127,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -164,7 +164,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -199,7 +199,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -233,7 +233,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -306,7 +306,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -340,7 +340,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -375,7 +375,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -409,7 +409,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -444,7 +444,7 @@ export function BuseWaterQulity({
}}
value={
field.value !== undefined && field.value !== ""
? `${field.value}`
? `${field.value??''}`
: ""
}
readOnly={readonly}
@@ -460,7 +460,7 @@ export function BuseWaterQulity({
/>
</div>
<div className="col-span-8">
<Label className="text-xl">수소이온농도(PH)</Label>
<Label className="text-xl">수소이온농도(ph)</Label>
<div className="flex flex-row items-center gap-2">
<Input
className="!text-xl w-28"
@@ -9,7 +9,7 @@ import {
} from "@common/business_components/ui";
import { Form, FormField } from "@common/business_components/ui/form";
import { Button, Input } from "@common/components";
import { useEffect, useRef, useState } from "react";
import { useEffect, useState } from "react";
import { useFieldArray, type UseFormReturn } from "react-hook-form";
import {
commonButonSize,
@@ -18,7 +18,6 @@ import {
} from "@/components/lib/class/comClass";
import { TusClientUpload } from "@/components/lib/useTus_wr/useTusWr";
import {
type fcFileType,
type PbnstRegArrrayType,
type selectLabel,
} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
@@ -52,15 +51,11 @@ export function PbnstMngForm({
const { code, pbnst, fileDelete, fileDownLoad } = useWrStore(
(state) => state
);
const fileInitRef = useRef<{ index: number; key: string } | null>(null);
const [regFileList, setRegFileList] = useState<fcFileType[] | null>(null);
const [planFiles, setPlanFiles] = useState<FilesType[] | null>(null);
const [relationfiles, setRelationFiles] = useState<FilesType[] | null>(null);
const [fcltNm, setFcltNm] = useState<selectLabel[] | null>(null);
const [mngMtdCode, setMngMtdCode] =
useState<{ name: string; val: SelectDataType[] }[]>();
const {
fields: fcOpersField,
prepend,
@@ -155,35 +150,30 @@ export function PbnstMngForm({
}
};
const regFileFilter = (
files: FilesType[],
fileKnd: string,
regFile: fcFileType[]
) => {
const exFileDatas =
regFile?.filter((item) => item.fileKnd !== fileKnd) || [];
const currentdata = files.map((item) => ({
fileTkn: item.atflCd,
filePath: item.file.name,
fileKnd: fileKnd,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
}));
return [...exFileDatas, ...currentdata];
};
// const regFileFilter = (
// files: FilesType[],
// fileKnd: string,
// regFile: fcFileType[]
// ) => {
// const exFileDatas =
// regFile?.filter((item) => item.fileKnd !== fileKnd) || [];
// const currentdata = files.map((item) => ({
// fileTkn: item.atflCd,
// filePath: item.file.name,
// fileKnd: fileKnd,
// rgtr: TEST_UUID,
// mdfr: TEST_UUID,
// }));
// return [...exFileDatas, ...currentdata];
// };
useEffect(() => {
setRelationFiles([]);
setPlanFiles([]);
console.log("indexMng ", indexMng);
const currentItem = form.getValues(`items.${indexMng}`);
const currentKey = JSON.stringify(currentItem);
const isNewItem =
!fileInitRef.current ||
fileInitRef.current.index !== indexMng ||
fileInitRef.current.key !== currentKey;
if (!isNewItem) return; //
const defaultFiles = currentItem?.fcFiles || [];
const relationFileList = defaultFiles.filter(
(item) => item.fileKnd === "계통도"
);
@@ -199,7 +189,6 @@ export function PbnstMngForm({
}))
: null
);
setPlanFiles(
planFileList.length > 0
? planFileList.map((item) => ({
@@ -208,16 +197,10 @@ export function PbnstMngForm({
}))
: null
);
// ✅ 다음 루프에선 다시 안 하도록 저장
fileInitRef.current = {
index: indexMng,
key: currentKey,
};
}, [indexMng, form.getValues(`items.${indexMng}`)]);
}, [form.getValues(`items.${indexMng}`)]);
useEffect(
() => {
//폼이 들어오면 폼에 대한 이름 셀렉트박스를만들기 위해
if (mngRegForm && mngRegForm.length >= 0) {
const fcltNmList = mngRegForm?.map((item, index) => ({
text: item.ruseUtztnFcltNm,
@@ -231,20 +214,33 @@ export function PbnstMngForm({
[mngRegForm]
);
useEffect(() => {
if (regFileList && regFileList?.length > 0) {
form.setValue(`items.${indexMng}.fcFiles`, regFileList);
}
}, [regFileList, indexMng]);
const formFileChange = (file: FilesType[], type: string) => {
return file?.map((item) => ({
fileTkn: item.atflCd,
filePath: item.file.name,
fileKnd: type,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
}));
};
useEffect(() => {
if (relationfiles) {
setRegFileList(regFileFilter(relationfiles, "계통도", regFileList || []));
console.log("indexMng relationfiles", indexMng);
form.setValue(`items.${indexMng}.fcFiles`, [
...(formFileChange(planFiles ?? [], "평면도") ?? []),
...formFileChange(relationfiles, "계통도"),
]);
//setRegFileList(regFileFilter(relationfiles, "계통도", regFileList || []));
}
}, [relationfiles]);
useEffect(() => {
if (planFiles) {
setRegFileList(regFileFilter(planFiles, "평면도", regFileList || []));
// setRegFileList(regFileFilter(planFiles, "평면도", regFileList || []));
console.log("indexMng planFiles", indexMng);
form.setValue(`items.${indexMng}.fcFiles`, [
...(formFileChange(planFiles ?? [], "평면도") ?? []),
...formFileChange(relationfiles ?? [], "계통도"),
]);
}
}, [planFiles]);
@@ -254,6 +250,7 @@ export function PbnstMngForm({
}
}, [code]);
return (
<div className=" !mx-[1.6rem] !p-0r">
<div>
@@ -365,7 +362,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
handleCommaNumberChange(e, field.onChange);
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
@@ -388,7 +385,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
handleCommaNumberChange(e, field.onChange);
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
@@ -410,7 +407,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
handleCommaNumberChange(e, field.onChange);
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
@@ -445,6 +442,7 @@ export function PbnstMngForm({
) : (
<FormUi label="계통도">
<FileUpload
key={`items.${indexMng}.planFiles`}
files={relationfiles?.map((item) => item.file) || []}
setFiles={(files: File[] | null) => {
if (files) fileHandler(files, "relation");
@@ -482,6 +480,7 @@ export function PbnstMngForm({
) : (
<FormUi label="평면도">
<FileUpload
key={`items.${indexMng}.planFiles`}
files={planFiles?.map((item) => item.file) || []}
setFiles={(files: File[] | null) => {
if (files) fileHandler(files, "plan");
@@ -579,7 +579,6 @@ export default function RainRegForm({
value={isUnknown ? "확인불가" : (field.value ?? "")}
onChange={(e) => {
if (readonly) return;
if (e.target.value === "확인불가") {
field.onChange("");
} else {
@@ -2,7 +2,7 @@ import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { pbnMapTableSize } from "@/app/store/map/pbnstMap";
import type { pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { tableData } from "@/components/lib/func/commom";
import { excelDownload, tableData } from "@/components/lib/func/commom";
import {
ContentsDiv,
SearchBaseForm,
@@ -13,14 +13,17 @@ import {
} from "@common/business_components/ui";
import { Label } from "@common/components/ui";
import { useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export function HasuFacility({rtnFeature}:{rtnFeature:(feature:any)=>void } ) {
const { code, pbnMap, pbnMapInit } = useWrStore((state) => state);
const { code, pbnMap, pbnMapInit ,pbnMapSearch} = useWrStore((state) => state);
const [hasuTable, setHasuTable] = useState<pubHasuType[]>();
const [isReset, setIsReset] = useState(false);
const [pbnRuseNm, setPbnRuseNm] = useState<string>("");
const ref = useRef<ReturnType>({} as ReturnType);
const { pbnMapHeadList, pbnMapRes, pbnMapCount } = pbnMap;
const { pbnMapHeadList, pbnMapRes, pbnMapCount ,hasuMapExcelList} = pbnMap;
const { t } = useTranslation("base");
useEffect(() => {
if (!pbnMap.isInit) {
@@ -39,6 +42,22 @@ export function HasuFacility({rtnFeature}:{rtnFeature:(feature:any)=>void } ) {
rtnFeature(pbnMapRes[index])
}
};
useEffect(() => {
if (hasuMapExcelList.length > 0) {
excelDownload(
hasuMapExcelList,
"하수처리시설 현황",
"sample_hasuMap.xlsx",
"A1:H1",
2
);
} else {
toast.error(t("excelDownErrMsg"));
}
}, [hasuMapExcelList]);
return (
<>
<ContentsDiv>
@@ -83,6 +102,10 @@ export function HasuFacility({rtnFeature}:{rtnFeature:(feature:any)=>void } ) {
isAdmin={false}
excelClick={function (returnType: ReturnType): void {
console.log("pbnstSttnSearch ", returnType);
pbnMapSearch(true,1, 100000, returnType,pbnRuseNm??'' )
}}
/>
</div>
@@ -96,7 +119,9 @@ export function HasuFacility({rtnFeature}:{rtnFeature:(feature:any)=>void } ) {
headName={""}
cellClick={hasuCellClick}
onPageChange={(page) => {
pbnMapInit(page, pbnMapTableSize, ref.current);
//pbnMapInit(page, pbnMapTableSize, ref.current);
pbnMapSearch(false,page, pbnMapTableSize, ref.current,pbnRuseNm??'' )
setIsReset(false);
}}
resetPageNo={isReset}
@@ -1,7 +1,12 @@
import { useWrStore } from "@/app/store";
import { htdfMapSize } from "@/app/store/map/htdflMap";
import { rainMapSize } from "@/app/store/map/rainMap";
import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg";
import { getCity, tableData } from "@/components/lib/func/commom";
import {
excelDownload,
getCity,
tableData,
} from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
@@ -17,15 +22,26 @@ import {
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export function HtdflFacility({
rtnFeature,
}: {
rtnFeature: (feature: any) => void;
}) {
const { code, htdfMap, htdfMapInit,htdfMapSearch } = useWrStore((state) => state);
const { htdfMapCount, htdfMapRes, htdfSttHeadList, htdfSttNodeList } =
htdfMap;
const { code, htdfMap, htdfMapInit, htdfMapSearch } = useWrStore(
(state) => state
);
const { t } = useTranslation("base");
const {
htdfMapCount,
htdflMapExcelList,
htdfMapRes,
htdfSttHeadList,
htdfSttNodeList,
} = htdfMap;
const [htdflTable, setHtdflTable] = useState<customHtdflBdst[]>();
const [isReset, setIsReset] = useState(false);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
@@ -86,6 +102,19 @@ export function HtdflFacility({
setHtdflTable(chData);
}, [code, htdfMapRes]);
useEffect(() => {
if (htdflMapExcelList.length > 0) {
excelDownload(
htdflMapExcelList,
"온배수시설 현황",
"sample_htdflSttn.xlsx",
"A1:R3"
);
} else {
toast.error(t("excelDownErrMsg"));
}
}, [htdflMapExcelList]);
return (
<>
<ContentsDiv>
@@ -115,17 +144,50 @@ export function HtdflFacility({
/>
<SearchInput
className={"!text-3xl ml-4"}
label="회사명"
label="건물명"
textValue={seartchTxt ?? ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
/>{" "}
<Button
className="mt-2 mx-4"
size={"sm"}
onClick={() => {
setIsReset(true);
}}
>
조회
</Button>
<Button
className="mt-2"
size={"sm"}
color="green"
onClick={() => {
const con =
objSearch.sgg && objSearch.sgg !== "0"
? objSearch.sgg
: objSearch.city;
if (con) {
htdfMapSearch(
true,
1,
"1000000",
String(con),
seartchTxt||'',
code.cityCd,
code.sggCd
);
}
}}
>
엑셀다운로드
</Button>
</div>
</SearchFormLeft>
<SearchFormRight className="w-3/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
<div className="flex flex-row space-x-2">
<Button
{/* <Button
className="mt-2"
size={"sm"}
onClick={() => {
@@ -134,13 +196,23 @@ export function HtdflFacility({
>
조회
</Button>
<Button
className="mt-2"
size={"sm"}
color="green"
onClick={() => {
setIsReset(true);
}}
>
엑셀다운로드
</Button> */}
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-2 gap-4 ">
<div className="col-span-2">
<div className="col-span-2">
<UiTable
headName={[]}
tableData={htdflTable || []}
@@ -156,16 +228,15 @@ export function HtdflFacility({
? objSearch.sgg
: objSearch.city;
if (con) {
if (seartchTxt && seartchTxt?.length > 0) {
htdfMapSearch(
page,
rainMapSize,
String(con),
seartchTxt ?? ""
);
} else {
htdfMapSearch(page, rainMapSize, String(con));
}
htdfMapSearch(
false,
page,
String(htdfMapSize),
String(con),
seartchTxt||'',
code.cityCd,
code.sggCd
);
setIsReset(false);
}
}}
@@ -1,7 +1,7 @@
import { useWrStore } from "@/app/store";
import { rainMapSize } from "@/app/store/map/rainMap";
import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { getCity, tableData } from "@/components/lib/func/commom";
import { excelDownload, getCity, tableData } from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
@@ -17,6 +17,8 @@ import {
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export function RainFacility({
rtnFeature,
@@ -26,7 +28,7 @@ export function RainFacility({
const { code, rainMap, rainMapInit, rainMapSearch } = useWrStore(
(state) => state
);
const { rainMapRes, rainMapCount, rainSttHeadList, rainSttNodeList } =
const { rainMapRes, rainMapExcelList,rainMapCount, rainSttHeadList, rainSttNodeList } =
rainMap;
const [rainTable, setRainTable] = useState<customRainBdst[]>();
const [isReset, setIsReset] = useState(false);
@@ -35,6 +37,7 @@ export function RainFacility({
sgg: "",
city: "",
});
const { t } = useTranslation('base');
const [seartchTxt, setSearchTxt] = useState<string>();
@@ -116,7 +119,18 @@ export function RainFacility({
.filter((item: any) => item.rainyObj !== undefined);
setRainTable(chData);
}, [code, rainMapRes]);
useEffect(() => {
if (rainMapExcelList.length > 0) {
excelDownload(
rainMapExcelList,
"빗물재이용시설 현황",
"sample_rainSttn.xlsx",
"A1:W3"
);
} else {
toast.error(t("excelDownErrMsg"));
}
}, [rainMapExcelList]);
return (
<>
<ContentsDiv>
@@ -146,17 +160,50 @@ export function RainFacility({
/>
<SearchInput
className={"!text-3xl ml-4"}
label="회사명"
label="건물명"
textValue={seartchTxt ?? ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
<Button
className="mt-2 mx-4"
size={"sm"}
onClick={() => {
setIsReset(true);
}}
>
조회
</Button>
<Button
className="mt-2"
size={"sm"}
color="green"
onClick={() => {
const con =
objSearch.sgg && objSearch.sgg !== "0"
? objSearch.sgg
: objSearch.city;
if (con) {
rainMapSearch(
true,
1,
"1000000",
String(con),
seartchTxt ?? "",
code.cityCd,
code.sggCd
);
}
}}
>
엑셀다운로드
</Button>
</div>
</SearchFormLeft>
<SearchFormRight className="w-3/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
<div className="flex flex-row space-x-2">
<Button
{/* <Button
className="mt-2"
size={"sm"}
onClick={() => {
@@ -165,6 +212,15 @@ export function RainFacility({
>
조회
</Button>
<Button
className="mt-2"
size={"sm"}
color="green"
onClick={() => {
}}
>
엑셀다운로드
</Button> */}
</div>
</SearchFormRight>
</SearchDiv>
@@ -187,16 +243,16 @@ export function RainFacility({
? objSearch.sgg
: objSearch.city;
if (con) {
if (seartchTxt && seartchTxt?.length > 0) {
rainMapSearch(
page,
rainMapSize,
String(con),
seartchTxt ?? ""
);
} else {
rainMapSearch(page, rainMapSize, String(con));
}
rainMapSearch(
false,
page,
String(rainMapSize),
String(con),
seartchTxt ?? "",
code.cityCd,
code.sggCd
);
setIsReset(false);
}
}}
@@ -1,57 +1,71 @@
import { useWrStore } from "@/app/store";
import { rainMapSize } from "@/app/store/map/rainMap";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { getCity, tableData } from "@/components/lib/func/commom";
import { excelDownload, getCity, tableData } from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import { ContentsDiv, SearchDiv, SearchFormLeft, SearchFormRight, SearchInput, SelectBox, Title, UiTable, type SelectDataType } from "@common/business_components/ui";
import {
ContentsDiv,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiTable,
type SelectDataType,
} from "@common/business_components/ui";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export function RswtFacility({
rtnFeature,
}: {
rtnFeature: (feature: any) => void;
}) {
const { code, rswtMap, rswtMapInit,rswtMapSearch } = useWrStore((state) => state);
const { rswtMapRes, rswtMapCount, rswtSttHeadList, rswtSttNodeList } =
const { code, rswtMap, rswtMapInit, rswtMapSearch } = useWrStore(
(state) => state
);
const { rswtMapRes, rswtMapExcelList, rswtMapCount, rswtSttHeadList, rswtSttNodeList } =
rswtMap;
const [rswtrTable, setRswtrTable] = useState<customRswtBdst[]>();
const [isReset, setIsReset] = useState(false);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({
sgg: "",
city: "",
});
const [seartchTxt, setSearchTxt] = useState<string>();
const getSelCity = useCallback(
(val: string | number) => {
const cityValue = String(val);
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: "0" });
},
[code.sggCd]
);
const getSgg = useCallback((val: string | number) => {
setObjSearch((prev) => ({ ...prev, sgg: String(val) }));
}, []);
useEffect(() => {
// code.cityCd 데이터가 로드되었고, 아직 시/도 선택이 안된 초기 상태일 때 실행
if (code.cityCd && code.cityCd.length > 0 && !objSearch.city) {
const firstCityVal = code.cityCd[0]?.val;
if (firstCityVal) {
// 첫 번째 시/도 값으로 상태를 초기화합니다.
getSelCity(firstCityVal);
}
const [objSearch, setObjSearch] = useState<objSearchType>({
sgg: "",
city: "",
});
const { t } = useTranslation('base');
const [seartchTxt, setSearchTxt] = useState<string>();
const getSelCity = useCallback(
(val: string | number) => {
const cityValue = String(val);
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: "0" });
},
[code.sggCd]
);
const getSgg = useCallback((val: string | number) => {
setObjSearch((prev) => ({ ...prev, sgg: String(val) }));
}, []);
useEffect(() => {
// code.cityCd 데이터가 로드되었고, 아직 시/도 선택이 안된 초기 상태일 때 실행
if (code.cityCd && code.cityCd.length > 0 && !objSearch.city) {
const firstCityVal = code.cityCd[0]?.val;
if (firstCityVal) {
// 첫 번째 시/도 값으로 상태를 초기화합니다.
getSelCity(firstCityVal);
}
}, [code.cityCd, objSearch.city, getSelCity]);
}
}, [code.cityCd, objSearch.city, getSelCity]);
const rswtCellClick = (index: number | undefined, headId: string) => {
if (
headId !== "chBuildingYn" &&
@@ -100,6 +114,19 @@ export function RswtFacility({
);
setRswtrTable(chData);
}, [code, rswtMapRes]);
useEffect(() => {
if (rswtMapExcelList.length > 0) {
excelDownload(
rswtMapExcelList,
"중수도시설 현황",
"sample_rswtSttn.xlsx",
"A1:W3",
);
} else {
toast.error(t('excelDownErrMsg'));
}
}, [rswtMapExcelList]);
return (
<>
<ContentsDiv>
@@ -129,18 +156,14 @@ export function RswtFacility({
/>
<SearchInput
className={"!text-3xl ml-4"}
label="회사명"
label="건물명"
textValue={seartchTxt ?? ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
</div>
</SearchFormLeft>
<SearchFormRight className="w-3/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
<div className="flex flex-row space-x-2">
<Button
className="mt-2"
className="mt-2 mx-4"
size={"sm"}
onClick={() => {
setIsReset(true);
@@ -148,6 +171,43 @@ export function RswtFacility({
>
조회
</Button>
<Button
className="mt-2"
size={"sm"}
color="green"
onClick={() => {
const con =
objSearch.sgg && objSearch.sgg !== "0"
? objSearch.sgg
: objSearch.city;
if (con) {
rswtMapSearch(
true,
1,
"1000000",
String(con),
seartchTxt ?? "",
code.cityCd,
code.sggCd
);
}
}}
>
엑셀다운로드
</Button>
</div>
</SearchFormLeft>
<SearchFormRight className="w-3/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
<div className="flex flex-row space-x-2">
{/* <Button
className="mt-2"
size={"sm"}
onClick={() => {
setIsReset(true);
}}
>
조회
</Button> */}
</div>
</SearchFormRight>
</SearchDiv>
@@ -166,22 +226,23 @@ export function RswtFacility({
}}
onPageChange={(page) => {
const con =
objSearch.sgg && objSearch.sgg !== "0"
? objSearch.sgg
: objSearch.city;
if (con) {
if (seartchTxt && seartchTxt?.length > 0) {
objSearch.sgg && objSearch.sgg !== "0"
? objSearch.sgg
: objSearch.city;
if (con) {
rswtMapSearch(
false,
page,
rainMapSize,
String(rainMapSize),
String(con),
seartchTxt ?? ""
seartchTxt ?? "",
code.cityCd,
code.sggCd
);
} else {
rswtMapSearch(page, rainMapSize, String(con));
setIsReset(false);
}
setIsReset(false);
}}}
}}
resetPageNo={isReset}
>
<HeadMakeColSpan upHeadList={rswtSttNodeList} />
@@ -2,7 +2,7 @@ import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { ruseMapSize } from "@/app/store/map/ruseMap";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { yearOptions } from "@/components/lib/func/commom";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import {
ContentsDiv,
SearchBaseForm,
@@ -14,17 +14,20 @@ import {
} from "@common/business_components/ui";
import { Label } from "@common/components/ui";
import { useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export function RuseFacility({
rtnFeature,
}: {
rtnFeature: (feature: any) => void;
}) {
const { code, ruseMap, ruseMapInit, getMapFlcts } = useWrStore(
const { code, ruseMap, ruseMapInit, getMapFlcts,ruseMapSearch } = useWrStore(
(state) => state
);
const { t } = useTranslation("base");
const { ruseMapCount, fclts, ruseMapRes,ruseMapHeadList } = ruseMap;
const { ruseMapCount, ruseExcelList,fclts, ruseMapRes,ruseMapHeadList } = ruseMap;
const [ruseTable, setRuseTable] = useState<WaterReuseFacility[]>();
const [isReset, setIsReset] = useState(false);
@@ -51,6 +54,23 @@ export function RuseFacility({
ruseMapInit(1,ruseMapSize, ref.current, searchYear, fclts);
}, [fclts]);
useEffect(()=>{
if(ruseExcelList&&ruseExcelList.length>0){
if (ruseExcelList.length > 0) {
excelDownload(
ruseExcelList,
"하수재이용시설 현황",
"sample_pbnstSttn.xlsx",
"A1:U2",
3
);
} else {
toast.error(t('excelDownErrMsg'));
}
}
},[ruseExcelList])
useEffect(() => {
if (ruseMapRes && ruseMapRes.length > 0) {
setRuseTable(ruseMapRes);
@@ -113,7 +133,7 @@ export function RuseFacility({
ref={ref}
isAdmin={false}
excelClick={function (returnType: ReturnType): void {
console.log("pbnstSttnSearch ", returnType);
ruseMapSearch(true,1,1000000 , returnType, searchYear, fclts,pbnRuseNm??'')
}}
/>
</div>
@@ -127,7 +147,12 @@ export function RuseFacility({
headName={""}
cellClick={ruseCellClick}
onPageChange={(page) => {
ruseMapInit(page,ruseMapSize , ref.current, searchYear, fclts);
if(pbnRuseNm&&pbnRuseNm.length>0){
ruseMapSearch(false,page,ruseMapSize , ref.current, searchYear, fclts,pbnRuseNm)
}else{
ruseMapInit(page,ruseMapSize , ref.current, searchYear, fclts);
}
setIsReset(false);
}}
resetPageNo={isReset}
@@ -13,7 +13,7 @@ export function RuseDetailPopup({ bscFctCd }: { bscFctCd: string }) {
const { ruseMap, getRuseMaplList } = useWrStore((state) => state);
const { ruseDetailList } = ruseMap;
const [fcltTab, setFcltTab] = useState<string>("");
const [isDetail, setIsDetail] = useState<customPbnst>({} as customPbnst);
const [, setIsDetail] = useState<customPbnst>({} as customPbnst);
const initRef = useRef<boolean>(false);
useEffect(() => {
@@ -38,9 +38,9 @@ export function RuseDetailPopup({ bscFctCd }: { bscFctCd: string }) {
if (!(ruseDetailList && ruseDetailList[0])) return;
return (
<div>
<div className="">
<Tabs value={fcltTab} onValueChange={setFcltTab}>
<TabsList className="mt-4">
<TabsList className="mt-2 mb-3 gap-2 flex flex-wrap">
{ruseDetailList.map((item, index) => {
return (
<TabsTrigger
@@ -54,9 +54,17 @@ export function RuseDetailPopup({ bscFctCd }: { bscFctCd: string }) {
})}
</TabsList>
<TabsContent className="flex-1 px-4" value={fcltTab}>
<PbnstSttnModal data={isDetail} isMap={true} />
</TabsContent>
{ruseDetailList.map((item) => (
<TabsContent
key={item.pbnstRuseFcltId}
className="flex-1 px-4 py-3"
value={item.pbnstRuseFcltId}
>
<div className="mb-4">
<PbnstSttnModal data={item} isMap={true} />
</div>
</TabsContent>
))}
</Tabs>
</div>
);
@@ -6,6 +6,7 @@ import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn
import {
excelToRswtGuideData,
excelToRswtPolution,
rswtExcelDataCheck,
} from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/excel";
import { showConfirmToast } from "@/components/lib/func/commom";
import {
@@ -110,30 +111,23 @@ export default function ChkgdExcel({
});
} else if (type === "RST") {
filePickedArray(file, 0).then((res) => {
let issues: string[] = [];
if (res && res?.length > 1) {
const guideData = excelToRswtGuideData(
res[0],
form.getValues("chckYr"),
issues
);
const polutionData = excelToRswtPolution(res[1], issues);
const polutionData = excelToRswtPolution(res[1]);
issues = [...guideData.issues, ...polutionData.issues];
if (issues && issues.length > 0) {
issues.some((err, index) => {
showConfirmToast(err);
return index === 6; // true 반환 시 반복 종료
});
clearFile();
} else {
const keyGenerator = (item: rswtChkZodType) =>
`${item.bdstRuseFcltSn}|${item.chckYmd}|${item.utztnUsgCd}`;
const totalData: rswtChkZodType[] = guideData.data.map(
const totalData: rswtChkZodType[] = guideData.map(
(guide) => {
const fusion = polutionData.data.find(
const fusion = polutionData.find(
(polution) =>
guide.bdstRuseFcltSn === polution.bdstRuseFcltSn &&
guide.chckYmd === polution.chckYmd &&
@@ -153,8 +147,8 @@ export default function ChkgdExcel({
}
}
);
const guideKey = new Set(guideData.data.map(keyGenerator));
const onlypolution = polutionData.data.filter(
const guideKey = new Set(guideData.map(keyGenerator));
const onlypolution = polutionData.filter(
(item) => !guideKey.has(keyGenerator(item))
);
@@ -162,9 +156,20 @@ export default function ChkgdExcel({
...totalData,
...onlypolution,
];
const issues: string[] = [];
setExcelRswtData(listTotalData);
}
console.log('listTotalData ', listTotalData)
rswtExcelDataCheck(listTotalData,issues)
if (issues && issues.length > 0) {
issues.some((err, index) => {
showConfirmToast(err);
return index === 6; // true 반환 시 반복 종료
});
clearFile();
} else {
setExcelRswtData(listTotalData);
}
}
});
}
@@ -79,7 +79,6 @@ export default function RuseCaseMngExcel() {
};
Object.keys(reUseCaseNames).forEach((key: string) => {
console.log("reUseCaseNames", reUseCaseNames)
if (item && reUseCaseNames[key] !== undefined) {
const mappedKey = reUseCaseNames[key];
if (mappedKey && object.hasOwnProperty(mappedKey)) {
@@ -128,23 +128,10 @@ export default function FcOrgwtsRegModal({
}>
조회
</Button>
<Button size="sm" onClick={saveData}>저장</Button>
<Button size="sm" onClick={saveData}>적용</Button>
</div>
</div>
</div>
{/* <div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Label className="text-xl text-gray-600">시설명</Label>
<Input
className="w-48 text-xl"
type="text"
value={inputVal}
onChange={(e) => setInputVal(e.target.value)}
/>
<Button size="sm" onClick={() => getSwtrmtFcltNm(inputVal)}>조회</Button>
</div>
</div>
</div> */}
{/* 테이블 영역 */}
<div className="flex flex-row gap-4 flex-grow p-4 overflow-x-auto">
@@ -25,18 +25,20 @@ export function PbnstRegModal({
form,
setPbnstInsert,
onInvalid,
newIndexMng
}: {
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
setPbnstInsert: (data: customPbnst) => void;
onInvalid: (
errors: FieldErrors<{ items: z.infer<typeof pbnstRegZod>[] }>
) => void;
newIndexMng:number
}) {
const { t } = useTranslation("base");
//TODO: 유즈 스테이트에 set만해도 되나?
const [, setCurrentTab] = useState<string>("mng");
const [indexMng, setIndexMng] = useState<number>(0);
const [indexMng, setIndexMng] = useState<number>(newIndexMng);
const [indexBiz, setIndexBiz] = useState<number>(0);
const onSubmit = async (valuse: { items: PbnstRegArrrayType }) => {
@@ -59,12 +61,8 @@ export function PbnstRegModal({
console.log("form errors:", form.formState.errors);
}, [form.formState.errors]);
useEffect(() => {
const firstForm = form.getValues("items");
if (firstForm) {
setIndexMng(firstForm.length - 1);
}
}, [form]);
return (
<>
<h1 className="text-2xl font-medium text-label pl-8">

Some files were not shown because too many files have changed in this diff Show More