@dssp/dkpi 1.0.0-alpha.66 → 1.0.0-alpha.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist-client/components/kpi-2d-lookup-chart.d.ts +10 -30
  2. package/dist-client/components/kpi-2d-lookup-chart.js +150 -362
  3. package/dist-client/components/kpi-2d-lookup-chart.js.map +1 -1
  4. package/dist-client/components/kpi-boxplot-chart.js +51 -20
  5. package/dist-client/components/kpi-boxplot-chart.js.map +1 -1
  6. package/dist-client/components/kpi-lookup-chart.d.ts +15 -4
  7. package/dist-client/components/kpi-lookup-chart.js +248 -292
  8. package/dist-client/components/kpi-lookup-chart.js.map +1 -1
  9. package/dist-client/components/kpi-radar-chart.js +29 -5
  10. package/dist-client/components/kpi-radar-chart.js.map +1 -1
  11. package/dist-client/components/kpi-single-boxplot-chart.js +72 -14
  12. package/dist-client/components/kpi-single-boxplot-chart.js.map +1 -1
  13. package/dist-client/google-map/common-google-map.js +10 -8
  14. package/dist-client/google-map/common-google-map.js.map +1 -1
  15. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +7 -0
  16. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
  17. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +2 -0
  18. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +12 -4
  19. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
  20. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +2 -0
  21. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +84 -25
  22. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
  23. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +12 -0
  24. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +243 -16
  25. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
  26. package/dist-client/pages/sv-project-detail.d.ts +1 -1
  27. package/dist-client/pages/sv-project-detail.js +25 -7
  28. package/dist-client/pages/sv-project-detail.js.map +1 -1
  29. package/dist-client/tsconfig.tsbuildinfo +1 -1
  30. package/dist-server/service/kpi-stat/kpi-stat-query.d.ts +2 -0
  31. package/dist-server/service/kpi-stat/kpi-stat-query.js +120 -0
  32. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -1
  33. package/dist-server/service/kpi-stat/kpi-stat-types.d.ts +1 -0
  34. package/dist-server/service/kpi-stat/kpi-stat-types.js +4 -0
  35. package/dist-server/service/kpi-stat/kpi-stat-types.js.map +1 -1
  36. package/dist-server/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +2 -2
  38. package/schema.graphql +7 -0
@@ -1,3 +1,4 @@
1
+ var KpiRegionPopup_1;
1
2
  import { __decorate, __metadata } from "tslib";
2
3
  import gql from 'graphql-tag';
3
4
  import { LitElement, html, css, nothing } from 'lit';
@@ -7,10 +8,11 @@ import { ScrollbarStyles } from '@operato/styles';
7
8
  import '../../../components/kpi-radar-chart.js';
8
9
  import '../../../components/kpi-boxplot-chart.js';
9
10
  import '../../../components/kpi-trend-chart.js';
