Merge commit 'c9169772922b9ad3046b894b4375f3983779a1bd'
This commit is contained in:
@@ -1,237 +1,43 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { regionData, regionIdMap } from '@/app/common/comFunction';
|
||||||
|
import { useDmStore } from '@/app/store';
|
||||||
|
import type { DmStatusDataType } from '@/app/store/wrStatus/type';
|
||||||
import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components';
|
import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components';
|
||||||
import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react';
|
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
||||||
|
|
||||||
interface RegionData {
|
|
||||||
name: string;
|
interface WrStatusChartProps {
|
||||||
x: number;
|
chartForm: string;
|
||||||
y: number;
|
chartConfig: ChartConfig;
|
||||||
values: number[];
|
chartData: any;
|
||||||
|
chartTitle: string;
|
||||||
|
chartClassName?: string;
|
||||||
|
graphSize?: number;
|
||||||
|
yFieldText? : string | undefined;
|
||||||
|
yFieldText2? : string | undefined;
|
||||||
|
showLegend? : boolean;
|
||||||
|
setXAxisYearTick ?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TableData {
|
export default function WrStatusPage() {
|
||||||
region: string;
|
|
||||||
sewage: string;
|
|
||||||
rainwater: string;
|
|
||||||
reclaimed: string;
|
|
||||||
thermal: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const { dmStatus, getDmStatusData} = useDmStore((state) => state);
|
||||||
const WrStatusPage: React.FC = () => {
|
const { statusData,facilityTotals ,chartData} = dmStatus;
|
||||||
const [selectedRegion, setSelectedRegion] = useState<string | null>(null);
|
const [selectedRegion, setSelectedRegion] = useState<string | null>(null);
|
||||||
const [hoveredRegion, setHoveredRegion] = useState<string | null>(null);
|
const [hoveredRegion, setHoveredRegion] = useState<string | null>(null);
|
||||||
const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null);
|
const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null);
|
||||||
|
const [chartOption, setChartOption] = useState<WrStatusChartProps>({} as WrStatusChartProps)
|
||||||
const svgContainerRef = useRef<HTMLDivElement>(null);
|
const svgContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const [chartData] = useState<any[]>([
|
|
||||||
{
|
|
||||||
label : '서울',
|
|
||||||
하수 : 4,
|
|
||||||
빗물 : 816,
|
|
||||||
중수도 : 371,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '부산',
|
|
||||||
하수 : 13,
|
|
||||||
빗물 : 68,
|
|
||||||
중수도 : 20,
|
|
||||||
온배수 : 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '대구',
|
|
||||||
하수 : 9,
|
|
||||||
빗물 : 294,
|
|
||||||
중수도 : 14,
|
|
||||||
온배수 : 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '인천',
|
|
||||||
하수 : 17,
|
|
||||||
빗물 : 165,
|
|
||||||
중수도 : 35,
|
|
||||||
온배수 : 15
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '광주',
|
|
||||||
하수 : 3,
|
|
||||||
빗물 : 74,
|
|
||||||
중수도 : 15,
|
|
||||||
온배수 : 15
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '대전',
|
|
||||||
하수 : 2,
|
|
||||||
빗물 : 52,
|
|
||||||
중수도 : 11,
|
|
||||||
온배수 : 20
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '울산',
|
|
||||||
하수 : 8,
|
|
||||||
빗물 : 111,
|
|
||||||
중수도 : 19,
|
|
||||||
온배수 : 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '세종',
|
|
||||||
하수 : 9,
|
|
||||||
빗물 : 65,
|
|
||||||
중수도 : 0,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '경기',
|
|
||||||
하수 : 176,
|
|
||||||
빗물 : 1009,
|
|
||||||
중수도 : 252,
|
|
||||||
온배수 : 40
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '강원',
|
|
||||||
하수 : 69,
|
|
||||||
빗물 : 69,
|
|
||||||
중수도 : 22,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '충북',
|
|
||||||
하수 : 38,
|
|
||||||
빗물 : 17,
|
|
||||||
중수도 : 91,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '충남',
|
|
||||||
하수 : 67,
|
|
||||||
빗물 : 54,
|
|
||||||
중수도 : 188,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '전북',
|
|
||||||
하수 : 55,
|
|
||||||
빗물 : 33,
|
|
||||||
중수도 : 220,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '전남',
|
|
||||||
하수 : 83,
|
|
||||||
빗물 : 16,
|
|
||||||
중수도 : 75,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '경북',
|
|
||||||
하수 : 81,
|
|
||||||
빗물 : 37,
|
|
||||||
중수도 : 70,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '경남',
|
|
||||||
하수 : 75,
|
|
||||||
빗물 : 27,
|
|
||||||
중수도 : 140,
|
|
||||||
온배수 : 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label : '제주',
|
|
||||||
하수 : 8,
|
|
||||||
빗물 : 47,
|
|
||||||
중수도 : 64,
|
|
||||||
온배수 : 0
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
const chartConfig = chartData.reduce((config, element) => {
|
|
||||||
config[element.label] = {
|
|
||||||
label: element.label,
|
|
||||||
color : "hsl(var(--chart-1))"
|
|
||||||
};
|
|
||||||
return config;
|
|
||||||
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
|
||||||
|
|
||||||
const chartOption = {
|
|
||||||
chartForm : CHART_FORM.BAR,
|
|
||||||
chartConfig : chartConfig,
|
|
||||||
chartData : chartData,
|
|
||||||
chartTitle : '',
|
|
||||||
chartClassName : "h-[300px] w-full",
|
|
||||||
graphSize : 40,
|
|
||||||
yFieldText : '시설(개소)',
|
|
||||||
showLegend : true
|
|
||||||
}
|
|
||||||
|
|
||||||
const colorLegend = [
|
const colorLegend = [
|
||||||
{ label: '하수', color: '#FF6B6B', key: 'sewage' },
|
{ label: '하수', color: '#FF6B6B', key: 'sewage' },
|
||||||
{ label: '빗물', color: '#4ECDC4', key: 'rainwater' },
|
{ label: '빗물', color: '#4ECDC4', key: 'rainwater' },
|
||||||
{ label: '중수도', color: '#45B7D1', key: 'reclaimed' },
|
{ label: '중수도', color: '#45B7D1', key: 'reclaimed' },
|
||||||
{ label: '온배수', color: '#FED16A', key: 'thermal' },
|
{ label: '온배수', color: '#FED16A', key: 'thermal' },
|
||||||
];
|
];
|
||||||
|
const facilityTotalsColor = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
|
||||||
|
|
||||||
const regionIdMap: Record<string, string> = {
|
|
||||||
서울: '서울특별시',
|
|
||||||
부산: '부산광역시',
|
|
||||||
대구: '대구광역시',
|
|
||||||
인천: '인천광역시',
|
|
||||||
광주: '광주광역시',
|
|
||||||
대전: '대전광역시',
|
|
||||||
울산: '울산광역시',
|
|
||||||
세종: '세종특별자치시',
|
|
||||||
경기: '경기도',
|
|
||||||
강원: '강원특별자치도',
|
|
||||||
충북: '충청북도',
|
|
||||||
충남: '충청남도',
|
|
||||||
전북: '전라북도',
|
|
||||||
전남: '전라남도',
|
|
||||||
경북: '경상북도',
|
|
||||||
경남: '경상남도',
|
|
||||||
제주: '제주특별자치도'
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableData: TableData[] = [
|
|
||||||
{ region: '전국', sewage: '717(1,137,538)', rainwater: '3544(13,945)', reclaimed: '1018(222,476)', thermal: '123(492)' },
|
|
||||||
{ region: '서울특별시', sewage: '4(114,908)', rainwater: '816(430)', reclaimed: '371(341)', thermal: '0' },
|
|
||||||
{ region: '부산광역시', sewage: '13(146,197)', rainwater: '68(335)', reclaimed: '20(512)', thermal: '1(18)' },
|
|
||||||
{ region: '대구광역시', sewage: '9(102,380)', rainwater: '294(133)', reclaimed: '14(44)', thermal: '2(12)' },
|
|
||||||
{ region: '인천광역시', sewage: '17(57,691)', rainwater: '165(642)', reclaimed: '35(7,859)', thermal: '15(32)' },
|
|
||||||
{ region: '광주광역시', sewage: '3(28,738)', rainwater: '74(23)', reclaimed: '15(450)', thermal: '15(6)' },
|
|
||||||
{ region: '대전광역시', sewage: '2(11,966)', rainwater: '52(2)', reclaimed: '11(492)', thermal: '20(100)' },
|
|
||||||
{ region: '울산광역시', sewage: '8(36,076)', rainwater: '111(39)', reclaimed: '19(28,904)', thermal: '30(130)' },
|
|
||||||
{ region: '세종특별자치시', sewage: '9(2,555)', rainwater: '65(16)', reclaimed: '0(0)', thermal: '0' },
|
|
||||||
{ region: '경기도', sewage: '176(313,298)', rainwater: '1009(4,735)', reclaimed: '252(77,096)', thermal: '40(143)' },
|
|
||||||
{ region: '강원특별자치도', sewage: '69(19,677)', rainwater: '69(4)', reclaimed: '22(447)', thermal: '0' },
|
|
||||||
{ region: '충청북도', sewage: '38(15,607)', rainwater: '17(91)', reclaimed: '91(2,211)', thermal: '0' },
|
|
||||||
{ region: '충청남도', sewage: '67(41,368)', rainwater: '54(77)', reclaimed: '188(50,434)', thermal: '0' },
|
|
||||||
{ region: '전라북도', sewage: '55(42,671)', rainwater: '33(199)', reclaimed: '220(9,453)', thermal: '0' },
|
|
||||||
{ region: '전라남도', sewage: '83(23,560)', rainwater: '16(885)', reclaimed: '75(15,412)', thermal: '0' },
|
|
||||||
{ region: '경상북도', sewage: '81(129,081)', rainwater: '37(341)', reclaimed: '70(27,818)', thermal: '0' },
|
|
||||||
{ region: '경상남도', sewage: '75(50,101)', rainwater: '27(244)', reclaimed: '140(343)', thermal: '0' },
|
|
||||||
{ region: '제주특별자치도', sewage: '8(1,666)', rainwater: '47(5,746)', reclaimed: '64(660)', thermal: '0' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const regionData: RegionData[] = useMemo(() => [
|
|
||||||
{ name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
{ name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] },
|
|
||||||
], []);
|
|
||||||
|
|
||||||
const handleMarkerClick = (regionId: string) => {
|
const handleMarkerClick = (regionId: string) => {
|
||||||
if (selectedRegion === regionId) {
|
if (selectedRegion === regionId) {
|
||||||
@@ -241,7 +47,6 @@ const WrStatusPage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const createDonutMarker = useCallback((svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => {
|
const createDonutMarker = useCallback((svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => {
|
||||||
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
|
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A'];
|
||||||
const radius = 26;
|
const radius = 26;
|
||||||
@@ -252,7 +57,6 @@ const WrStatusPage: React.FC = () => {
|
|||||||
console.warn(`Invalid region name: ${name}`);
|
console.warn(`Invalid region name: ${name}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
g.setAttribute('transform', `translate(${x}, ${y})`);
|
g.setAttribute('transform', `translate(${x}, ${y})`);
|
||||||
g.setAttribute('id', `marker-${name}`);
|
g.setAttribute('id', `marker-${name}`);
|
||||||
@@ -336,6 +140,13 @@ const WrStatusPage: React.FC = () => {
|
|||||||
svg.appendChild(g);
|
svg.appendChild(g);
|
||||||
}, [handleMarkerClick, regionIdMap]);
|
}, [handleMarkerClick, regionIdMap]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDmStatusData('2023');
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadSVG = async () => {
|
const loadSVG = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -393,6 +204,31 @@ const WrStatusPage: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [selectedRegion]);
|
}, [selectedRegion]);
|
||||||
|
useEffect(() => {
|
||||||
|
if(chartData.length>0){
|
||||||
|
const chartConfig = chartData.reduce((config, element) => {
|
||||||
|
config[element.label] = {
|
||||||
|
label: element.label,
|
||||||
|
color : "hsl(var(--chart-1))"
|
||||||
|
};
|
||||||
|
return config;
|
||||||
|
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
||||||
|
|
||||||
|
const Option = {
|
||||||
|
chartForm : CHART_FORM.BAR,
|
||||||
|
chartConfig : chartConfig,
|
||||||
|
chartData : chartData,
|
||||||
|
chartTitle : '',
|
||||||
|
chartClassName : "h-[300px] w-full",
|
||||||
|
graphSize : 40,
|
||||||
|
yFieldText : '시설(개소)',
|
||||||
|
showLegend : true
|
||||||
|
}
|
||||||
|
setChartOption(Option)
|
||||||
|
}else{
|
||||||
|
setChartOption({} as WrStatusChartProps)
|
||||||
|
}
|
||||||
|
}, [chartData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen bg-[#F2F2F2] text-gray-800">
|
<div className="flex h-screen bg-[#F2F2F2] text-gray-800">
|
||||||
@@ -401,7 +237,6 @@ const WrStatusPage: React.FC = () => {
|
|||||||
{/* 상단 제목 */}
|
{/* 상단 제목 */}
|
||||||
<div className="mb-6 flex justify-between items-center">
|
<div className="mb-6 flex justify-between items-center">
|
||||||
<h2 className="text-2xl font-bold">물재이용 현황</h2>
|
<h2 className="text-2xl font-bold">물재이용 현황</h2>
|
||||||
<div className="text-sm text-gray-500">관리자 ▼</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 콘텐츠 본문 */}
|
{/* 콘텐츠 본문 */}
|
||||||
@@ -439,11 +274,11 @@ const WrStatusPage: React.FC = () => {
|
|||||||
<div className="font-semibold mb-1">{hoveredRegion}</div>
|
<div className="font-semibold mb-1">{hoveredRegion}</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{colorLegend.map(({ label, color, key }) => (
|
{colorLegend.map(({ label, color, key }) => (
|
||||||
<div key={key} className="flex items-center space-x-2">
|
<div key={key+'' +color} className="flex items-center space-x-2">
|
||||||
<span className="text-[12px] inline-block w-3 h-3 rounded-sm" style={{ backgroundColor: color }}></span>
|
<span className="text-[12px] inline-block w-3 h-3 rounded-sm" style={{ backgroundColor: color }}></span>
|
||||||
<span className="text-[12px]">
|
<span className="text-[12px]">
|
||||||
{label}:{' '}
|
{label}:{' '}
|
||||||
{tableData.find(d => d.region === hoveredRegion)?.[key as keyof TableData] ?? '-'}
|
{statusData?.find(d => d.region === hoveredRegion)?.[key as keyof DmStatusDataType] || '-'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -453,22 +288,12 @@ const WrStatusPage: React.FC = () => {
|
|||||||
|
|
||||||
{/* 범례 */}
|
{/* 범례 */}
|
||||||
<div className="absolute bottom-2 right-2 bg-white rounded-lg shadow-md p-4 text-sm space-y-2">
|
<div className="absolute bottom-2 right-2 bg-white rounded-lg shadow-md p-4 text-sm space-y-2">
|
||||||
<div className="flex items-center space-x-2">
|
{facilityTotals?.map((item, index) => (
|
||||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#FF6B6B'}}></span>
|
<div key ={'fcltTotal' +index}className="flex items-center space-x-2">
|
||||||
<span className="text-[12px] text-gray-900">하수재이용시설 (총 717개소)</span>
|
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor:facilityTotalsColor[index]}}></span>
|
||||||
</div>
|
<span className="text-[12px] text-gray-900">{item}</span>
|
||||||
<div className="flex items-center space-x-2">
|
</div>
|
||||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#4ECDC4'}}></span>
|
)) }
|
||||||
<span className="text-[12px] text-gray-900">빗물이용시설 (총 3,730개소)</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#45B7D1'}}></span>
|
|
||||||
<span className="text-[12px] text-gray-900">중수도시설 (총 1,074개소)</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<span className="inline-block w-4 h-4 rounded-sm" style={{backgroundColor: '#FED16A'}}></span>
|
|
||||||
<span className="text-[12px] text-gray-900">온배수시설 (총 201개소)</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -479,10 +304,10 @@ const WrStatusPage: React.FC = () => {
|
|||||||
{/* 재이용시설현황 표 */}
|
{/* 재이용시설현황 표 */}
|
||||||
<div className="bg-white rounded-xl shadow border border-[#DBE2E6] overflow-hidden">
|
<div className="bg-white rounded-xl shadow border border-[#DBE2E6] overflow-hidden">
|
||||||
{/* 타이틀 + 버튼 영역 */}
|
{/* 타이틀 + 버튼 영역 */}
|
||||||
<div className="flex justify-between items-center border-b border-[#DBE2E6] px-4 py-3">
|
<div className="flex justify-between items-center border-b border-[#436d85] px-4 py-3">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-[12px] font-semibold">재이용시설현황(2023)</h3>
|
<h3 className="text-[12px] font-semibold">재이용시설현황(2023)</h3>
|
||||||
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설현황(개소)</p>
|
<p className="text-[12px] text-[#999] font-medium">행정구역별 재이용시설현황[개소(천m³/년)]</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
@@ -493,14 +318,18 @@ const WrStatusPage: React.FC = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">번호</th>
|
<th className="text-[12px] font-semibold px-4 py-2">번호</th>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">시도</th>
|
<th className="text-[12px] font-semibold px-4 py-2">시도</th>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">하수(이용량,천𝓂³/년)</th>
|
<th className="text-[12px] font-semibold px-4 py-2">하수재이용시설</th>
|
||||||
|
<th className="text-[12px] font-semibold px-4 py-2">빗물이용시설</th>
|
||||||
|
<th className="text-[12px] font-semibold px-4 py-2">중수도시설</th>
|
||||||
|
<th className="text-[12px] font-semibold px-4 py-2">온배수시설</th>
|
||||||
|
{/* <th className="text-[12px] font-semibold px-4 py-2">하수(이용량,천𝓂³/년)</th>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">빗물(이용량,천𝓂³/년)</th>
|
<th className="text-[12px] font-semibold px-4 py-2">빗물(이용량,천𝓂³/년)</th>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">중수도(이용량,천𝓂³/년)</th>
|
<th className="text-[12px] font-semibold px-4 py-2">중수도(이용량,천𝓂³/년)</th>
|
||||||
<th className="text-[12px] font-semibold px-4 py-2">온배수(이용량,천𝓂³/년)</th>
|
<th className="text-[12px] font-semibold px-4 py-2">온배수(이용량,천𝓂³/년)</th> */}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y">
|
<tbody className="divide-y">
|
||||||
{tableData.map((row, index) => (
|
{statusData?.map((row, index) => (
|
||||||
<tr key={index} className="hover:bg-gray-50">
|
<tr key={index} className="hover:bg-gray-50">
|
||||||
<td className="text-[12px] px-4 py-2 text-center">
|
<td className="text-[12px] px-4 py-2 text-center">
|
||||||
{index+1}
|
{index+1}
|
||||||
@@ -526,16 +355,18 @@ const WrStatusPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-[#f9fbfd]">
|
<div className="p-4 bg-[#f9fbfd]">
|
||||||
<div className="h-[305px] text-gray-500">
|
<div className="h-[305px] text-gray-500">
|
||||||
<MainChart
|
{chartOption?
|
||||||
chartForm={chartOption.chartForm}
|
<MainChart
|
||||||
chartConfig={chartOption.chartConfig}
|
chartForm={chartOption.chartForm}
|
||||||
chartData={chartOption.chartData}
|
chartConfig={chartOption.chartConfig}
|
||||||
chartTitle={chartOption.chartTitle}
|
chartData={chartOption.chartData}
|
||||||
chartClassName={chartOption.chartClassName}
|
chartTitle={chartOption.chartTitle}
|
||||||
graphSize={chartOption.graphSize}
|
chartClassName={chartOption.chartClassName}
|
||||||
yFieldText={chartOption.yFieldText}
|
graphSize={chartOption.graphSize}
|
||||||
showLegend={chartOption.showLegend}
|
yFieldText={chartOption.yFieldText}
|
||||||
/>
|
showLegend={chartOption.showLegend}
|
||||||
|
/>
|
||||||
|
:<></>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -545,5 +376,3 @@ const WrStatusPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WrStatusPage;
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import type { DmStatusChartType, DmStatusDataType, RegionData, } from "../store/wrStatus/type";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const regionData:RegionData[] = [
|
||||||
|
{ name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '강원', x: 330, y: 120, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '충북', x: 260, y: 280, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '충남', x: 100, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '세종', x: 180, y: 305, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '대전', x: 195, y: 360, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '전북', x: 170, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '전남', x: 160, y: 600, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '광주', x: 120, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '경북', x: 400, y: 320, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '경남', x: 310, y: 530, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '대구', x: 350, y: 450, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
{ name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const regionIdMap: Record<string, string> = {
|
||||||
|
서울: '서울특별시',
|
||||||
|
부산: '부산광역시',
|
||||||
|
대구: '대구광역시',
|
||||||
|
인천: '인천광역시',
|
||||||
|
광주: '광주광역시',
|
||||||
|
대전: '대전광역시',
|
||||||
|
울산: '울산광역시',
|
||||||
|
세종: '세종특별자치시',
|
||||||
|
경기: '경기도',
|
||||||
|
강원: '강원특별자치도',
|
||||||
|
충북: '충청북도',
|
||||||
|
충남: '충청남도',
|
||||||
|
전북: '전라북도',
|
||||||
|
전남: '전라남도',
|
||||||
|
경북: '경상북도',
|
||||||
|
경남: '경상남도',
|
||||||
|
제주: '제주특별자치도'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const makeRegion = (region: string) => {
|
||||||
|
if (region === '서울특별시') return '서울'
|
||||||
|
if (region === '부산광역시') return '부산'
|
||||||
|
if (region === '대구광역시') return '대구'
|
||||||
|
if (region === '인천광역시') return '인천'
|
||||||
|
if (region === '광주광역시') return '광주'
|
||||||
|
if (region === '대전광역시') return '대전'
|
||||||
|
if (region === '울산광역시') return '울산'
|
||||||
|
if (region === '세종특별자치시') return '세종'
|
||||||
|
if (region === '경기도') return '경기'
|
||||||
|
if (region === '강원특별자치도') return '강원'
|
||||||
|
if (region === '충청북도') return '충북'
|
||||||
|
if (region === '충청남도') return '충남'
|
||||||
|
if (region === '전라북도') return '전북'
|
||||||
|
if (region === '전라남도') return '전남'
|
||||||
|
if (region === '경상북도') return '경북'
|
||||||
|
if (region === '경상남도') return '경남'
|
||||||
|
if (region === '제주특별자치도') return '제주'
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
export const changeStatusMapData= (data: DmStatusDataType[]) : DmStatusChartType[]=> {
|
||||||
|
return data.map((item) => ({
|
||||||
|
label: makeRegion(item.region??''),
|
||||||
|
하수: item.sewage.split('(')[0]??'',
|
||||||
|
빗물: item.rainwater.split('(')[0]??'',
|
||||||
|
중수도: item.reclaimed.split('(')[0] ??'',
|
||||||
|
온배수: item.thermal.split('(')[0] ??'',
|
||||||
|
}));
|
||||||
|
}
|
||||||
+38
-19
@@ -1,29 +1,48 @@
|
|||||||
import { createStore } from 'zustand/vanilla';
|
import { createStore } from "zustand/vanilla";
|
||||||
import { CommonReducer, CommonState, type CommonStore, type CommonType } from './common';
|
import {
|
||||||
import { SdmReducer, SdmState, type SdmStore, type SdmType } from './sdmMng';
|
CommonReducer,
|
||||||
import { dmMapState, type DmMapType, type DmMapStore, DmMapReducer } from './map';
|
CommonState,
|
||||||
import { tokenManager } from '@/src/entities/auth/lib/token-manager';
|
type CommonStore,
|
||||||
|
type CommonType,
|
||||||
|
} from "./common";
|
||||||
|
import { SdmReducer, SdmState, type SdmStore, type SdmType } from "./sdmMng";
|
||||||
|
import {
|
||||||
|
dmMapState,
|
||||||
|
type DmMapType,
|
||||||
|
type DmMapStore,
|
||||||
|
DmMapReducer,
|
||||||
|
} from "./map";
|
||||||
|
import { tokenManager } from "@/src/entities/auth/lib/token-manager";
|
||||||
|
import {
|
||||||
|
DmStatusReducer,
|
||||||
|
dmStatusState,
|
||||||
|
type DmStatusStore,
|
||||||
|
type DmStatusType,
|
||||||
|
} from "./wrStatus";
|
||||||
|
|
||||||
export type DmStore = CommonStore & SdmStore &DmMapStore ;
|
export type DmStore = CommonStore & SdmStore & DmMapStore & DmStatusStore;
|
||||||
export type DmState = CommonType & SdmType &DmMapType;
|
export type DmState = CommonType & SdmType & DmMapType & DmStatusType;
|
||||||
|
|
||||||
export const StoreZus = (initState: DmState= {
|
export const StoreZus = (
|
||||||
...CommonState,
|
initState: DmState = {
|
||||||
...SdmState,
|
...CommonState,
|
||||||
...dmMapState,
|
...SdmState,
|
||||||
}) => {
|
...dmMapState,
|
||||||
|
...dmStatusState,
|
||||||
|
}
|
||||||
|
) => {
|
||||||
return createStore<DmStore>()((set) => {
|
return createStore<DmStore>()((set) => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
tokenManager.setToken("site-id-key", 'DM');
|
tokenManager.setToken("site-id-key", "DM");
|
||||||
tokenManager.setToken("site-theme-key", 'green');
|
tokenManager.setToken("site-theme-key", "green");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...initState,
|
...initState,
|
||||||
...CommonReducer(set),
|
...CommonReducer(set),
|
||||||
...SdmReducer(set),
|
...SdmReducer(set),
|
||||||
...DmMapReducer(set)
|
...DmMapReducer(set),
|
||||||
}
|
...DmStatusReducer(set),
|
||||||
})
|
};
|
||||||
}
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { changeStatusMapData } from "@/app/common/comFunction";
|
||||||
|
import { fetchType, getFetch } from "@/components/ui/api";
|
||||||
|
import type {
|
||||||
|
DmStatusDataType,
|
||||||
|
DmStatusChartType,
|
||||||
|
} from "./type";
|
||||||
|
|
||||||
|
export type DmStatusActions = {
|
||||||
|
getDmStatusData(year: string): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DmStatusType = {
|
||||||
|
dmStatus: {
|
||||||
|
statusData: DmStatusDataType[];
|
||||||
|
facilityTotals: string[];
|
||||||
|
chartData: DmStatusChartType[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dmStatusState: DmStatusType = {
|
||||||
|
dmStatus: {
|
||||||
|
statusData: [],
|
||||||
|
facilityTotals: [],
|
||||||
|
chartData: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export type DmStatusStore = DmStatusType & DmStatusActions;
|
||||||
|
|
||||||
|
export const DmStatusReducer = (set: any): DmStatusActions => {
|
||||||
|
return {
|
||||||
|
getDmStatusData: async (year: string) => {
|
||||||
|
const data = await getFetch(fetchType.WR, "/daemin/" + year);
|
||||||
|
let isData:DmStatusDataType[] =[]
|
||||||
|
if(data.data&&data.data.length>0){
|
||||||
|
isData=data.data
|
||||||
|
}else{
|
||||||
|
fetch(`data/wrStatusData.json`).then((res) => res.json()).then((json) => isData=json)//만약 백엔드에서 못가져올경우 방어책
|
||||||
|
}
|
||||||
|
|
||||||
|
const orgin: DmStatusDataType[] = isData;
|
||||||
|
const chartData = changeStatusMapData(orgin);
|
||||||
|
const facilityTotals = [
|
||||||
|
"하수재이용시설" + "(총" + orgin[0]?.sewage.split("(")[0] + "개소)",
|
||||||
|
"빗물재이용시설" + "(총" + orgin[0]?.rainwater.split("(")[0] + "개소)",
|
||||||
|
"중수도재이용시설" +
|
||||||
|
"(총" +
|
||||||
|
orgin[0]?.reclaimed.split("(")[0] +
|
||||||
|
"개소)",
|
||||||
|
"온배수재이용시설" + "(총" + orgin[0]?.thermal.split("(")[0] + "개소)",
|
||||||
|
];
|
||||||
|
|
||||||
|
set((state: DmStatusType) => ({
|
||||||
|
...state,
|
||||||
|
dmStatus: {
|
||||||
|
...state.dmStatus,
|
||||||
|
statusData: data.data,
|
||||||
|
chartData: chartData,
|
||||||
|
facilityTotals: facilityTotals,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
export type DmStatusDataType = {
|
||||||
|
region: string;
|
||||||
|
sewage: string;
|
||||||
|
rainwater: string;
|
||||||
|
reclaimed: string;
|
||||||
|
thermal: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type DmStatusFcltType = {
|
||||||
|
sewageFclt: string;
|
||||||
|
rainwaterFclt: string;
|
||||||
|
reclaimedFclt: string;
|
||||||
|
thermalFclt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export type DmStatusChartType = {
|
||||||
|
label: string,
|
||||||
|
하수: string,
|
||||||
|
빗물: string,
|
||||||
|
중수도: string,
|
||||||
|
온배수: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RegionData = {
|
||||||
|
name: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
values: number[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{ "region": "전국", "sewage": "717(1,137,538)", "rainwater": "3544(13,945)", "reclaimed": "1018(222,476)", "thermal": "123(492)" },
|
||||||
|
{ "region": "서울특별시", "sewage": "4(114,908)", "rainwater": "816(430)", "reclaimed": "371(341)", "thermal": "0" },
|
||||||
|
{ "region": "부산광역시", "sewage": "13(146,197)", "rainwater": "68(335)", "reclaimed": "20(512)", "thermal": "1(18)" },
|
||||||
|
{ "region": "대구광역시", "sewage": "9(102,380)", "rainwater": "294(133)", "reclaimed": "14(44)", "thermal": "2(12)" },
|
||||||
|
{ "region": "인천광역시", "sewage": "17(57,691)", "rainwater": "165(642)", "reclaimed": "35(7,859)", "thermal": "15(32)" },
|
||||||
|
{ "region": "광주광역시", "sewage": "3(28,738)", "rainwater": "74(23)", "reclaimed": "15(450)", "thermal": "15(6)" },
|
||||||
|
{ "region": "대전광역시", "sewage": "2(11,966)", "rainwater": "52(2)", "reclaimed": "11(492)", "thermal": "20(100)" },
|
||||||
|
{ "region": "울산광역시", "sewage": "8(36,076)", "rainwater": "111(39)", "reclaimed": "19(28,904)", "thermal": "30(130)" },
|
||||||
|
{ "region": "세종특별자치시", "sewage": "9(2,555)", "rainwater": "65(16)", "reclaimed": "0(0)", "thermal": "0" },
|
||||||
|
{ "region": "경기도", "sewage": "176(313,298)", "rainwater": "1009(4,735)", "reclaimed": "252(77,096)", "thermal": "40(143)" },
|
||||||
|
{ "region": "강원특별자치도", "sewage": "69(19,677)", "rainwater": "69(4)", "reclaimed": "22(447)", "thermal": "0" },
|
||||||
|
{ "region": "충청북도", "sewage": "38(15,607)", "rainwater": "17(91)", "reclaimed": "91(2,211)", "thermal": "0" },
|
||||||
|
{ "region": "충청남도", "sewage": "67(41,368)", "rainwater": "54(77)", "reclaimed": "188(50,434)", "thermal": "0" },
|
||||||
|
{ "region": "전라북도", "sewage": "55(42,671)", "rainwater": "33(199)", "reclaimed": "220(9,453)", "thermal": "0" },
|
||||||
|
{ "region": "전라남도", "sewage": "83(23,560)", "rainwater": "16(885)", "reclaimed": "75(15,412)", "thermal": "0" },
|
||||||
|
{ "region": "경상북도", "sewage": "81(129,081)", "rainwater": "37(341)", "reclaimed": "70(27,818)", "thermal": "0" },
|
||||||
|
{ "region": "경상남도", "sewage": "75(50,101)", "rainwater": "27(244)", "reclaimed": "140(343)", "thermal": "0" },
|
||||||
|
{ "region": "제주특별자치도", "sewage": "8(1,666)", "rainwater": "47(5,746)", "reclaimed": "64(660)", "thermal": "0" }
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user