+ {item.price.toLocaleString()}원
+
0
diff --git a/src/components/product/detail/building/BuildingProductDetail.tsx b/src/components/product/detail/building/BuildingProductDetail.tsx
index 8bb5becc..80d7411e 100644
--- a/src/components/product/detail/building/BuildingProductDetail.tsx
+++ b/src/components/product/detail/building/BuildingProductDetail.tsx
@@ -4,26 +4,50 @@ import FloatingPopulationChart from './chart/FloatingPopulationChart';
import PopulationInformationChart from './chart/PopulationInformationChart';
import PublicTransport from './PublicTransport';
import OfficialPriceChart from './chart/OfficialPriceChart';
+import AccommodationVisitorsChart from './chart/AccommodationVisitorsChart';
+import AccommoationRateChart from './chart/AccommodationRateChart';
const BuildingProductDetail = ({
url,
- rentType
+ rentType,
+ stayType
}: {
url: string;
rentType: boolean | undefined;
+ stayType: boolean | undefined;
}) => {
+ console.log(rentType);
+ console.log(stayType);
return (
-
- 상권 임대료
- (단위: 천원/m²)
-
+ {stayType ? (
+ <>
+
+ 숙박 유형별 방문자 수
+
-
-
- 상권 공실률
- (단위: %)
-
-
+
+
+
+ 숙박 방문자 비율 / 평균 숙박일
+
+
+
+ >
+ ) : (
+ <>
+ {' '}
+
+ 상권 임대료
+ (단위: 천원/m²)
+
+
+
+ 상권 공실률
+ (단위: %)
+
+
+ >
+ )}
공시지가
diff --git a/src/components/product/detail/building/chart/AccommodationRateChart.tsx b/src/components/product/detail/building/chart/AccommodationRateChart.tsx
new file mode 100644
index 00000000..246acc04
--- /dev/null
+++ b/src/components/product/detail/building/chart/AccommodationRateChart.tsx
@@ -0,0 +1,210 @@
+import React, { useState, useRef, useEffect } from 'react';
+import { useQuery } from '@tanstack/react-query';
+import axios from 'axios';
+import { usePathname } from 'next/navigation';
+import { IStayRateData } from '@/types/BuildingProductType';
+import { Chart } from 'react-chartjs-2';
+import { TooltipItem } from 'chart.js';
+
+const AccommoationRateChart = () => {
+ const pathname = usePathname();
+ const lastSegment = pathname.split('/').pop();
+ const [startYear, setStartYear] = useState
(2022);
+ const [endYear, setEndYear] = useState(2024);
+ const fetchData = async () => {
+ try {
+ const response = await axios.get(
+ `https://api.moaguide.com/detail/building/stay/rate/${lastSegment}?syear=${startYear}&eyear=${endYear}`
+ );
+ return response.data;
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ throw error; // 에러를 다시 던져서 useQuery의 onError로 전달
+ }
+ };
+
+ const {
+ data: CopyRightFeeData,
+ isLoading,
+ error
+ } = useQuery({
+ queryKey: ['AccommodationRate', startYear, lastSegment, endYear],
+ queryFn: fetchData
+ });
+
+ const AccommodationRateDay = CopyRightFeeData?.object.map((item) => item.day);
+
+ const AccommodationRatevalue = CopyRightFeeData?.object.map((item) => item.value);
+
+ const AccommodationRateRate = CopyRightFeeData?.object.map((item) => item.rate);
+
+ const data = {
+ labels: AccommodationRateDay,
+ datasets: [
+ {
+ type: 'bar' as const,
+ label: '평균 숙박 일수',
+ data: AccommodationRatevalue,
+ backgroundColor: (context: any) => {
+ const chart = context.chart;
+ const { ctx, chartArea } = chart;
+
+ if (!chartArea) {
+ return null;
+ }
+
+ const gradient = ctx.createLinearGradient(
+ 0,
+ chartArea.bottom,
+ 0,
+ chartArea.top
+ );
+ gradient.addColorStop(0, 'rgba(140, 192, 250, 0.8)');
+ gradient.addColorStop(1, '#2575d1');
+
+ return gradient;
+ },
+ yAxisID: 'y1',
+ borderRadius: 5,
+ barThickness: 20,
+ barPercentage: 0.2,
+ categoryPercentage: 0.5,
+
+ datalabels: {
+ display: false,
+ align: 'end' as const,
+ anchor: 'end' as const,
+ color: '#000',
+ formatter: (value: number) => `${value}`
+ }
+ },
+ {
+ type: 'line' as const,
+ label: '숙박 방문자 비율',
+ data: AccommodationRateRate,
+ borderColor: '#0000FF',
+ backgroundColor: '#0000FF',
+ pointBackgroundColor: '#0000FF',
+ pointBorderColor: '#0000FF',
+ fill: false,
+ tension: 0.4,
+ yAxisID: 'y2',
+ pointStyle: 'circle',
+ pointRadius: 6,
+ datalabels: {
+ display: false
+ }
+ }
+ ]
+ };
+
+ const options = {
+ responsive: true,
+ maintainAspectRatio: false,
+ aspectRatio: 2,
+ scales: {
+ x: {
+ display: true,
+ grid: {
+ display: false
+ }
+ },
+ y1: {
+ type: 'linear' as const,
+ position: 'left' as const,
+ grid: {
+ display: false
+ },
+ beginAtZero: true,
+ // max: BarnewVariable,
+ ticks: {
+ stepSize: 10
+ }
+ },
+ y2: {
+ type: 'linear' as const,
+ position: 'right' as const,
+ grid: {
+ display: false
+ },
+ // max: LinenewVariable,
+ beginAtZero: true
+ }
+ },
+ plugins: {
+ legend: {
+ display: false,
+ position: 'top' as const
+ },
+ tooltip: {
+ enabled: true,
+ intersect: false,
+ callbacks: {
+ label: function (context: TooltipItem<'bar' | 'line'>) {
+ const label = context.dataset.label || '';
+ const value = context.raw as number;
+ const unit = context.dataset.type === 'bar' ? '일' : '%';
+ // return `${label}: ${value.toLocaleString()}${unit}`;
+ return ``;
+ },
+ beforeBody: function (context: TooltipItem<'bar' | 'line'>[]) {
+ const index = context[0].dataIndex;
+ const datasets = context[0].chart.data.datasets;
+
+ let tooltipText = '';
+ datasets.forEach((dataset) => {
+ const value = dataset.data[index] as number;
+ const unit = dataset.type === 'bar' ? '일' : '%';
+ tooltipText += `${dataset.label}: ${value.toLocaleString()}${unit}\n`;
+ });
+
+ return tooltipText;
+ }
+ }
+ },
+ datalabels: {
+ display: true
+ }
+ }
+ };
+
+ return (
+
+
+
+
+ ~
+
+
+
+
+
+
+ );
+};
+
+export default AccommoationRateChart;
diff --git a/src/components/product/detail/building/chart/AccommodationVisitorsChart.tsx b/src/components/product/detail/building/chart/AccommodationVisitorsChart.tsx
new file mode 100644
index 00000000..b20d6a86
--- /dev/null
+++ b/src/components/product/detail/building/chart/AccommodationVisitorsChart.tsx
@@ -0,0 +1,168 @@
+import React, { useState } from 'react';
+import { Bar } from 'react-chartjs-2';
+import { useQuery } from '@tanstack/react-query';
+import axios from 'axios';
+import { usePathname } from 'next/navigation';
+import { IStayDayData } from '@/types/BuildingProductType';
+import { TooltipItem } from 'chart.js';
+
+const AccommodationVisitorsChart = () => {
+ const pathname = usePathname();
+ const lastSegment = pathname.split('/').pop(); // 경로의 마지막 부분 추출
+ const [startYear, setStartYear] = useState(2022);
+ const [endYear, setEndYear] = useState(2024);
+ const fetchData = async () => {
+ const response = await axios.get(
+ `https://api.moaguide.com/detail/building/stay/day/${lastSegment}?syear=${startYear}&eyear=${endYear}`
+ );
+ return response.data;
+ };
+ // useQuery로 데이터 패칭
+ const { data, error, isLoading } = useQuery({
+ queryKey: ['accommodationVisitordata', lastSegment, startYear, endYear],
+ queryFn: fetchData
+ });
+
+ const accommodationVisitorDay = data?.object.map((item) => item.day);
+
+ const accommodationVisitorData = (() => {
+ if (!data?.object) return [];
+
+ const totalArray = data.object.map((item) => item.total);
+ const nodayArray = data.object.map((item) => item.noday);
+ const onedayArray = data.object.map((item) => item.oneday);
+ const twodayArray = data.object.map((item) => item.twoday);
+ const threedayArray = data.object.map((item) => item.threeday);
+
+ return [totalArray, nodayArray, onedayArray, twodayArray, threedayArray];
+ })();
+
+ const chartData = {
+ labels: accommodationVisitorDay,
+ datasets: [
+ {
+ label: '전체',
+ data: accommodationVisitorData[0],
+ backgroundColor: '#89a3ff'
+ },
+ {
+ label: '무박',
+ data: accommodationVisitorData[1],
+ backgroundColor: '#6243ee'
+ },
+ {
+ label: '1박',
+ data: accommodationVisitorData[2],
+ backgroundColor: '#aea0e9'
+ },
+ {
+ label: '2박',
+ data: accommodationVisitorData[3],
+ backgroundColor: '#3343f1'
+ },
+ {
+ label: '3박이상',
+ data: accommodationVisitorData[4],
+ backgroundColor: '#e435ed'
+ }
+ ]
+ };
+
+ const options = {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ display: true,
+ position: 'bottom' as const
+ },
+ tooltip: {
+ enabled: true,
+ intersect: false,
+ callbacks: {
+ label: function (context: TooltipItem<'bar'>) {
+ const label = context.dataset.label || '';
+ const value = context.raw;
+ return ``;
+ },
+ beforeBody: function (context: TooltipItem<'bar'>[]) {
+ const index = context[0].dataIndex;
+ const datasets = context[0].chart.data.datasets;
+
+ let tooltipText = '';
+ datasets.forEach((dataset) => {
+ const value = dataset.data[index] as number;
+ tooltipText += `${dataset.label}: ${value.toLocaleString()}명\n`;
+ });
+
+ return tooltipText;
+ }
+ }
+ },
+ datalabels: {
+ display: false // 데이터 레이블 숨기기
+ }
+ // customText: customTextPlugin
+ },
+ scales: {
+ x: {
+ stacked: true,
+ grid: {
+ display: false
+ }
+ },
+ y: {
+ stacked: true,
+ beginAtZero: true,
+ grid: {
+ display: true
+ }
+ }
+ }
+ };
+
+ return (
+
+
+
+
+
+ ~
+
+
+
+
+
+
+ {chartData ? (
+
+ ) : (
+
Loading chart...
+ )}
+
+
+
+ );
+};
+
+export default AccommodationVisitorsChart;
diff --git a/src/components/product/detail/building/chart/FloatingPopulationChart.tsx b/src/components/product/detail/building/chart/FloatingPopulationChart.tsx
index 06a4c794..5bbb892d 100644
--- a/src/components/product/detail/building/chart/FloatingPopulationChart.tsx
+++ b/src/components/product/detail/building/chart/FloatingPopulationChart.tsx
@@ -1,10 +1,8 @@
import React from 'react';
import { Bar } from 'react-chartjs-2';
-
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import { usePathname } from 'next/navigation';
-import { it } from 'node:test';
import { ISubwayData } from '@/types/BuildingProductType';
const FloatingPopulationChart = () => {
diff --git a/src/types/BuildingProductType.ts b/src/types/BuildingProductType.ts
index c7065e3c..be6de6c7 100644
--- a/src/types/BuildingProductType.ts
+++ b/src/types/BuildingProductType.ts
@@ -37,6 +37,7 @@ export interface IBuildingProductDetail {
link: string;
rentType: boolean;
bookmark: boolean;
+ stayType: boolean;
}
export interface IBuildingProductProfitDetail {
@@ -117,3 +118,26 @@ export interface ISubwayData {
subwayDay: ISubwayDayItem[];
subwayMonth: ISubwayMonthItem[];
}
+
+export interface ISaydayItem {
+ day: string;
+ noday: number;
+ oneday: number;
+ twoday: number;
+ threeday: number;
+ total: number;
+}
+
+export interface IStayDayData {
+ object: ISaydayItem[];
+}
+
+export interface IStayRateItem {
+ day: string;
+ rate: number;
+ value: number;
+}
+
+export interface IStayRateData {
+ object: IStayRateItem[];
+}