10
- let KpiRegionPopup = class KpiRegionPopup extends LitElement {
11
+ let KpiRegionPopup = KpiRegionPopup_1 = class KpiRegionPopup extends LitElement {
11
12
  constructor() {
12
13
  super(...arguments);
13
14
  this.selectedRegion = null;
15
+ this.geoGroup = null; // 시군구 geo_group 코드 (있으면 시군구 쿼리 사용)
14
16
  this.selectedCategory = '전체 KPI';
15
17
  this.selectedChartType = 'boxplot';
16
18
  this.selectedPeriod = '월';
@@ -43,28 +45,58 @@ let KpiRegionPopup = class KpiRegionPopup extends LitElement {
43
45
  if (!this.selectedRegion)
44
46
  return;
45
47
  try {
46
- const response = await client.query({
47
- query: gql `
48
- query GetRegionKpiStats($metroArea: String!, $startYearMonth: String, $endYearMonth: String) {
49
- kpiYValueStatsByMetroArea(metroArea: $metroArea, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {
50
- kpiName
51
- minVal
52
- q1Val
53
- medVal
54
- q3Val
55
- maxVal
56
- avgVal
57
- projectCount
48
+ let regionKpiStats;
49
+ if (this.geoGroup) {
50
+ // 시군구 모드: geo_group 코드로 조회
51
+ const response = await client.query({
52
+ query: gql `
53
+ query GetSigunguKpiStats($geoGroup: String!, $startYearMonth: String, $endYearMonth: String) {
54
+ kpiYValueStatsByGeoGroup(geoGroup: $geoGroup, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {
55
+ kpiName
56
+ minVal
57
+ q1Val
58
+ medVal
59
+ q3Val
60
+ maxVal
61
+ avgVal
62
+ projectCount
63
+ }
58
64
  }
59
- }
60
- `,
61
- variables: {
62
- metroArea: this.selectedRegion,
63
- startYearMonth: this.startYearMonth,
64
- endYearMonth: this.endYearMonth
65
- }
66
- });
67
- this.regionKpiStats = response.data.kpiYValueStatsByMetroArea || [];
65
+ `,
66
+ variables: {
67
+ geoGroup: this.geoGroup,
68
+ startYearMonth: this.startYearMonth,
69
+ endYearMonth: this.endYearMonth
70
+ }
71
+ });
72
+ regionKpiStats = response.data.kpiYValueStatsByGeoGroup || [];
73
+ }
74
+ else {
75
+ // 광역 모드: 광역시도 이름으로 조회
76
+ const response = await client.query({
77
+ query: gql `
78
+ query GetRegionKpiStats($metroArea: String!, $startYearMonth: String, $endYearMonth: String) {
79
+ kpiYValueStatsByMetroArea(metroArea: $metroArea, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {
80
+ kpiName
81
+ minVal
82
+ q1Val
83
+ medVal
84
+ q3Val
85
+ maxVal
86
+ avgVal
87
+ projectCount
88
+ }
89
+ }
90
+ `,
91
+ variables: {
92
+ metroArea: this.selectedRegion,
93
+ startYearMonth: this.startYearMonth,
94
+ endYearMonth: this.endYearMonth
95
+ }
96
+ });
97
+ regionKpiStats = response.data.kpiYValueStatsByMetroArea || [];
98
+ }
99
+ this.regionKpiStats = regionKpiStats;
68
100
  console.log('Region KPI Stats:', this.regionKpiStats);
69
101
  this.generateChartData();
70
102
  }
@@ -144,9 +176,12 @@ let KpiRegionPopup = class KpiRegionPopup extends LitElement {
144
176
  generateTrendData() {
145
177
  if (!this.selectedRegion)
146
178
  return;
147
- // 선택된 지역의 월별 추이 데이터 추출
179
+ // 시군구 모드인 경우 소속 광역시도의 추이 데이터 사용
180
+ const trendRegion = this.geoGroup
181
+ ? KpiRegionPopup_1.GEO_TO_METRO[this.geoGroup] || this.selectedRegion
182
+ : this.selectedRegion;
148
183
  const regionTrendData = this.monthlyTrendData
149
- .filter(d => d.geoGroup === this.selectedRegion)
184
+ .filter(d => d.geoGroup === trendRegion)
150
185
  .sort((a, b) => a.yearMonth.localeCompare(b.yearMonth));
151
186
  this.trendData = regionTrendData.map(d => {
152
187
  const value = Math.round(d.avgVal * 100); // 20배 스케일
@@ -384,10 +419,34 @@ KpiRegionPopup.styles = [
384
419
  }
385
420
  `
386
421
  ];
422
+ // geo_group → 광역시도 매핑 (시군구 모드에서 추이 데이터 조회용)
423
+ KpiRegionPopup.GEO_TO_METRO = {
424
+ '01': '서울특별시', '02': '서울특별시', '03': '서울특별시', '04': '서울특별시',
425
+ '05': '서울특별시', '06': '서울특별시', '07': '서울특별시', '08': '서울특별시',
426
+ '10': '경기도', '11': '경기도', '12': '경기도', '13': '경기도', '14': '경기도',
427
+ '15': '경기도', '16': '경기도', '17': '경기도', '18': '경기도',
428
+ '21': '인천광역시', '22': '인천광역시', '23': '인천광역시',
429
+ '24': '강원도', '25': '강원도', '26': '강원도', '33': '강원도',
430
+ '27': '충청북도', '28': '충청북도', '29': '충청북도',
431
+ '30': '세종특별자치시', '31': '충청남도', '32': '충청남도',
432
+ '34': '대전광역시', '35': '대전광역시',
433
+ '36': '경상북도', '37': '경상북도', '38': '경상북도', '39': '경상북도', '40': '경상북도',
434
+ '41': '대구광역시', '42': '대구광역시', '43': '대구광역시',
435
+ '44': '울산광역시', '45': '울산광역시',
436
+ '46': '부산광역시', '47': '부산광역시', '48': '부산광역시', '49': '부산광역시',
437
+ '50': '경상남도', '51': '경상남도', '52': '경상남도', '53': '경상남도',
438
+ '54': '전라북도', '55': '전라북도', '56': '전라북도',
439
+ '57': '전라남도', '58': '전라남도', '59': '전라남도',
440
+ '61': '광주광역시', '62': '광주광역시', '63': '제주특별자치도'
441
+ };
387
442
  __decorate([
388
443
  property({ type: String }),
389
444
  __metadata("design:type", Object)
390
445
  ], KpiRegionPopup.prototype, "selectedRegion", void 0);
446
+ __decorate([
447
+ property({ type: String }),
448
+ __metadata("design:type", Object)
449
+ ], KpiRegionPopup.prototype, "geoGroup", void 0);
391
450
  __decorate([
392
451
  property({ type: String }),
393
452
  __metadata("design:type", Object)
@@ -432,7 +491,7 @@ __decorate([
432
491
  state(),
433
492
  __metadata("design:type", Array)
434
493
  ], KpiRegionPopup.prototype, "regionKpiStats", void 0);
435
- KpiRegionPopup = __decorate([
494
+ KpiRegionPopup = KpiRegionPopup_1 = __decorate([
436
495
  customElement('kpi-region-popup')
437
496
  ], KpiRegionPopup);
438
497
  export { KpiRegionPopup };
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-region-popup.js","sourceRoot":"","sources":["../../../../client/pages/kpi-dashboard/components/kpi-region-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\nimport { LitElement, html, css, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport '../../../components/kpi-radar-chart.js'\nimport '../../../components/kpi-boxplot-chart.js'\nimport '../../../components/kpi-trend-chart.js'\n\n@customElement('kpi-region-popup')\nexport class KpiRegionPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n position: absolute;\n top: 0;\n left: 402px;\n width: 400px;\n height: 100%;\n background: #fff;\n border-right: 1px solid #e0e0e0;\n z-index: 1000;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);\n }\n .popup-content {\n padding: 20px;\n overflow-y: auto;\n flex: 1;\n }\n .popup-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fff;\n height: 70px;\n box-sizing: border-box;\n }\n .popup-title {\n font-size: 1.2rem;\n font-weight: bold;\n color: #333;\n }\n .popup-close {\n width: 32px;\n height: 32px;\n border: none;\n background: #fff;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n color: #666;\n transition: all 0.2s;\n }\n .popup-close:hover {\n background: #e9ecef;\n color: #333;\n }\n .sub-title {\n font-size: 1rem;\n font-weight: 600;\n margin-bottom: 16px;\n color: #495057;\n }\n .chart-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 20px;\n }\n .chart-toggle {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n }\n .toggle-button {\n padding: 8px 16px;\n border: 1px solid #ced4da;\n background: #fff;\n border-radius: 6px;\n cursor: pointer;\n font-size: 0.9rem;\n transition: all 0.2s;\n }\n .toggle-button.active {\n background: #667eea;\n color: white;\n border-color: #667eea;\n }\n .chart-container {\n height: 300px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n border-radius: 6px;\n border: 1px solid #e9ecef;\n }\n .period-selector {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n }\n .period-button {\n padding: 6px 12px;\n border: 1px solid #ced4da;\n background: #fff;\n border-radius: 4px;\n cursor: pointer;\n font-size: 0.85rem;\n transition: all 0.2s;\n }\n .period-button.active {\n background: #667eea;\n color: white;\n border-color: #667eea;\n }\n .date-range-selector {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n }\n .date-select {\n padding: 6px 12px;\n border: 1px solid #ced4da;\n border-radius: 4px;\n background: white;\n font-size: 0.9rem;\n }\n `\n ]\n\n @property({ type: String }) selectedRegion: string | null = null\n @property({ type: String }) selectedCategory = '전체 KPI'\n @property({ type: String }) selectedChartType = 'boxplot'\n @property({ type: String }) selectedPeriod = '월'\n @property({ type: String }) startYearMonth = '' // YYYY-MM 형식\n @property({ type: String }) endYearMonth = '' // YYYY-MM 형식\n @property({ type: Array }) monthlyTrendData: any[] = [] // 부모에서 전달받은 월별 추이 데이터\n @property({ type: Array }) totalKpiStats: any[] = [] // 전체 KPI 통계 (비교용)\n\n @state() private chartData: any[] = []\n @state() private chartCategories: string[] = []\n @state() private trendData: { date: string; value: number; color?: string }[] = []\n @state() private regionKpiStats: any[] = []\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('selectedRegion') && this.selectedRegion) {\n this.fetchRegionKpiStats()\n this.generateTrendData()\n }\n\n // selectedCategory 또는 monthlyTrendData가 변경되면 추이 데이터 재생성\n if (changedProperties.has('selectedCategory') || changedProperties.has('monthlyTrendData')) {\n this.generateTrendData()\n }\n\n // 기간이 변경되면 차트 데이터 다시 가져오기\n if (changedProperties.has('startYearMonth') || changedProperties.has('endYearMonth')) {\n if (this.selectedRegion) {\n this.fetchRegionKpiStats()\n }\n }\n }\n\n async fetchRegionKpiStats() {\n if (!this.selectedRegion) return\n\n try {\n const response = await client.query({\n query: gql`\n query GetRegionKpiStats($metroArea: String!, $startYearMonth: String, $endYearMonth: String) {\n kpiYValueStatsByMetroArea(metroArea: $metroArea, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {\n kpiName\n minVal\n q1Val\n medVal\n q3Val\n maxVal\n avgVal\n projectCount\n }\n }\n `,\n variables: {\n metroArea: this.selectedRegion,\n startYearMonth: this.startYearMonth,\n endYearMonth: this.endYearMonth\n }\n })\n\n this.regionKpiStats = response.data.kpiYValueStatsByMetroArea || []\n console.log('Region KPI Stats:', this.regionKpiStats)\n this.generateChartData()\n } catch (error) {\n console.error('Failed to fetch region KPI stats:', error)\n this.regionKpiStats = []\n this.generateChartData()\n }\n }\n\n private generateChartData() {\n // KPI 이름을 카테고리로 매핑 및 축약\n const categoryMapping: Record<string, string> = {\n 'Y1. 일정성과': '일정',\n 'Y2. 비용성과': '비용',\n 'Y3. 품질성과': '품질',\n 'Y4. 안전성과': '안전',\n 'Y5. 환경성과': '환경',\n 'Y6. 생산성성과': '생산성'\n }\n\n // 레이더 차트와 박스플롯은 항상 전체 Y-level KPI 표시 (selectedCategory 무시)\n if (this.selectedChartType === 'radar') {\n // 레이더 차트용 데이터 생성 (전체평균 + 지역 비교)\n const data: Array<{ org: string; category: string; value: number }> = []\n const categories: string[] = []\n\n // 카테고리 수집\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n if (!categories.includes(category)) {\n categories.push(category)\n }\n })\n\n // 전체평균 데이터 추가\n this.totalKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n data.push({\n org: '전체평균',\n category,\n value: Math.round(stat.avgVal * 100)\n })\n })\n\n // 지역 데이터 추가\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n data.push({\n org: this.selectedRegion || '지역',\n category,\n value: Math.round(stat.avgVal * 100)\n })\n })\n\n this.chartCategories = categories.length > 0 ? categories : ['일정', '비용', '품질', '안전', '환경', '생산성']\n this.chartData = data\n } else {\n // 박스플롯용 데이터 생성\n const data: Array<{\n org: string\n min: number\n max: number\n q1: number\n q3: number\n median: number\n mean: number\n value: number\n }> = []\n const categories: string[] = []\n\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n if (!categories.includes(category)) {\n categories.push(category)\n }\n data.push({\n org: category,\n min: stat.minVal * 100,\n max: stat.maxVal * 100,\n q1: stat.q1Val * 100,\n q3: stat.q3Val * 100,\n median: stat.medVal * 100,\n mean: stat.avgVal * 100,\n value: stat.avgVal * 100\n })\n })\n\n this.chartCategories = categories.length > 0 ? categories : ['일정', '비용', '품질', '안전', '환경', '생산성']\n this.chartData = data\n }\n }\n\n private generateTrendData() {\n if (!this.selectedRegion) return\n\n // 선택된 지역의 월별 추이 데이터 추출\n const regionTrendData = this.monthlyTrendData\n .filter(d => d.geoGroup === this.selectedRegion)\n .sort((a, b) => a.yearMonth.localeCompare(b.yearMonth))\n\n this.trendData = regionTrendData.map(d => {\n const value = Math.round(d.avgVal * 100) // 20배 스케일\n return {\n date: d.yearMonth, // YYYY-MM 형식\n value: value,\n color: value > 60 ? '#4caf50' : value > 40 ? '#ff9800' : '#f44336'\n }\n })\n }\n\n private onClose() {\n this.dispatchEvent(\n new CustomEvent('popup-close', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private onChartTypeChange(type: string) {\n this.selectedChartType = type\n this.generateChartData()\n }\n\n render() {\n if (!this.selectedRegion) {\n return nothing\n }\n\n return html`\n <div class=\"popup-header\">\n <div class=\"popup-title\">${this.selectedRegion} KPI</div>\n <button class=\"popup-close\" @click=${this.onClose}>×</button>\n </div>\n <div class=\"popup-content\">\n <!-- 종합 성과 -->\n <div class=\"chart-section\">\n <div class=\"sub-title\">종합 성과</div>\n <div class=\"chart-toggle\">\n <button\n class=\"toggle-button ${this.selectedChartType === 'boxplot' ? 'active' : ''}\"\n @click=${() => this.onChartTypeChange('boxplot')}\n >\n 박스플롯\n </button>\n <button\n class=\"toggle-button ${this.selectedChartType === 'radar' ? 'active' : ''}\"\n @click=${() => this.onChartTypeChange('radar')}\n >\n 레이더차트\n </button>\n </div>\n <div class=\"chart-container\">\n ${this.selectedChartType === 'boxplot'\n ? html`\n <sv-kpi-boxplot-chart\n .data=${this.chartData}\n .groups=${this.chartCategories}\n .valueKey=${'value'}\n ></sv-kpi-boxplot-chart>\n `\n : html`\n <sv-kpi-radar-chart\n .data=${this.chartData}\n .categories=${this.chartCategories}\n .valueKey=${'value'}\n ></sv-kpi-radar-chart>\n `}\n </div>\n </div>\n\n <!-- 기간별 성과 추이 -->\n <div class=\"trend-section\">\n <div class=\"sub-title\">기간별 성과 추이</div>\n <div class=\"trend-chart-container\" style=\"height: 200px; margin-bottom: 16px;\">\n <sv-kpi-trend-chart\n .data=${this.trendData}\n .lineColor=${'#2196f3'}\n .strokeWidth=${2}\n .showPoints=${false}\n .pointRadius=${4}\n ></sv-kpi-trend-chart>\n </div>\n <div class=\"trend-table\">\n <table style=\"width: 100%; border-collapse: collapse; font-size: 0.85rem;\">\n <thead style=\"position: sticky; top: 0; background: white; z-index: 1;\">\n <tr style=\"border-bottom: 2px solid #f1f3f4; background-color: #f8f9fa;\">\n <th style=\"padding: 8px; text-align: left; font-weight: 600;\">날짜</th>\n <th style=\"padding: 8px; text-align: right; font-weight: 600;\">성과</th>\n <th style=\"padding: 8px; text-align: center; font-weight: 600;\">추이</th>\n </tr>\n </thead>\n <tbody>\n ${this.trendData.map(\n (item: any) => html`\n <tr style=\"border-bottom: 1px solid #f1f3f4;\">\n <td style=\"padding: 8px; font-size: 0.85rem;\">${item.date}</td>\n <td style=\"padding: 8px; text-align: right; font-size: 0.85rem; font-weight: 600;\">\n ${item.value.toFixed(1)}\n </td>\n <td style=\"padding: 8px; text-align: center; font-size: 0.85rem;\">\n <span style=\"color: ${item.color};\"> ${item.value > 60 ? '▲' : item.value > 40 ? '▲' : '▼'} </span>\n </td>\n </tr>\n `\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-region-popup.js","sourceRoot":"","sources":["../../../../client/pages/kpi-dashboard/components/kpi-region-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\nimport { LitElement, html, css, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport '../../../components/kpi-radar-chart.js'\nimport '../../../components/kpi-boxplot-chart.js'\nimport '../../../components/kpi-trend-chart.js'\n\n@customElement('kpi-region-popup')\nexport class KpiRegionPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n position: absolute;\n top: 0;\n left: 402px;\n width: 400px;\n height: 100%;\n background: #fff;\n border-right: 1px solid #e0e0e0;\n z-index: 1000;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);\n }\n .popup-content {\n padding: 20px;\n overflow-y: auto;\n flex: 1;\n }\n .popup-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fff;\n height: 70px;\n box-sizing: border-box;\n }\n .popup-title {\n font-size: 1.2rem;\n font-weight: bold;\n color: #333;\n }\n .popup-close {\n width: 32px;\n height: 32px;\n border: none;\n background: #fff;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n color: #666;\n transition: all 0.2s;\n }\n .popup-close:hover {\n background: #e9ecef;\n color: #333;\n }\n .sub-title {\n font-size: 1rem;\n font-weight: 600;\n margin-bottom: 16px;\n color: #495057;\n }\n .chart-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 20px;\n }\n .chart-toggle {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n }\n .toggle-button {\n padding: 8px 16px;\n border: 1px solid #ced4da;\n background: #fff;\n border-radius: 6px;\n cursor: pointer;\n font-size: 0.9rem;\n transition: all 0.2s;\n }\n .toggle-button.active {\n background: #667eea;\n color: white;\n border-color: #667eea;\n }\n .chart-container {\n height: 300px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n border-radius: 6px;\n border: 1px solid #e9ecef;\n }\n .period-selector {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n }\n .period-button {\n padding: 6px 12px;\n border: 1px solid #ced4da;\n background: #fff;\n border-radius: 4px;\n cursor: pointer;\n font-size: 0.85rem;\n transition: all 0.2s;\n }\n .period-button.active {\n background: #667eea;\n color: white;\n border-color: #667eea;\n }\n .date-range-selector {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n }\n .date-select {\n padding: 6px 12px;\n border: 1px solid #ced4da;\n border-radius: 4px;\n background: white;\n font-size: 0.9rem;\n }\n `\n ]\n\n @property({ type: String }) selectedRegion: string | null = null\n @property({ type: String }) geoGroup: string | null = null // 시군구 geo_group 코드 (있으면 시군구 쿼리 사용)\n @property({ type: String }) selectedCategory = '전체 KPI'\n @property({ type: String }) selectedChartType = 'boxplot'\n @property({ type: String }) selectedPeriod = '월'\n @property({ type: String }) startYearMonth = '' // YYYY-MM 형식\n @property({ type: String }) endYearMonth = '' // YYYY-MM 형식\n @property({ type: Array }) monthlyTrendData: any[] = [] // 부모에서 전달받은 월별 추이 데이터\n @property({ type: Array }) totalKpiStats: any[] = [] // 전체 KPI 통계 (비교용)\n\n @state() private chartData: any[] = []\n @state() private chartCategories: string[] = []\n @state() private trendData: { date: string; value: number; color?: string }[] = []\n @state() private regionKpiStats: any[] = []\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('selectedRegion') && this.selectedRegion) {\n this.fetchRegionKpiStats()\n this.generateTrendData()\n }\n\n // selectedCategory 또는 monthlyTrendData가 변경되면 추이 데이터 재생성\n if (changedProperties.has('selectedCategory') || changedProperties.has('monthlyTrendData')) {\n this.generateTrendData()\n }\n\n // 기간이 변경되면 차트 데이터 다시 가져오기\n if (changedProperties.has('startYearMonth') || changedProperties.has('endYearMonth')) {\n if (this.selectedRegion) {\n this.fetchRegionKpiStats()\n }\n }\n }\n\n async fetchRegionKpiStats() {\n if (!this.selectedRegion) return\n\n try {\n let regionKpiStats: any[]\n\n if (this.geoGroup) {\n // 시군구 모드: geo_group 코드로 조회\n const response = await client.query({\n query: gql`\n query GetSigunguKpiStats($geoGroup: String!, $startYearMonth: String, $endYearMonth: String) {\n kpiYValueStatsByGeoGroup(geoGroup: $geoGroup, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {\n kpiName\n minVal\n q1Val\n medVal\n q3Val\n maxVal\n avgVal\n projectCount\n }\n }\n `,\n variables: {\n geoGroup: this.geoGroup,\n startYearMonth: this.startYearMonth,\n endYearMonth: this.endYearMonth\n }\n })\n regionKpiStats = response.data.kpiYValueStatsByGeoGroup || []\n } else {\n // 광역 모드: 광역시도 이름으로 조회\n const response = await client.query({\n query: gql`\n query GetRegionKpiStats($metroArea: String!, $startYearMonth: String, $endYearMonth: String) {\n kpiYValueStatsByMetroArea(metroArea: $metroArea, startYearMonth: $startYearMonth, endYearMonth: $endYearMonth) {\n kpiName\n minVal\n q1Val\n medVal\n q3Val\n maxVal\n avgVal\n projectCount\n }\n }\n `,\n variables: {\n metroArea: this.selectedRegion,\n startYearMonth: this.startYearMonth,\n endYearMonth: this.endYearMonth\n }\n })\n regionKpiStats = response.data.kpiYValueStatsByMetroArea || []\n }\n\n this.regionKpiStats = regionKpiStats\n console.log('Region KPI Stats:', this.regionKpiStats)\n this.generateChartData()\n } catch (error) {\n console.error('Failed to fetch region KPI stats:', error)\n this.regionKpiStats = []\n this.generateChartData()\n }\n }\n\n private generateChartData() {\n // KPI 이름을 카테고리로 매핑 및 축약\n const categoryMapping: Record<string, string> = {\n 'Y1. 일정성과': '일정',\n 'Y2. 비용성과': '비용',\n 'Y3. 품질성과': '품질',\n 'Y4. 안전성과': '안전',\n 'Y5. 환경성과': '환경',\n 'Y6. 생산성성과': '생산성'\n }\n\n // 레이더 차트와 박스플롯은 항상 전체 Y-level KPI 표시 (selectedCategory 무시)\n if (this.selectedChartType === 'radar') {\n // 레이더 차트용 데이터 생성 (전체평균 + 지역 비교)\n const data: Array<{ org: string; category: string; value: number }> = []\n const categories: string[] = []\n\n // 카테고리 수집\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n if (!categories.includes(category)) {\n categories.push(category)\n }\n })\n\n // 전체평균 데이터 추가\n this.totalKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n data.push({\n org: '전체평균',\n category,\n value: Math.round(stat.avgVal * 100)\n })\n })\n\n // 지역 데이터 추가\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n data.push({\n org: this.selectedRegion || '지역',\n category,\n value: Math.round(stat.avgVal * 100)\n })\n })\n\n this.chartCategories = categories.length > 0 ? categories : ['일정', '비용', '품질', '안전', '환경', '생산성']\n this.chartData = data\n } else {\n // 박스플롯용 데이터 생성\n const data: Array<{\n org: string\n min: number\n max: number\n q1: number\n q3: number\n median: number\n mean: number\n value: number\n }> = []\n const categories: string[] = []\n\n this.regionKpiStats.forEach(stat => {\n const category = categoryMapping[stat.kpiName] || stat.kpiName\n if (!categories.includes(category)) {\n categories.push(category)\n }\n data.push({\n org: category,\n min: stat.minVal * 100,\n max: stat.maxVal * 100,\n q1: stat.q1Val * 100,\n q3: stat.q3Val * 100,\n median: stat.medVal * 100,\n mean: stat.avgVal * 100,\n value: stat.avgVal * 100\n })\n })\n\n this.chartCategories = categories.length > 0 ? categories : ['일정', '비용', '품질', '안전', '환경', '생산성']\n this.chartData = data\n }\n }\n\n // geo_group → 광역시도 매핑 (시군구 모드에서 추이 데이터 조회용)\n private static readonly GEO_TO_METRO: Record<string, string> = {\n '01':'서울특별시','02':'서울특별시','03':'서울특별시','04':'서울특별시',\n '05':'서울특별시','06':'서울특별시','07':'서울특별시','08':'서울특별시',\n '10':'경기도','11':'경기도','12':'경기도','13':'경기도','14':'경기도',\n '15':'경기도','16':'경기도','17':'경기도','18':'경기도',\n '21':'인천광역시','22':'인천광역시','23':'인천광역시',\n '24':'강원도','25':'강원도','26':'강원도','33':'강원도',\n '27':'충청북도','28':'충청북도','29':'충청북도',\n '30':'세종특별자치시','31':'충청남도','32':'충청남도',\n '34':'대전광역시','35':'대전광역시',\n '36':'경상북도','37':'경상북도','38':'경상북도','39':'경상북도','40':'경상북도',\n '41':'대구광역시','42':'대구광역시','43':'대구광역시',\n '44':'울산광역시','45':'울산광역시',\n '46':'부산광역시','47':'부산광역시','48':'부산광역시','49':'부산광역시',\n '50':'경상남도','51':'경상남도','52':'경상남도','53':'경상남도',\n '54':'전라북도','55':'전라북도','56':'전라북도',\n '57':'전라남도','58':'전라남도','59':'전라남도',\n '61':'광주광역시','62':'광주광역시','63':'제주특별자치도'\n }\n\n private generateTrendData() {\n if (!this.selectedRegion) return\n\n // 시군구 모드인 경우 소속 광역시도의 추이 데이터 사용\n const trendRegion = this.geoGroup\n ? KpiRegionPopup.GEO_TO_METRO[this.geoGroup] || this.selectedRegion\n : this.selectedRegion\n\n const regionTrendData = this.monthlyTrendData\n .filter(d => d.geoGroup === trendRegion)\n .sort((a, b) => a.yearMonth.localeCompare(b.yearMonth))\n\n this.trendData = regionTrendData.map(d => {\n const value = Math.round(d.avgVal * 100) // 20배 스케일\n return {\n date: d.yearMonth, // YYYY-MM 형식\n value: value,\n color: value > 60 ? '#4caf50' : value > 40 ? '#ff9800' : '#f44336'\n }\n })\n }\n\n private onClose() {\n this.dispatchEvent(\n new CustomEvent('popup-close', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private onChartTypeChange(type: string) {\n this.selectedChartType = type\n this.generateChartData()\n }\n\n render() {\n if (!this.selectedRegion) {\n return nothing\n }\n\n return html`\n <div class=\"popup-header\">\n <div class=\"popup-title\">${this.selectedRegion} KPI</div>\n <button class=\"popup-close\" @click=${this.onClose}>×</button>\n </div>\n <div class=\"popup-content\">\n <!-- 종합 성과 -->\n <div class=\"chart-section\">\n <div class=\"sub-title\">종합 성과</div>\n <div class=\"chart-toggle\">\n <button\n class=\"toggle-button ${this.selectedChartType === 'boxplot' ? 'active' : ''}\"\n @click=${() => this.onChartTypeChange('boxplot')}\n >\n 박스플롯\n </button>\n <button\n class=\"toggle-button ${this.selectedChartType === 'radar' ? 'active' : ''}\"\n @click=${() => this.onChartTypeChange('radar')}\n >\n 레이더차트\n </button>\n </div>\n <div class=\"chart-container\">\n ${this.selectedChartType === 'boxplot'\n ? html`\n <sv-kpi-boxplot-chart\n .data=${this.chartData}\n .groups=${this.chartCategories}\n .valueKey=${'value'}\n ></sv-kpi-boxplot-chart>\n `\n : html`\n <sv-kpi-radar-chart\n .data=${this.chartData}\n .categories=${this.chartCategories}\n .valueKey=${'value'}\n ></sv-kpi-radar-chart>\n `}\n </div>\n </div>\n\n <!-- 기간별 성과 추이 -->\n <div class=\"trend-section\">\n <div class=\"sub-title\">기간별 성과 추이</div>\n <div class=\"trend-chart-container\" style=\"height: 200px; margin-bottom: 16px;\">\n <sv-kpi-trend-chart\n .data=${this.trendData}\n .lineColor=${'#2196f3'}\n .strokeWidth=${2}\n .showPoints=${false}\n .pointRadius=${4}\n ></sv-kpi-trend-chart>\n </div>\n <div class=\"trend-table\">\n <table style=\"width: 100%; border-collapse: collapse; font-size: 0.85rem;\">\n <thead style=\"position: sticky; top: 0; background: white; z-index: 1;\">\n <tr style=\"border-bottom: 2px solid #f1f3f4; background-color: #f8f9fa;\">\n <th style=\"padding: 8px; text-align: left; font-weight: 600;\">날짜</th>\n <th style=\"padding: 8px; text-align: right; font-weight: 600;\">성과</th>\n <th style=\"padding: 8px; text-align: center; font-weight: 600;\">추이</th>\n </tr>\n </thead>\n <tbody>\n ${this.trendData.map(\n (item: any) => html`\n <tr style=\"border-bottom: 1px solid #f1f3f4;\">\n <td style=\"padding: 8px; font-size: 0.85rem;\">${item.date}</td>\n <td style=\"padding: 8px; text-align: right; font-size: 0.85rem; font-weight: 600;\">\n ${item.value.toFixed(1)}\n </td>\n <td style=\"padding: 8px; text-align: center; font-size: 0.85rem;\">\n <span style=\"color: ${item.color};\"> ${item.value > 60 ? '▲' : item.value > 40 ? '▲' : '▼'} </span>\n </td>\n </tr>\n `\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n `\n }\n}\n"]}
@@ -10,6 +10,9 @@ export declare class KpiDashboardMapPage extends PageView {
10
10
  endYearMonth: string;
11
11
  selectedSectorType: string;
12
12
  selectedBuildingUsage: string;
13
+ currentZoom: number;
14
+ sigunguData: any[];
15
+ private static readonly SIGUNGU_ZOOM_THRESHOLD;
13
16
  nationalData: any;
14
17
  seoulData: any;
15
18
  mapData: any;
@@ -17,6 +20,7 @@ export declare class KpiDashboardMapPage extends PageView {
17
20
  totalKpiYStats: any[];
18
21
  regionalKpiStats: any[];
19
22
  selectedRegion: string | null;
23
+ selectedGeoGroup: string | null;
20
24
  showRegionPopup: boolean;
21
25
  connectedCallback(): void;
22
26
  private initializeDefaultPeriod;
@@ -26,6 +30,14 @@ export declare class KpiDashboardMapPage extends PageView {
26
30
  private generateMapDataFromKpiValues;
27
31
  private generateMapDataFromStatistics;
28
32
  private generateMapDataFromRegionalStats;
33
+ private static readonly SIGUNGU_MAP;
34
+ private fetchSigunguData;
35
+ private static readonly GEO_TO_METRO;
36
+ private calculateChangeRate;
37
+ private generateSigunguMapData;
38
+ private onZoomChanged;
39
+ private static readonly METRO_BOUNDS;
40
+ private focusMapOnRegion;
29
41
  private downloadExcel;
30
42
  private onRegionClick;
31
43
  private closeRegionPopup;
@@ -1,3 +1,4 @@
1
+ var KpiDashboardMapPage_1;
1
2
  import { __decorate, __metadata } from "tslib";
2
3
  import gql from 'graphql-tag';
3
4
  import { html, css, nothing } from 'lit';
@@ -9,7 +10,7 @@ import { notify } from '@operato/layout';
9
10
  import './components/kpi-map-panel';
10
11
  import './components/kpi-left-panel';
11
12
  import './components/kpi-region-popup';
12
- let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
13
+ let KpiDashboardMapPage = KpiDashboardMapPage_1 = class KpiDashboardMapPage extends PageView {
13
14
  constructor() {
14
15
  super(...arguments);
15
16
  this.selectedCategory = '전체 KPI';
@@ -18,6 +19,8 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
18
19
  this.endYearMonth = ''; // YYYY-MM 형식
19
20
  this.selectedSectorType = ''; // PUBLIC | PRIVATE
20
21
  this.selectedBuildingUsage = ''; // RESIDENTIAL | NON_RESIDENTIAL
22
+ this.currentZoom = 7.2;
23
+ this.sigunguData = []; // 시군구 단위 데이터
21
24
  this.nationalData = null;
22
25
  this.seoulData = null;
23
26
  this.mapData = null;
@@ -26,6 +29,7 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
26
29
  this.regionalKpiStats = []; // 지역별 KPI 통계
27
30
  // 팝업 관련 상태 추가
28
31
  this.selectedRegion = null;
32
+ this.selectedGeoGroup = null; // 시군구 geo_group 코드
29
33
  this.showRegionPopup = false;
30
34
  }
31
35
  connectedCallback() {
@@ -334,19 +338,7 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
334
338
  };
335
339
  this.mapData = Object.keys(regionCoordinates).map(regionName => {
336
340
  const stat = this.regionalKpiStats.find(s => s.geoGroup === regionName);
337
- // 해당 지역의 월별 데이터를 시간순으로 정렬
338
- const regionMonthlyData = this.monthlyTrendData
339
- .filter(d => d.geoGroup === regionName)
340
- .sort((a, b) => a.yearMonth.localeCompare(b.yearMonth));
341
- // 변동율 계산: 가장 오래된 달과 가장 최근 달 비교
342
- let changeRate = 0;
343
- if (regionMonthlyData.length >= 2) {
344
- const oldestValue = regionMonthlyData[0].avgVal;
345
- const latestValue = regionMonthlyData[regionMonthlyData.length - 1].avgVal;
346
- if (oldestValue !== 0) {
347
- changeRate = ((latestValue - oldestValue) / oldestValue) * 100;
348
- }
349
- }
341
+ const changeRate = this.calculateChangeRate(regionName);
350
342
  return {
351
343
  region: regionName,
352
344
  kpi: stat ? (stat.avgVal * 100).toFixed(1) : '0.0',
@@ -359,12 +351,123 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
359
351
  });
360
352
  console.log('Generated map data from regional stats:', this.mapData.length, 'regions');
361
353
  }
354
+ async fetchSigunguData() {
355
+ try {
356
+ const categoryToKpiName = {
357
+ '전체 KPI': null,
358
+ '일정 성과': 'Y1. 일정성과',
359
+ '비용 성과': 'Y2. 비용성과',
360
+ '품질 성과': 'Y3. 품질성과',
361
+ '안전 성과': 'Y4. 안전성과',
362
+ '환경 성과': 'Y5. 환경성과',
363
+ '생산성 성과': 'Y6. 생산성성과'
364
+ };
365
+ const kpiName = categoryToKpiName[this.selectedCategory];
366
+ const response = await client.query({
367
+ query: gql `
368
+ query GetSigunguStats(
369
+ $kpiName: String
370
+ $startYearMonth: String
371
+ $endYearMonth: String
372
+ $sectorType: String
373
+ $buildingUsage: String
374
+ ) {
375
+ kpiZValueStatsBySigungu(
376
+ kpiName: $kpiName
377
+ startYearMonth: $startYearMonth
378
+ endYearMonth: $endYearMonth
379
+ sectorType: $sectorType
380
+ buildingUsage: $buildingUsage
381
+ ) {
382
+ geoGroup
383
+ avgVal
384
+ minVal
385
+ maxVal
386
+ projectCount
387
+ }
388
+ }
389
+ `,
390
+ variables: {
391
+ kpiName,
392
+ startYearMonth: this.startYearMonth || null,
393
+ endYearMonth: this.endYearMonth || null,
394
+ sectorType: this.selectedSectorType || null,
395
+ buildingUsage: this.selectedBuildingUsage || null
396
+ }
397
+ });
398
+ this.sigunguData = response.data.kpiZValueStatsBySigungu || [];
399
+ this.generateSigunguMapData();
400
+ }
401
+ catch (e) {
402
+ console.error('시군구 데이터 조회 실패:', e);
403
+ }
404
+ }
405
+ calculateChangeRate(metroName) {
406
+ const regionMonthlyData = this.monthlyTrendData
407
+ .filter((d) => d.geoGroup === metroName)
408
+ .sort((a, b) => a.yearMonth.localeCompare(b.yearMonth));
409
+ if (regionMonthlyData.length >= 2) {
410
+ const oldest = regionMonthlyData[0].avgVal;
411
+ const latest = regionMonthlyData[regionMonthlyData.length - 1].avgVal;
412
+ if (oldest !== 0) {
413
+ return ((latest - oldest) / oldest) * 100;
414
+ }
415
+ }
416
+ return 0;
417
+ }
418
+ generateSigunguMapData() {
419
+ const map = KpiDashboardMapPage_1.SIGUNGU_MAP;
420
+ const geoToMetro = KpiDashboardMapPage_1.GEO_TO_METRO;
421
+ this.mapData = this.sigunguData
422
+ .filter((s) => s.geoGroup && map[s.geoGroup])
423
+ .map((s) => {
424
+ const info = map[s.geoGroup];
425
+ const metro = geoToMetro[s.geoGroup] || '';
426
+ const changeRate = this.calculateChangeRate(metro);
427
+ return {
428
+ region: info.name,
429
+ kpi: (s.avgVal * 100).toFixed(1),
430
+ change: changeRate.toFixed(2),
431
+ trend: changeRate >= 0 ? 'up' : 'down',
432
+ lat: info.lat,
433
+ lng: info.lng,
434
+ dataCount: s.projectCount || 0
435
+ };
436
+ });
437
+ }
438
+ onZoomChanged(e) {
439
+ const newZoom = e.detail.zoom;
440
+ const threshold = KpiDashboardMapPage_1.SIGUNGU_ZOOM_THRESHOLD;
441
+ const wasAbove = this.currentZoom >= threshold;
442
+ const isAbove = newZoom >= threshold;
443
+ this.currentZoom = newZoom;
444
+ // 줌 레벨이 threshold를 넘나들 때만 데이터 전환
445
+ if (wasAbove !== isAbove) {
446
+ if (isAbove) {
447
+ this.fetchSigunguData();
448
+ }
449
+ else {
450
+ this.generateMapDataFromRegionalStats();
451
+ }
452
+ }
453
+ }
454
+ focusMapOnRegion(regionName) {
455
+ var _a;
456
+ const bounds = KpiDashboardMapPage_1.METRO_BOUNDS[regionName];
457
+ if (!bounds)
458
+ return;
459
+ const mapPanel = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('kpi-map-panel');
460
+ mapPanel === null || mapPanel === void 0 ? void 0 : mapPanel.focusOnLocation(bounds.lat, bounds.lng, bounds.zoom);
461
+ }
362
462
  downloadExcel() {
363
- // 엑셀 다운로드 기능
364
463
  console.log('엑셀 다운로드');
365
464
  }
366
465
  onRegionClick(region) {
367
466
  this.selectedRegion = region;
467
+ // 시군구 모드인 경우 region name → geo_group 코드 역매핑
468
+ const sigunguMap = KpiDashboardMapPage_1.SIGUNGU_MAP;
469
+ const entry = Object.entries(sigunguMap).find(([, v]) => v.name === region);
470
+ this.selectedGeoGroup = entry ? entry[0] : null;
368
471
  this.showRegionPopup = true;
369
472
  // fetchRegionData는 더 이상 필요하지 않음 (kpi-region-popup에서 직접 데이터 가져옴)
370
473
  // this.fetchRegionData(region)
@@ -445,6 +548,9 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
445
548
  }}
446
549
  @region-click=${(e) => {
447
550
  this.onRegionClick(e.detail.region);
551
+ }}
552
+ @focus-region=${(e) => {
553
+ this.focusMapOnRegion(e.detail.region);
448
554
  }}
449
555
  @monthly-trend-data-loaded=${(e) => {
450
556
  this.monthlyTrendData = e.detail.data;
@@ -467,6 +573,9 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
467
573
  .mapData=${this.mapData}
468
574
  @region-click=${(e) => {
469
575
  this.onRegionClick(e.detail.region);
576
+ }}
577
+ @zoom-changed=${(e) => {
578
+ this.onZoomChanged(e);
470
579
  }}
471
580
  ></kpi-map-panel>
472
581
 
@@ -475,6 +584,7 @@ let KpiDashboardMapPage = class KpiDashboardMapPage extends PageView {
475
584
  ? html `
476
585
  <kpi-region-popup
477
586
  .selectedRegion=${this.selectedRegion}
587
+ .geoGroup=${this.selectedGeoGroup}
478
588
  .selectedCategory=${this.selectedCategory}
479
589
  .monthlyTrendData=${this.monthlyTrendData}
480
590
  .totalKpiStats=${this.totalKpiYStats}
@@ -512,6 +622,111 @@ KpiDashboardMapPage.styles = [
512
622
  }
513
623
  `
514
624
  ];
625
+ KpiDashboardMapPage.SIGUNGU_ZOOM_THRESHOLD = 10;
626
+ // 시군구별 좌표 (geo_group 2자리 코드 → { name, lat, lng })
627
+ KpiDashboardMapPage.SIGUNGU_MAP = {
628
+ '01': { name: '서울 종로구', lat: 37.5735, lng: 126.9790 },
629
+ '02': { name: '서울 중구', lat: 37.5641, lng: 126.9979 },
630
+ '03': { name: '서울 용산구', lat: 37.5326, lng: 126.9906 },
631
+ '04': { name: '서울 성동구', lat: 37.5634, lng: 127.0369 },
632
+ '05': { name: '서울 광진구', lat: 37.5385, lng: 127.0823 },
633
+ '06': { name: '서울 강남구', lat: 37.5172, lng: 127.0473 },
634
+ '07': { name: '서울 송파구', lat: 37.5145, lng: 127.1060 },
635
+ '08': { name: '서울 강서구', lat: 37.5510, lng: 126.8495 },
636
+ '10': { name: '수원시', lat: 37.2636, lng: 127.0286 },
637
+ '11': { name: '성남시', lat: 37.4200, lng: 127.1265 },
638
+ '12': { name: '고양시', lat: 37.6584, lng: 126.8320 },
639
+ '13': { name: '용인시', lat: 37.2411, lng: 127.1776 },
640
+ '14': { name: '부천시', lat: 37.5034, lng: 126.7660 },
641
+ '15': { name: '안산시', lat: 37.3219, lng: 126.8309 },
642
+ '16': { name: '화성시', lat: 37.1995, lng: 126.8312 },
643
+ '17': { name: '평택시', lat: 36.9921, lng: 127.1127 },
644
+ '18': { name: '파주시', lat: 37.7599, lng: 126.7799 },
645
+ '21': { name: '인천 남동구', lat: 37.4488, lng: 126.7308 },
646
+ '22': { name: '인천 부평구', lat: 37.5076, lng: 126.7218 },
647
+ '23': { name: '인천 서구', lat: 37.5458, lng: 126.6760 },
648
+ '24': { name: '춘천시', lat: 37.8813, lng: 127.7300 },
649
+ '25': { name: '원주시', lat: 37.3422, lng: 127.9202 },
650
+ '26': { name: '강릉시', lat: 37.7519, lng: 128.8761 },
651
+ '27': { name: '청주시', lat: 36.6424, lng: 127.4890 },
652
+ '28': { name: '충주시', lat: 36.9910, lng: 127.9259 },
653
+ '29': { name: '제천시', lat: 37.1327, lng: 128.1910 },
654
+ '30': { name: '세종시', lat: 36.4875, lng: 127.2816 },
655
+ '31': { name: '천안시', lat: 36.8151, lng: 127.1139 },
656
+ '32': { name: '아산시', lat: 36.7898, lng: 127.0018 },
657
+ '33': { name: '속초시', lat: 38.2071, lng: 128.5918 },
658
+ '34': { name: '대전 서구', lat: 36.3555, lng: 127.3835 },
659
+ '35': { name: '대전 유성구', lat: 36.3622, lng: 127.3561 },
660
+ '36': { name: '포항시', lat: 36.0190, lng: 129.3435 },
661
+ '37': { name: '경주시', lat: 35.8562, lng: 129.2247 },
662
+ '38': { name: '구미시', lat: 36.1196, lng: 128.3443 },
663
+ '39': { name: '안동시', lat: 36.5684, lng: 128.7294 },
664
+ '40': { name: '김천시', lat: 36.1398, lng: 128.1136 },
665
+ '41': { name: '대구 중구', lat: 35.8693, lng: 128.6062 },
666
+ '42': { name: '대구 수성구', lat: 35.8584, lng: 128.6308 },
667
+ '43': { name: '대구 달서구', lat: 35.8299, lng: 128.5327 },
668
+ '44': { name: '울산 남구', lat: 35.5444, lng: 129.3304 },
669
+ '45': { name: '울산 중구', lat: 35.5696, lng: 129.3324 },
670
+ '46': { name: '부산 중구', lat: 35.1060, lng: 129.0324 },
671
+ '47': { name: '부산 해운대구', lat: 35.1631, lng: 129.1636 },
672
+ '48': { name: '부산 사하구', lat: 35.1046, lng: 128.9751 },
673
+ '49': { name: '부산 금정구', lat: 35.2431, lng: 129.0923 },
674
+ '50': { name: '창원시', lat: 35.2281, lng: 128.6812 },
675
+ '51': { name: '김해시', lat: 35.2285, lng: 128.8894 },
676
+ '52': { name: '진주시', lat: 35.1798, lng: 128.1076 },
677
+ '53': { name: '양산시', lat: 35.3350, lng: 129.0373 },
678
+ '54': { name: '전주시', lat: 35.8242, lng: 127.1480 },
679
+ '55': { name: '익산시', lat: 35.9483, lng: 126.9576 },
680
+ '56': { name: '군산시', lat: 35.9676, lng: 126.7369 },
681
+ '57': { name: '목포시', lat: 34.8118, lng: 126.3922 },
682
+ '58': { name: '여수시', lat: 34.7604, lng: 127.6622 },
683
+ '59': { name: '순천시', lat: 34.9506, lng: 127.4873 },
684
+ '61': { name: '광주 서구', lat: 35.1525, lng: 126.8895 },
685
+ '62': { name: '광주 북구', lat: 35.1744, lng: 126.9120 },
686
+ '63': { name: '제주시', lat: 33.4996, lng: 126.5312 }
687
+ };
688
+ // geo_group 코드 → 광역시도 매핑
689
+ KpiDashboardMapPage.GEO_TO_METRO = {
690
+ '01': '서울특별시', '02': '서울특별시', '03': '서울특별시', '04': '서울특별시',
691
+ '05': '서울특별시', '06': '서울특별시', '07': '서울특별시', '08': '서울특별시',
692
+ '10': '경기도', '11': '경기도', '12': '경기도', '13': '경기도', '14': '경기도',
693
+ '15': '경기도', '16': '경기도', '17': '경기도', '18': '경기도',
694
+ '21': '인천광역시', '22': '인천광역시', '23': '인천광역시',
695
+ '24': '강원도', '25': '강원도', '26': '강원도', '33': '강원도',
696
+ '27': '충청북도', '28': '충청북도', '29': '충청북도',
697
+ '30': '세종특별자치시',
698
+ '31': '충청남도', '32': '충청남도',
699
+ '34': '대전광역시', '35': '대전광역시',
700
+ '36': '경상북도', '37': '경상북도', '38': '경상북도', '39': '경상북도', '40': '경상북도',
701
+ '41': '대구광역시', '42': '대구광역시', '43': '대구광역시',
702
+ '44': '울산광역시', '45': '울산광역시',
703
+ '46': '부산광역시', '47': '부산광역시', '48': '부산광역시', '49': '부산광역시',
704
+ '50': '경상남도', '51': '경상남도', '52': '경상남도', '53': '경상남도',
705
+ '54': '전라북도', '55': '전라북도', '56': '전라북도',
706
+ '57': '전라남도', '58': '전라남도', '59': '전라남도',
707
+ '61': '광주광역시', '62': '광주광역시',
708
+ '63': '제주특별자치도'
709
+ };
710
+ // 광역시도별 중심 좌표 + 줌 레벨 (시군구가 모두 보이는 수준)
711
+ KpiDashboardMapPage.METRO_BOUNDS = {
712
+ 서울특별시: { lat: 37.5665, lng: 126.978, zoom: 11 },
713
+ 부산광역시: { lat: 35.1796, lng: 129.0756, zoom: 11 },
714
+ 대구광역시: { lat: 35.8714, lng: 128.6014, zoom: 11 },
715
+ 인천광역시: { lat: 37.4563, lng: 126.7052, zoom: 11 },
716
+ 광주광역시: { lat: 35.1595, lng: 126.8526, zoom: 12 },
717
+ 대전광역시: { lat: 36.3504, lng: 127.3845, zoom: 12 },
718
+ 울산광역시: { lat: 35.5384, lng: 129.3114, zoom: 11 },
719
+ 세종특별자치시: { lat: 36.4875, lng: 127.2816, zoom: 12 },
720
+ 경기도: { lat: 37.4138, lng: 127.0183, zoom: 9 },
721
+ 강원도: { lat: 37.8228, lng: 128.1555, zoom: 9 },
722
+ 충청북도: { lat: 36.8, lng: 127.7, zoom: 9 },
723
+ 충청남도: { lat: 36.5184, lng: 126.8, zoom: 10 },
724
+ 전라북도: { lat: 35.7175, lng: 127.153, zoom: 10 },
725
+ 전라남도: { lat: 34.8679, lng: 126.991, zoom: 9 },
726
+ 경상북도: { lat: 36.4919, lng: 128.8889, zoom: 9 },
727
+ 경상남도: { lat: 35.4606, lng: 128.2132, zoom: 9 },
728
+ 제주특별자치도: { lat: 33.4996, lng: 126.5312, zoom: 11 }
729
+ };
515
730
  __decorate([
516
731
  state(),
517
732
  __metadata("design:type", Object)
@@ -536,6 +751,14 @@ __decorate([
536
751
  state(),
537
752
  __metadata("design:type", Object)
538
753
  ], KpiDashboardMapPage.prototype, "selectedBuildingUsage", void 0);
754
+ __decorate([
755
+ state(),
756
+ __metadata("design:type", Object)
757
+ ], KpiDashboardMapPage.prototype, "currentZoom", void 0);
758
+ __decorate([
759
+ state(),
760
+ __metadata("design:type", Array)
761
+ ], KpiDashboardMapPage.prototype, "sigunguData", void 0);
539
762
  __decorate([
540
763
  state(),
541
764
  __metadata("design:type", Object)
@@ -564,11 +787,15 @@ __decorate([
564
787
  state(),
565
788
  __metadata("design:type", Object)
566
789
  ], KpiDashboardMapPage.prototype, "selectedRegion", void 0);
790
+ __decorate([
791
+ state(),
792
+ __metadata("design:type", Object)
793
+ ], KpiDashboardMapPage.prototype, "selectedGeoGroup", void 0);
567
794
  __decorate([
568
795
  state(),
569
796
  __metadata("design:type", Object)
570
797
  ], KpiDashboardMapPage.prototype, "showRegionPopup", void 0);
571
- KpiDashboardMapPage = __decorate([
798
+ KpiDashboardMapPage = KpiDashboardMapPage_1 = __decorate([
572
799
  customElement('kpi-dashboard-map')
573
800
  ], KpiDashboardMapPage);
574
801
  export { KpiDashboardMapPage };