Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend
This commit is contained in:
@@ -3,7 +3,7 @@ import { client } from "@/shared/api";
|
||||
import { create } from "zustand";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type { PplLengthContent, SewerageService } from "../model/sn-interface";
|
||||
import type { OldPplChartData,mapPplOldType,mapPplOldItem } from "../model/sn-interface";
|
||||
import type { OldPplChartData, mapPplOldType, mapPplOldItem } from "../model/sn-interface";
|
||||
|
||||
export type SnState = {
|
||||
snStatus: PplLengthContent[] | null;
|
||||
@@ -13,48 +13,48 @@ export type SnStateActions = {
|
||||
};
|
||||
export type SnStore = SnState & SnStateActions;
|
||||
|
||||
const initialUsePplChartData: OldPplChartData={
|
||||
"labels": ["금강","한강","낙동강", "영산강"],
|
||||
"datasets": [
|
||||
{
|
||||
"label": "기타",
|
||||
"data": [1966,15480,6957,1936],
|
||||
"backgroundColor": "rgba(255, 178, 150, 0.9)"
|
||||
},
|
||||
{
|
||||
"label": "오수관로",
|
||||
"data": [8074,15879,16337,5671],
|
||||
"backgroundColor": "rgba(180, 240, 190, 0.95)"
|
||||
},
|
||||
{
|
||||
"label": "우수관로",
|
||||
"data": [4838,12893,10492,4281],
|
||||
"backgroundColor": "rgba(170, 210, 245, 0.95)"
|
||||
}
|
||||
]
|
||||
const initialUsePplChartData: OldPplChartData = {
|
||||
labels: ["금강", "한강", "낙동강", "영산강"],
|
||||
datasets: [
|
||||
{
|
||||
label: "기타",
|
||||
data: [1966, 15480, 6957, 1937],
|
||||
backgroundColor: "rgba(255, 178, 150, 0.9)"
|
||||
},
|
||||
{
|
||||
label: "오수관로",
|
||||
data: [8074, 15879, 16337, 5671],
|
||||
backgroundColor: "rgba(180, 240, 190, 0.95)"
|
||||
},
|
||||
{
|
||||
label: "우수관로",
|
||||
data: [4838, 12893, 10492, 4281],
|
||||
backgroundColor: "rgba(170, 210, 245, 0.95)"
|
||||
}
|
||||
]
|
||||
};
|
||||
const initialOldPplChartData: OldPplChartData={
|
||||
labels: ["금강","한강","낙동강","영산강"],
|
||||
datasets: [
|
||||
{
|
||||
label: "20-25년",
|
||||
data: [ 1140,3181,3100,1662],
|
||||
backgroundColor: "#3B82F6",
|
||||
borderRadius: 4
|
||||
},
|
||||
{
|
||||
label: "25-30년",
|
||||
data: [1391, 3615, 1814, 1411],
|
||||
backgroundColor: "#EF4444",
|
||||
borderRadius: 4
|
||||
},
|
||||
{
|
||||
label: "30년이상",
|
||||
data: [ 2014, 10303,9831,2000],
|
||||
backgroundColor: "#F87171",
|
||||
borderRadius: 4
|
||||
}
|
||||
]
|
||||
const initialOldPplChartData: OldPplChartData = {
|
||||
labels: ["금강", "한강", "낙동강", "영산강"],
|
||||
datasets: [
|
||||
{
|
||||
label: "20-25년",
|
||||
data: [1140, 3181, 3100, 1662],
|
||||
backgroundColor: "#3B82F6",
|
||||
borderRadius: 4
|
||||
},
|
||||
{
|
||||
label: "25-30년",
|
||||
data: [1391, 3615, 1814, 1411],
|
||||
backgroundColor: "#EF4444",
|
||||
borderRadius: 4
|
||||
},
|
||||
{
|
||||
label: "30년이상",
|
||||
data: [2014, 10303, 9831, 2000],
|
||||
backgroundColor: "#F87171",
|
||||
borderRadius: 4
|
||||
}
|
||||
]
|
||||
};
|
||||
type OldPplStoreState = {
|
||||
chartData: OldPplChartData;
|
||||
@@ -70,13 +70,13 @@ export const useUsePplStore = create<OldPplStoreState>((set) => ({
|
||||
}));
|
||||
|
||||
export const initailMapOldPplData: mapPplOldType = {
|
||||
colTitle: {totalLen: "총길이",pplLen2025: "20~25년",pplLen2530: "25~30년",pplLen30 : "30년 이상" }, //헤더 영역
|
||||
data: [
|
||||
{name: "금강", totalLen: 4545, pplLen2025: 1140, pplLen2530: 1391, pplLen30 : 2014},
|
||||
{name: "한강", totalLen: 17099, pplLen2025: 3181, pplLen2530: 3615, pplLen30 : 10303},
|
||||
{name: "낙동강", totalLen: 14745, pplLen2025: 3100, pplLen2530: 1814, pplLen30 : 9831},
|
||||
{name: "영산강", totalLen: 5073, pplLen2025: 1662, pplLen2530: 1411, pplLen30 : 2000},
|
||||
]
|
||||
colTitle: { totalLen: "총길이", pplLen2025: "20~25년", pplLen2530: "25~30년", pplLen30: "30년 이상" }, //헤더 영역
|
||||
data: [
|
||||
{ name: "금강", totalLen: 4545, pplLen2025: 1140, pplLen2530: 1391, pplLen30: 2014 },
|
||||
{ name: "한강", totalLen: 17099, pplLen2025: 3181, pplLen2530: 3615, pplLen30: 10303 },
|
||||
{ name: "낙동강", totalLen: 14745, pplLen2025: 3100, pplLen2530: 1814, pplLen30: 9831 },
|
||||
{ name: "영산강", totalLen: 5073, pplLen2025: 1662, pplLen2530: 1411, pplLen30: 2000 },
|
||||
]
|
||||
};
|
||||
type mapPplOldState = {
|
||||
mapData: mapPplOldItem[];
|
||||
@@ -136,7 +136,7 @@ export class SewerageApiService implements SewerageService {
|
||||
...item,
|
||||
sumPrlgVl: Number(item.sumPrlgVl),
|
||||
}));
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -158,6 +158,32 @@ export class SewerageApiService implements SewerageService {
|
||||
}));
|
||||
return list;
|
||||
}
|
||||
|
||||
// 유역별 용도별 관로 길이(km) MV조회 : usgCd - SBA004 오수관, SBA003 우수관
|
||||
public async getMvUsgPplLength(): Promise<PplLengthContent[]> {
|
||||
const response = await client.get<{
|
||||
PplLengthList: PplLengthContent[];
|
||||
}>(ENDPOINT.SEWERAGE_SERVICE.MV_USG_PPL_LENGTH);
|
||||
|
||||
const list = (response.data.PplLengthList ?? []).map((item) => ({
|
||||
...item,
|
||||
sumPrlgVl: Number(item.sumPrlgVl),
|
||||
}));
|
||||
return list;
|
||||
}
|
||||
// 유역별 노후도별 관로 길이(km) MV조회 : yearGroup - 20년~25년미만,25년~30년미만,30년이상
|
||||
public async getMvOldPplLength(): Promise<PplLengthContent[]> {
|
||||
const response = await client.get<{
|
||||
PplLengthList: PplLengthContent[];
|
||||
}>(ENDPOINT.SEWERAGE_SERVICE.MV_OLD_PPL_LENGTH);
|
||||
|
||||
const list = (response.data.PplLengthList ?? []).map((item) => ({
|
||||
...item,
|
||||
sumPrlgVl: Number(item.sumPrlgVl),
|
||||
}));
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const SewerageApi = new SewerageApiService();
|
||||
|
||||
@@ -2,11 +2,15 @@ import { basinKeyMap } from "../model/map-data";
|
||||
export interface PplLengthContent {
|
||||
zoneNm: string;
|
||||
sumPrlgVl: number;
|
||||
usgCd?: string;
|
||||
yearGroup?: string;
|
||||
}
|
||||
|
||||
export interface SewerageService {
|
||||
getPplLength(ymdFrom: string, ymdTo: string, useCd: string): Promise<PplLengthContent[]>;
|
||||
getPplUseLength(ymdFrom: string, ymdTo: string, useCd: string): Promise<PplLengthContent[]>;
|
||||
getMvUsgPplLength(): Promise<PplLengthContent[]>;
|
||||
getMvOldPplLength(): Promise<PplLengthContent[]>;
|
||||
}
|
||||
|
||||
export interface ChartDataSet {
|
||||
@@ -39,11 +43,11 @@ export type mapPplOldItem = {
|
||||
};
|
||||
|
||||
export type mapPplOldType = {
|
||||
colTitle: {
|
||||
colTitle: {
|
||||
totalLen: string; // 총길이
|
||||
pplLen2025: string; // 20~25년
|
||||
pplLen2530: string; // 25~30년
|
||||
pplLen30 : string; // 30년 이상
|
||||
pplLen30: string; // 30년 이상
|
||||
};
|
||||
data: mapPplOldItem[];
|
||||
};
|
||||
@@ -72,7 +76,7 @@ export function buildSnOldPplLength(
|
||||
colTitle,
|
||||
rows: [
|
||||
total, // 총길이 (undefined면 0)
|
||||
...datasetValues, // 각 연차 데이터 (undefined면 0)
|
||||
...datasetValues, // 각 연차 데이터 (undefined면 0)
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -23,55 +23,56 @@ import { SewerageApi, useOldPplStore,useMapOldPplStore, transformChartDataToMapD
|
||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
|
||||
|
||||
export default function SnOldPpl() {
|
||||
const [oldPpl2025Data, setOldPpl2025Data] = useState<PplLengthContent[]>([]);
|
||||
const [oldPpl2530Data, setOldPpl2530Data] = useState<PplLengthContent[]>([]);
|
||||
const [oldPpl30Data, setOldPpl30Data] = useState<PplLengthContent[]>([]);
|
||||
const [oldPplLenData, setOldPplLenData] = useState<PplLengthContent[]>([]);
|
||||
const {chartData, setChartData} = useOldPplStore();
|
||||
const {setMapData} = useMapOldPplStore();
|
||||
|
||||
useEffect(() => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
const ranges = {
|
||||
"20-25년": { from: `${currentYear - 25 + 1}0101`, to: `${currentYear - 20}1231`, setter: setOldPpl2025Data },
|
||||
"25-30년": { from: `${currentYear - 30 + 1}0101`, to: `${currentYear - 25}1231`, setter: setOldPpl2530Data },
|
||||
"30년이상": { from: "19010101", to: `${currentYear - 30}1231`, setter: setOldPpl30Data },
|
||||
};
|
||||
|
||||
Object.entries(ranges).forEach(([label, range]) => {
|
||||
SewerageApi.getPplLength(range.from, range.to)
|
||||
.then(range.setter)
|
||||
.catch((e) => console.error(`${label} 데이터 조회 실패`, e));
|
||||
});
|
||||
// 유역별, 노후년도별 관로길이 데이터를 한번에 조회
|
||||
SewerageApi.getMvOldPplLength()
|
||||
.then((apiResult) => {
|
||||
setOldPplLenData(apiResult);
|
||||
})
|
||||
.catch((e) => console.error("노후관로 데이터 조회 실패", e));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const allData = [...oldPpl2025Data, ...oldPpl2530Data, ...oldPpl30Data];
|
||||
if (allData.length === 0) return;
|
||||
if (oldPplLenData.length === 0) return;
|
||||
|
||||
const allZones = Array.from(new Set(allData.map(d => d.zoneNm)));
|
||||
// 유역 목록 추출 (중복 제거)
|
||||
const allZones = [...new Set(oldPplLenData.map(d => d.zoneNm))];
|
||||
|
||||
const createDataset = (label: string, data: PplLengthContent[], color: string) => {
|
||||
const dataMap = new Map(data.map(item => [item.zoneNm, item.sumPrlgVl]));
|
||||
// console.log(dataMap);
|
||||
return {
|
||||
label,
|
||||
data: allZones.map(zone => dataMap.get(zone) ?? 0),
|
||||
backgroundColor: color,
|
||||
borderRadius: 4,
|
||||
};
|
||||
// yearGroup 매핑: API 응답값 -> 차트 label
|
||||
const yearGroupMap: { [key: string]: { label: string; color: string } } = {
|
||||
"20년~25년미만": { label: "20-25년", color: "#3B82F6" },
|
||||
"25년~30년미만": { label: "25-30년", color: "#EF4444" },
|
||||
"30년이상": { label: "30년이상", color: "#F87171" },
|
||||
};
|
||||
|
||||
const newDatasets: ChartDataSet[] = [];
|
||||
if (oldPpl2025Data.length > 0) {
|
||||
newDatasets.push(createDataset('20-25년', oldPpl2025Data, '#3B82F6'));
|
||||
}
|
||||
if (oldPpl2530Data.length > 0) {
|
||||
newDatasets.push(createDataset('25-30년', oldPpl2530Data, '#EF4444'));
|
||||
}
|
||||
if (oldPpl30Data.length > 0) {
|
||||
newDatasets.push(createDataset('30년이상', oldPpl30Data, '#F87171'));
|
||||
}
|
||||
// 유역별, 노후년도별 데이터 구조화
|
||||
const dataByZone: { [zone: string]: { [yearGroup: string]: number } } = {};
|
||||
allZones.forEach(zone => {
|
||||
dataByZone[zone] = {};
|
||||
});
|
||||
|
||||
oldPplLenData.forEach(item => {
|
||||
let zoneData = dataByZone[item.zoneNm];
|
||||
if (!zoneData) {
|
||||
zoneData = {};
|
||||
dataByZone[item.zoneNm] = zoneData;
|
||||
}
|
||||
if (item.yearGroup) {
|
||||
zoneData[item.yearGroup] = item.sumPrlgVl;
|
||||
}
|
||||
});
|
||||
|
||||
// 데이터셋 생성
|
||||
const newDatasets: ChartDataSet[] = Object.entries(yearGroupMap).map(([yearGroup, { label, color }]) => ({
|
||||
label,
|
||||
data: allZones.map(zone => dataByZone[zone]?.[yearGroup] ?? 0),
|
||||
backgroundColor: color,
|
||||
borderRadius: 4,
|
||||
}));
|
||||
|
||||
const newChartData: OldPplChartData = {
|
||||
labels: allZones,
|
||||
@@ -82,7 +83,7 @@ export default function SnOldPpl() {
|
||||
|
||||
// 차트 데이터를 기반으로 지도 팝업 데이터 생성 및 상태 업데이트
|
||||
setMapData(transformChartDataToMapData(newChartData));
|
||||
}, [oldPpl2025Data, oldPpl2530Data, oldPpl30Data]);
|
||||
}, [oldPplLenData]);
|
||||
|
||||
// 각 지역별 총 길이 계산
|
||||
const totalLengths = chartData.labels.map((label, i) => {
|
||||
|
||||
@@ -25,81 +25,60 @@ interface ChartDataSet {
|
||||
borderColor?: string;
|
||||
}
|
||||
|
||||
// const usgCd = { "SBA004": "오수관로", "SBA003": "우수관로", "ETC": "기타" }; // 용도
|
||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
|
||||
|
||||
export default function SnPplStatus() {
|
||||
const [sewageData, setSewageData] = useState<PplLengthContent[]>([]);
|
||||
const [stormwaterData, setStormwaterData] = useState<PplLengthContent[]>([]);
|
||||
const [totalData, setTotalData] = useState<PplLengthContent[]>([]);
|
||||
// const [chartData, setChartData] = useState<{
|
||||
// labels: string[];
|
||||
// datasets: ChartDataSet[];
|
||||
// }>({ labels: [], datasets: [] });
|
||||
const {chartData, setChartData} = useUsePplStore();
|
||||
const [usgPplLenData, setUsgPplLenData] = useState<PplLengthContent[]>([]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const ymdFrom = "19010101";
|
||||
const ymdTo = "20241231";
|
||||
|
||||
SewerageApi.getPplUseLength(ymdFrom, ymdTo, "SBA004")
|
||||
// 유역별, 용도별 관로길이 데이터를 한번에 조회
|
||||
SewerageApi.getMvUsgPplLength()
|
||||
.then((apiResult) => {
|
||||
// getPplUseLength의 결과(apiResult)를
|
||||
// setSewageData 함수의 인자로 넣어서 호출합니다.
|
||||
// console.log(apiResult);
|
||||
setSewageData(apiResult);
|
||||
setUsgPplLenData(apiResult);
|
||||
})
|
||||
.catch((e) => console.error("오수관 데이터 조회 실패", e));
|
||||
|
||||
SewerageApi.getPplUseLength(ymdFrom, ymdTo, "SBA003")
|
||||
.then(setStormwaterData)
|
||||
.catch((e) => console.error("우수관 데이터 조회 실패", e));
|
||||
|
||||
SewerageApi.getPplLength(ymdFrom, ymdTo)
|
||||
.then((apiResult) => {
|
||||
// getPplLength 결과(apiResult)를
|
||||
// setTotalData 함수의 인자로 넣어서 호출합니다.
|
||||
// console.log(apiResult);
|
||||
setTotalData(apiResult);
|
||||
})
|
||||
.catch((e) => console.error("전체 관로 데이터 조회 실패", e));
|
||||
.catch((e) => console.error("용도별 관로 데이터 조회 실패", e));
|
||||
}, []);
|
||||
|
||||
// 데이터가 변경될 때마다 차트를 다시 계산
|
||||
useEffect(() => {
|
||||
// 오수관 우수관 두 데이터 모두 없으면 차트를 그리지 않음
|
||||
if (sewageData.length === 0 && stormwaterData.length === 0) return;
|
||||
if (usgPplLenData.length === 0) return;
|
||||
|
||||
const allZones = new Set([
|
||||
...sewageData.map(d => d.zoneNm),
|
||||
...stormwaterData.map(d => d.zoneNm),
|
||||
...totalData.map(d => d.zoneNm)
|
||||
]);
|
||||
const labels = Array.from(allZones);
|
||||
// 유역 목록 추출 (중복 제거)
|
||||
const allZones = [...new Set(usgPplLenData.map(d => d.zoneNm))];
|
||||
const labels = allZones;
|
||||
|
||||
const dataByZone: { [key: string]: { total: number; sewage: number; stormwater: number } } = {};
|
||||
labels.forEach(zone => {dataByZone[zone] = { total: 0, sewage: 0, stormwater: 0 }; });
|
||||
|
||||
totalData.forEach(item => {
|
||||
if (!dataByZone[item.zoneNm]) {
|
||||
dataByZone[item.zoneNm] = { total: 0, sewage: 0, stormwater: 0 };
|
||||
}
|
||||
dataByZone[item.zoneNm]!.total = item.sumPrlgVl;
|
||||
// 유역별, 용도별 데이터 구조화
|
||||
const dataByZone: { [key: string]: { sewage: number; stormwater: number; etc: number } } = {};
|
||||
labels.forEach(zone => {
|
||||
dataByZone[zone] = { sewage: 0, stormwater: 0, etc: 0 };
|
||||
});
|
||||
sewageData.forEach(item => {
|
||||
|
||||
// usgCd별로 데이터 분류: SBA004(오수관로), SBA003(우수관로), ETC(기타)
|
||||
usgPplLenData.forEach(item => {
|
||||
if (!dataByZone[item.zoneNm]) {
|
||||
dataByZone[item.zoneNm] = { total: 0, sewage: 0, stormwater: 0 };
|
||||
dataByZone[item.zoneNm] = { sewage: 0, stormwater: 0, etc: 0 };
|
||||
}
|
||||
dataByZone[item.zoneNm]!.sewage = item.sumPrlgVl;
|
||||
});
|
||||
stormwaterData.forEach(item => {
|
||||
if (!dataByZone[item.zoneNm]) {
|
||||
dataByZone[item.zoneNm] = { total: 0, sewage: 0, stormwater: 0 };
|
||||
if (item.usgCd === "SBA004") {
|
||||
dataByZone[item.zoneNm]!.sewage = item.sumPrlgVl;
|
||||
} else if (item.usgCd === "SBA003") {
|
||||
dataByZone[item.zoneNm]!.stormwater = item.sumPrlgVl;
|
||||
} else if (item.usgCd === "ETC") {
|
||||
dataByZone[item.zoneNm]!.etc = item.sumPrlgVl;
|
||||
}
|
||||
dataByZone[item.zoneNm]!.stormwater = item.sumPrlgVl;
|
||||
});
|
||||
|
||||
const datasets: ChartDataSet[] = [];
|
||||
|
||||
// 기타 데이터셋 (맨 아래에 쌓기 위해 먼저 추가)
|
||||
datasets.push({
|
||||
label: "기타",
|
||||
data: labels.map(zone => dataByZone[zone]?.etc),
|
||||
backgroundColor: "rgba(255, 178, 150, 0.9)",
|
||||
});
|
||||
|
||||
// 오수관로 데이터셋
|
||||
datasets.push({
|
||||
label: "오수관로",
|
||||
@@ -114,21 +93,9 @@ export default function SnPplStatus() {
|
||||
backgroundColor: "rgba(170, 210, 245, 0.95)",
|
||||
});
|
||||
|
||||
// 전체 데이터가 도착했다면 '기타' 데이터셋을 계산하고 추가
|
||||
if (totalData.length > 0) {
|
||||
datasets.unshift({ // '기타'를 맨 아래에 쌓기 위해 unshift 사용
|
||||
label: "기타",
|
||||
data: labels.map(zone => {
|
||||
const zoneData = dataByZone[zone] ?? { total: 0, sewage: 0, stormwater: 0 };
|
||||
return zoneData.total - zoneData.sewage - zoneData.stormwater;
|
||||
}),
|
||||
backgroundColor: "rgba(255, 178, 150, 0.9)",
|
||||
});
|
||||
}
|
||||
|
||||
setChartData({ labels, datasets });
|
||||
|
||||
}, [sewageData, stormwaterData, totalData]);
|
||||
}, [usgPplLenData]);
|
||||
|
||||
// 총합(라벨당) 계산
|
||||
const totals = chartData.labels.map((_, i) =>
|
||||
|
||||
@@ -78,7 +78,9 @@ export const ENDPOINT = {
|
||||
PPL_USE_LENGTH: "/sewerage-service/api/v1/ms/pplUseLength",
|
||||
PPL_COUNTS: "/sewerage-service/api/v1/ms/pplCounts",
|
||||
OLD_PPL_COUNTS: "/sewerage-service/api/v1/ms/oldPplCounts",
|
||||
},
|
||||
MV_USG_PPL_LENGTH: "/sewerage-service/api/v1/ms/mvUsgPplLength",
|
||||
MV_OLD_PPL_LENGTH: "/sewerage-service/api/v1/ms/mvOldPplLength",
|
||||
},
|
||||
OPERATION_SERVICE: {
|
||||
MAIN_YEAR: "/operation-service/api/v1/dashBoard/main/year",
|
||||
OPER_CNTRT: "/operation-service/api/v1/dashBoard/main/oper/cntrt",
|
||||
|
||||
Reference in New Issue
Block a user