@dssp/dkpi 1.0.0-alpha.86 → 1.0.0-alpha.88

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 (65) hide show
  1. package/_index.html +4 -4
  2. package/assets/helps/index.md +1 -1
  3. package/assets/manifest.json +2 -2
  4. package/dist-client/components/kpi-boxplot-chart.d.ts +7 -0
  5. package/dist-client/components/kpi-boxplot-chart.js +20 -5
  6. package/dist-client/components/kpi-boxplot-chart.js.map +1 -1
  7. package/dist-client/components/kpi-lookup-chart.js +1 -17
  8. package/dist-client/components/kpi-lookup-chart.js.map +1 -1
  9. package/dist-client/components/kpi-radar-chart.js +2 -2
  10. package/dist-client/components/kpi-radar-chart.js.map +1 -1
  11. package/dist-client/components/kpi-single-boxplot-chart.d.ts +7 -0
  12. package/dist-client/components/kpi-single-boxplot-chart.js +27 -26
  13. package/dist-client/components/kpi-single-boxplot-chart.js.map +1 -1
  14. package/dist-client/components/kpi-step-lookup-chart.d.ts +33 -0
  15. package/dist-client/components/kpi-step-lookup-chart.js +181 -0
  16. package/dist-client/components/kpi-step-lookup-chart.js.map +1 -0
  17. package/dist-client/components/kpi-trend-chart.js +2 -12
  18. package/dist-client/components/kpi-trend-chart.js.map +1 -1
  19. package/dist-client/google-map/common-google-map.js +5 -1
  20. package/dist-client/google-map/common-google-map.js.map +1 -1
  21. package/dist-client/pages/kpi-admin/dssp-kpi-overview.d.ts +2 -1
  22. package/dist-client/pages/kpi-admin/dssp-kpi-overview.js +24 -9
  23. package/dist-client/pages/kpi-admin/dssp-kpi-overview.js.map +1 -1
  24. package/dist-client/pages/kpi-admin/kpi-system-guide.js +311 -158
  25. package/dist-client/pages/kpi-admin/kpi-system-guide.js.map +1 -1
  26. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +6 -0
  27. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +110 -50
  28. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
  29. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +0 -9
  30. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +6 -91
  31. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
  32. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +2 -0
  33. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +148 -68
  34. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
  35. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +85 -41
  36. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
  37. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +15 -7
  38. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
  39. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +16 -25
  40. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -1
  41. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +9 -13
  42. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +1 -1
  43. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js +9 -15
  44. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js.map +1 -1
  45. package/dist-client/pages/sv-project-complete.js +7 -11
  46. package/dist-client/pages/sv-project-complete.js.map +1 -1
  47. package/dist-client/pages/sv-project-completed-list.js +4 -4
  48. package/dist-client/pages/sv-project-completed-list.js.map +1 -1
  49. package/dist-client/pages/sv-project-detail.d.ts +1 -0
  50. package/dist-client/pages/sv-project-detail.js +94 -82
  51. package/dist-client/pages/sv-project-detail.js.map +1 -1
  52. package/dist-client/pages/sv-project-list.js +15 -12
  53. package/dist-client/pages/sv-project-list.js.map +1 -1
  54. package/dist-client/tsconfig.tsbuildinfo +1 -1
  55. package/dist-client/viewparts/menu-tools.js +17 -3
  56. package/dist-client/viewparts/menu-tools.js.map +1 -1
  57. package/dist-server/service/kpi-stat/kpi-stat-query.js +20 -19
  58. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -1
  59. package/dist-server/tsconfig.tsbuildinfo +1 -1
  60. package/openapi/unstable.yaml +2 -2
  61. package/package.json +3 -3
  62. package/schema.graphql +20 -0
  63. package/translations/ko.json +2 -2
  64. package/views/auth-page.html +4 -4
  65. package/views/public/home.html +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"common-google-map.js","sourceRoot":"","sources":["../../client/google-map/common-google-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport GoogleMapLoader from './google-map-loader.js'\n\ndeclare global {\n interface Window {\n google: any\n markerClusterer?: any\n }\n}\n\ndeclare const google: any\n\ndeclare namespace google.maps {\n interface MapsLibrary {\n Map: any\n InfoWindow: any\n }\n\n interface MarkerLibrary {\n AdvancedMarkerElement: any\n PinElement: any\n }\n}\n\n@customElement('common-google-map')\nexport class CommonGoogleMap extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n }\n\n [map] {\n flex: 1;\n }\n\n .gm-style .gm-style-iw-c {\n padding: 0;\n }\n\n .gm-style .gm-style-iw-d {\n overflow: auto !important;\n }\n .gm-style .gm-style-iw-d + button {\n top: 0 !important;\n right: 0 !important;\n }\n `\n ]\n\n @property({ type: Object }) center\n @property({ type: Number }) zoom\n @property({ type: Array }) locations: any[] = []\n @property({ type: Object }) focused\n @property({ type: Array }) polygons\n @property({ type: Array }) polylines\n @property({ type: Array }) markers\n @property({ type: Array }) boundCoords\n @property({ type: Object }) controls\n @property({ type: Number }) clusterZoom = 10\n\n @state() map: any = null\n @state() defaultCenter: any = { lat: 36.5, lng: 127.5 }\n private _infoWindow: any = null\n private _markerClusterer: any = null\n private _buildMarkersTimer: any = null\n\n get anchor() {\n return this.renderRoot.querySelector('[map]')\n }\n\n async readyMap() {\n await GoogleMapLoader.load()\n\n // MarkerClusterer 라이브러리 로드\n if (!window.markerClusterer) {\n await GoogleMapLoader.loadMarkerClusterer()\n }\n\n if (this.map) {\n return\n }\n\n // DOM이 준비될 때까지 기다림\n await this.updateComplete\n\n // anchor가 준비될 때까지 기다림\n let attempts = 0\n const maxAttempts = 20\n while (attempts < maxAttempts) {\n const anchor = this.anchor as HTMLElement\n if (anchor && anchor.offsetWidth > 0) {\n break\n }\n await new Promise(resolve => setTimeout(resolve, 50))\n attempts++\n }\n\n if (!this.anchor) {\n console.error('Map anchor element not found')\n return\n }\n\n var show = async (center, zoom) => {\n try {\n // Google Maps 최신 API 사용\n const { Map } = (await google.maps.importLibrary('maps')) as google.maps.MapsLibrary\n\n const mapOptions = {\n zoom,\n center,\n mapId: 'DEMO_MAP_ID'\n }\n\n // controls 속성이 있으면 지도 옵션에 추가\n if (this.controls) {\n Object.assign(mapOptions, this.controls)\n }\n\n const map = new Map(this.anchor, mapOptions)\n\n this.markers && this.markers.forEach(marker => marker.setMap(map))\n\n this.map = map\n\n this.dispatchEvent(\n new CustomEvent('map-change', {\n detail: this.map\n })\n )\n\n // 줌 변경 이벤트 전달\n map.addListener('zoom_changed', () => {\n this.dispatchEvent(\n new CustomEvent('zoom-changed', {\n detail: { zoom: map.getZoom() },\n bubbles: true,\n composed: true\n })\n )\n })\n\n this.resetBounds()\n } catch (e) {\n console.error(e)\n }\n }\n\n var { center, zoom = 10 } = this\n\n /* center 속성이 설정되어있지 않으면, 현재 위치를 구해서 지도의 center로 설정한다. */\n if (!center && 'geolocation' in navigator && !this.boundCoords?.length) {\n navigator.geolocation.getCurrentPosition(\n ({ coords: { latitude: lat, longitude: lng } }) => show({ lat, lng }, zoom),\n err => {\n console.warn(`navigator.geolocation.getCurrentPosition failed. (${err.code}): ${err.message}`)\n show(this.defaultCenter, zoom)\n },\n {\n /* https://stackoverflow.com/questions/3397585/navigator-geolocation-getcurrentposition-sometimes-works-sometimes-doesnt */\n timeout: 500\n }\n )\n } else {\n show(center, zoom)\n }\n }\n\n async buildMarkers(locations: any[] = []) {\n if (!this.map) {\n return\n }\n\n if (this.markers) {\n this.markers.forEach(marker => marker.setMap(null))\n this.markers = []\n }\n\n // 기존 클러스터 제거\n if (this._markerClusterer) {\n this._markerClusterer.clearMarkers()\n this._markerClusterer = null\n }\n\n // Google Maps 최신 API 사용\n const { AdvancedMarkerElement, PinElement } = (await google.maps.importLibrary(\n 'marker'\n )) as google.maps.MarkerLibrary\n\n this.markers = locations\n .map(location => {\n // location 객체가 유효한지 확인\n if (!location || typeof location !== 'object') {\n console.warn('Invalid location object:', location)\n return null\n }\n\n // lat, lng 값이 유효한지 확인\n const lat = parseFloat(location.lat)\n const lng = parseFloat(location.lng)\n\n if (isNaN(lat) || isNaN(lng)) {\n console.warn('Invalid lat/lng values:', location)\n return null\n }\n\n // LatLng 객체 생성\n const position = new google.maps.LatLng(lat, lng)\n\n // 커스텀 마커 콘텐츠가 있으면 사용\n let markerElement\n if (location.markerContent) {\n // HTML 문자열을 DOM 요소로 변환\n const tempDiv = document.createElement('div')\n tempDiv.innerHTML = location.markerContent\n markerElement = tempDiv.firstElementChild\n } else {\n // 기본 핀 사용\n markerElement = new PinElement({\n background: '#1976d2',\n borderColor: '#1565c0',\n glyphColor: '#ffffff',\n scale: 1.2\n })\n }\n\n // AdvancedMarkerElement 사용\n const marker = new AdvancedMarkerElement({\n position: position,\n map: this.map,\n content: markerElement\n })\n\n marker.addListener('click', () => {\n // InfoWindow 대신 커스텀 이벤트 발생\n if (location?.region) {\n this.dispatchEvent(\n new CustomEvent('region-click', {\n detail: { region: location.region },\n bubbles: true,\n composed: true\n })\n )\n }\n })\n\n return marker\n })\n .filter(marker => marker !== null) // null 마커 제거\n\n // MarkerClusterer 미사용 — 마커 수가 적으므로 직접 지도에 표시\n }\n\n get infoWindow() {\n if (!this._infoWindow && this.map) {\n this._infoWindow = new google.maps.InfoWindow({\n content: 'loading...'\n })\n }\n\n return this._infoWindow\n }\n\n setFocus(focus, icon) {\n focus.setZIndex(1)\n focus.setIcon(icon)\n }\n\n resetFocus(focus, icon) {\n focus.setZIndex(0)\n focus.setIcon(icon)\n }\n\n async changeFocus(after, before) {\n await this.readyMap()\n\n // map이 준비되지 않았으면 포커스 변경하지 않음\n if (!this.map) {\n return\n }\n\n var locations = this.locations || []\n\n if (before) {\n var idx = locations.findIndex(location => {\n // location 객체의 구조를 안전하게 확인\n const beforePos = before?.position\n const locationPos = location?.position\n\n return (\n location?.name == before?.name && locationPos?.lat == beforePos?.lat && locationPos?.lng == beforePos?.lng\n )\n })\n idx !== -1 && this.markers && this.resetFocus(this.markers[idx], locations[idx]?.icon)\n }\n\n if (after) {\n var idx = locations.findIndex(location => {\n // location 객체의 구조를 안전하게 확인\n const afterPos = after?.position\n const locationPos = location?.position\n\n return location?.name == after?.name && locationPos?.lat == afterPos?.lat && locationPos?.lng == afterPos?.lng\n })\n idx !== -1 && this.markers && this.setFocus(this.markers[idx], after?.icon)\n }\n }\n\n async updated(changes) {\n if (!this.map) {\n await this.readyMap()\n }\n\n if (changes.has('locations')) {\n // 디바운스: 연속된 업데이트를 하나로 묶음\n if (this._buildMarkersTimer) {\n clearTimeout(this._buildMarkersTimer)\n }\n this._buildMarkersTimer = setTimeout(() => {\n this.buildMarkers(this.locations)\n this._buildMarkersTimer = null\n }, 500)\n }\n\n if (changes.has('focused')) {\n this.changeFocus(this.focused, changes.get('focused'))\n }\n\n if (changes.has('center')) {\n this.map.setCenter(this.center)\n }\n\n if (changes.has('controls')) {\n // controls가 변경되면 기존 지도의 옵션만 업데이트\n if (this.map && this.controls) {\n // Google Maps API의 setOptions 메서드 사용\n this.map.setOptions(this.controls)\n }\n }\n\n if (changes.has('polygons')) {\n ;(changes.get('polygons') || []).forEach(geofence => geofence.setMap(null))\n ;(this.polygons || []).forEach(geofence => geofence.setMap(this.map))\n }\n\n if (changes.has('polylines')) {\n ;(changes.get('polylines') || []).forEach(polyline => polyline.setMap(null))\n ;(this.polylines || []).forEach(polyline => polyline.setMap(this.map))\n }\n\n if (changes.has('markers')) {\n ;(changes.get('markers') || []).forEach(marker => marker.setMap(null))\n ;(this.markers || []).forEach(marker => marker.setMap(this.map))\n }\n\n if (changes.has('boundCoords')) {\n this.resetBounds()\n }\n\n // 클러스터링 설정 변경 시 마커 재구성\n if (changes.has('clusterZoom')) {\n this.buildMarkers(this.locations)\n }\n }\n\n render() {\n return html` <div map></div> `\n }\n\n resetBounds() {\n if (!this.boundCoords || this.boundCoords.length < 1 || !this.map) {\n return\n }\n\n var bounds = new google.maps.LatLngBounds()\n this.boundCoords.forEach(coord => bounds.extend(coord))\n this.map.fitBounds(bounds)\n }\n}\n"]}
1
+ {"version":3,"file":"common-google-map.js","sourceRoot":"","sources":["../../client/google-map/common-google-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport GoogleMapLoader from './google-map-loader.js'\n\ndeclare global {\n interface Window {\n google: any\n markerClusterer?: any\n }\n}\n\ndeclare const google: any\n\ndeclare namespace google.maps {\n interface MapsLibrary {\n Map: any\n InfoWindow: any\n }\n\n interface MarkerLibrary {\n AdvancedMarkerElement: any\n PinElement: any\n }\n}\n\n@customElement('common-google-map')\nexport class CommonGoogleMap extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n }\n\n [map] {\n flex: 1;\n }\n\n .gm-style .gm-style-iw-c {\n padding: 0;\n }\n\n .gm-style .gm-style-iw-d {\n overflow: auto !important;\n }\n .gm-style .gm-style-iw-d + button {\n top: 0 !important;\n right: 0 !important;\n }\n `\n ]\n\n @property({ type: Object }) center\n @property({ type: Number }) zoom\n @property({ type: Array }) locations: any[] = []\n @property({ type: Object }) focused\n @property({ type: Array }) polygons\n @property({ type: Array }) polylines\n @property({ type: Array }) markers\n @property({ type: Array }) boundCoords\n @property({ type: Object }) controls\n @property({ type: Number }) clusterZoom = 10\n\n @state() map: any = null\n @state() defaultCenter: any = { lat: 36.5, lng: 127.5 }\n private _infoWindow: any = null\n private _markerClusterer: any = null\n private _buildMarkersTimer: any = null\n\n get anchor() {\n return this.renderRoot.querySelector('[map]')\n }\n\n async readyMap() {\n await GoogleMapLoader.load()\n\n // MarkerClusterer 라이브러리 로드\n if (!window.markerClusterer) {\n await GoogleMapLoader.loadMarkerClusterer()\n }\n\n if (this.map) {\n return\n }\n\n // DOM이 준비될 때까지 기다림\n await this.updateComplete\n\n // anchor가 준비될 때까지 기다림\n let attempts = 0\n const maxAttempts = 20\n while (attempts < maxAttempts) {\n const anchor = this.anchor as HTMLElement\n if (anchor && anchor.offsetWidth > 0) {\n break\n }\n await new Promise(resolve => setTimeout(resolve, 50))\n attempts++\n }\n\n if (!this.anchor) {\n console.error('Map anchor element not found')\n return\n }\n\n var show = async (center, zoom) => {\n try {\n // Google Maps 최신 API 사용\n const { Map } = (await google.maps.importLibrary('maps')) as google.maps.MapsLibrary\n\n const mapOptions = {\n zoom,\n center,\n mapId: 'DEMO_MAP_ID'\n }\n\n // controls 속성이 있으면 지도 옵션에 추가\n if (this.controls) {\n Object.assign(mapOptions, this.controls)\n }\n\n const map = new Map(this.anchor, mapOptions)\n\n this.markers && this.markers.forEach(marker => marker.setMap(map))\n\n this.map = map\n\n this.dispatchEvent(\n new CustomEvent('map-change', {\n detail: this.map\n })\n )\n\n // 줌 변경 이벤트 전달\n map.addListener('zoom_changed', () => {\n this.dispatchEvent(\n new CustomEvent('zoom-changed', {\n detail: { zoom: map.getZoom() },\n bubbles: true,\n composed: true\n })\n )\n })\n\n this.resetBounds()\n } catch (e) {\n console.error(e)\n }\n }\n\n var { center, zoom = 10 } = this\n\n /* center 속성이 설정되어있지 않으면, 현재 위치를 구해서 지도의 center로 설정한다. */\n if (!center && 'geolocation' in navigator && !this.boundCoords?.length) {\n navigator.geolocation.getCurrentPosition(\n ({ coords: { latitude: lat, longitude: lng } }) => show({ lat, lng }, zoom),\n err => {\n console.warn(`navigator.geolocation.getCurrentPosition failed. (${err.code}): ${err.message}`)\n show(this.defaultCenter, zoom)\n },\n {\n /* https://stackoverflow.com/questions/3397585/navigator-geolocation-getcurrentposition-sometimes-works-sometimes-doesnt */\n timeout: 500\n }\n )\n } else {\n show(center, zoom)\n }\n }\n\n async buildMarkers(locations: any[] = []) {\n if (!this.map) {\n return\n }\n\n if (this.markers) {\n this.markers.forEach(marker => marker.setMap(null))\n this.markers = []\n }\n\n // 기존 클러스터 제거\n if (this._markerClusterer) {\n this._markerClusterer.clearMarkers()\n this._markerClusterer = null\n }\n\n // Google Maps 최신 API 사용\n const { AdvancedMarkerElement, PinElement } = (await google.maps.importLibrary(\n 'marker'\n )) as google.maps.MarkerLibrary\n\n this.markers = locations\n .map(location => {\n // location 객체가 유효한지 확인\n if (!location || typeof location !== 'object') {\n console.warn('Invalid location object:', location)\n return null\n }\n\n // lat, lng 값이 유효한지 확인\n const lat = parseFloat(location.lat)\n const lng = parseFloat(location.lng)\n\n if (isNaN(lat) || isNaN(lng)) {\n console.warn('Invalid lat/lng values:', location)\n return null\n }\n\n // LatLng 객체 생성\n const position = new google.maps.LatLng(lat, lng)\n\n // 커스텀 마커 콘텐츠가 있으면 사용\n let markerElement\n if (location.markerContent) {\n // HTML 문자열을 DOM 요소로 변환\n const tempDiv = document.createElement('div')\n tempDiv.innerHTML = location.markerContent\n markerElement = tempDiv.firstElementChild\n } else {\n // 기본 핀 사용\n markerElement = new PinElement({\n background: '#1976d2',\n borderColor: '#1565c0',\n glyphColor: '#ffffff',\n scale: 1.2\n })\n }\n\n // AdvancedMarkerElement 사용\n // collisionBehavior: 레이블(마커)이 서로 겹치면 우선순위 낮은 쪽을 자동 숨김 →\n // 시도/시군구 레이블이 축척에 따라 겹쳐 보이는 문제 완화.\n const marker = new AdvancedMarkerElement({\n position: position,\n map: this.map,\n content: markerElement,\n collisionBehavior: (google.maps as any).CollisionBehavior?.OPTIONAL_AND_HIDES_LOWER_PRIORITY\n })\n\n marker.addListener('click', () => {\n // InfoWindow 대신 커스텀 이벤트 발생\n if (location?.region) {\n this.dispatchEvent(\n new CustomEvent('region-click', {\n detail: { region: location.region },\n bubbles: true,\n composed: true\n })\n )\n }\n })\n\n return marker\n })\n .filter(marker => marker !== null) // null 마커 제거\n\n // MarkerClusterer 미사용 — 마커 수가 적으므로 직접 지도에 표시\n }\n\n get infoWindow() {\n if (!this._infoWindow && this.map) {\n this._infoWindow = new google.maps.InfoWindow({\n content: 'loading...'\n })\n }\n\n return this._infoWindow\n }\n\n setFocus(focus, icon) {\n focus.setZIndex(1)\n focus.setIcon(icon)\n }\n\n resetFocus(focus, icon) {\n focus.setZIndex(0)\n focus.setIcon(icon)\n }\n\n async changeFocus(after, before) {\n await this.readyMap()\n\n // map이 준비되지 않았으면 포커스 변경하지 않음\n if (!this.map) {\n return\n }\n\n var locations = this.locations || []\n\n if (before) {\n var idx = locations.findIndex(location => {\n // location 객체의 구조를 안전하게 확인\n const beforePos = before?.position\n const locationPos = location?.position\n\n return (\n location?.name == before?.name && locationPos?.lat == beforePos?.lat && locationPos?.lng == beforePos?.lng\n )\n })\n idx !== -1 && this.markers && this.resetFocus(this.markers[idx], locations[idx]?.icon)\n }\n\n if (after) {\n var idx = locations.findIndex(location => {\n // location 객체의 구조를 안전하게 확인\n const afterPos = after?.position\n const locationPos = location?.position\n\n return location?.name == after?.name && locationPos?.lat == afterPos?.lat && locationPos?.lng == afterPos?.lng\n })\n idx !== -1 && this.markers && this.setFocus(this.markers[idx], after?.icon)\n }\n }\n\n async updated(changes) {\n if (!this.map) {\n await this.readyMap()\n }\n\n if (changes.has('locations')) {\n // 디바운스: 연속된 업데이트를 하나로 묶음\n if (this._buildMarkersTimer) {\n clearTimeout(this._buildMarkersTimer)\n }\n this._buildMarkersTimer = setTimeout(() => {\n this.buildMarkers(this.locations)\n this._buildMarkersTimer = null\n }, 500)\n }\n\n if (changes.has('focused')) {\n this.changeFocus(this.focused, changes.get('focused'))\n }\n\n if (changes.has('center')) {\n this.map.setCenter(this.center)\n }\n\n if (changes.has('controls')) {\n // controls가 변경되면 기존 지도의 옵션만 업데이트\n if (this.map && this.controls) {\n // Google Maps API의 setOptions 메서드 사용\n this.map.setOptions(this.controls)\n }\n }\n\n if (changes.has('polygons')) {\n ;(changes.get('polygons') || []).forEach(geofence => geofence.setMap(null))\n ;(this.polygons || []).forEach(geofence => geofence.setMap(this.map))\n }\n\n if (changes.has('polylines')) {\n ;(changes.get('polylines') || []).forEach(polyline => polyline.setMap(null))\n ;(this.polylines || []).forEach(polyline => polyline.setMap(this.map))\n }\n\n if (changes.has('markers')) {\n ;(changes.get('markers') || []).forEach(marker => marker.setMap(null))\n ;(this.markers || []).forEach(marker => marker.setMap(this.map))\n }\n\n if (changes.has('boundCoords')) {\n this.resetBounds()\n }\n\n // 클러스터링 설정 변경 시 마커 재구성\n if (changes.has('clusterZoom')) {\n this.buildMarkers(this.locations)\n }\n }\n\n render() {\n return html` <div map></div> `\n }\n\n resetBounds() {\n if (!this.boundCoords || this.boundCoords.length < 1 || !this.map) {\n return\n }\n\n var bounds = new google.maps.LatLngBounds()\n this.boundCoords.forEach(coord => bounds.extend(coord))\n this.map.fitBounds(bounds)\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { KpiOverview } from '@things-factory/kpi/dist-client/pages/kpi/kpi-overview.js';
2
2
  import '../../components/kpi-lookup-chart';
3
3
  import '../../components/kpi-2d-lookup-chart';
4
+ import '../../components/kpi-step-lookup-chart';
4
5
  /**
5
6
  * KPI scoreType 정의 — value → score 변환 방식
6
7
  *
@@ -14,7 +15,7 @@ import '../../components/kpi-2d-lookup-chart';
14
15
  * 예: X13(일정 이탈 수준) = 공정률 × 편차율 → 1~5점
15
16
  * → 히트맵 차트로 표시
16
17
  * ASSESSMENT — 감리자 직접 평가, value(1~5) = score (grade table 불필요)
17
- * 예: X14(일정성과 수준 평가), X23(비용성과), X35(품질성과) 등
18
+ * 예: X14(일정성과 정성 평가), X23(비용성과), X35(품질성과) 등
18
19
  * → 등급 기준 설명만 표시 (차트 없음)
19
20
  *
20
21
  * Note: DIRECT와 ASSESSMENT는 모두 value=score이지만,
@@ -6,6 +6,7 @@ import gql from 'graphql-tag';
6
6
  import { KpiOverview } from '@things-factory/kpi/dist-client/pages/kpi/kpi-overview.js';
7
7
  import '../../components/kpi-lookup-chart';
8
8
  import '../../components/kpi-2d-lookup-chart';
9
+ import '../../components/kpi-step-lookup-chart';
9
10
  const GET_KPI_OVERVIEW_EXT = gql `
10
11
  query {
11
12
  kpiCategories: kpisLevel1 {
@@ -40,7 +41,7 @@ const GET_KPI_OVERVIEW_EXT = gql `
40
41
  * 예: X13(일정 이탈 수준) = 공정률 × 편차율 → 1~5점
41
42
  * → 히트맵 차트로 표시
42
43
  * ASSESSMENT — 감리자 직접 평가, value(1~5) = score (grade table 불필요)
43
- * 예: X14(일정성과 수준 평가), X23(비용성과), X35(품질성과) 등
44
+ * 예: X14(일정성과 정성 평가), X23(비용성과), X35(품질성과) 등
44
45
  * → 등급 기준 설명만 표시 (차트 없음)
45
46
  *
46
47
  * Note: DIRECT와 ASSESSMENT는 모두 value=score이지만,
@@ -83,8 +84,8 @@ let DsspKpiOverview = class DsspKpiOverview extends KpiOverview {
83
84
  <div class="overview-left">
84
85
  <div class="overview-title">KPI개요</div>
85
86
  <div class="overview-desc">
86
- 건설현장 KPI관리 시스템은 프로젝트 성과를 측정하고, 모니터링하여 효율적인 공정 관리를 지원합니다. 주요 지표를
87
- 통해 현장 생산성, 품질, 안전 등을 실시간으로 파악할 수 있습니다.
87
+ 건설프로젝트 KPI관리 시스템은 프로젝트 성과를 측정하고, 모니터링하여 효율적인 공정 관리를 지원합니다. 주요 지표를 통해
88
+ 프로젝트 생산성, 품질, 안전 등을 실시간으로 파악할 수 있습니다.
88
89
  </div>
89
90
  </div>
90
91
  </div>
@@ -144,9 +145,7 @@ let DsspKpiOverview = class DsspKpiOverview extends KpiOverview {
144
145
  : ''}
145
146
  ${this._renderTypeInfo(kpi)}
146
147
  </div>
147
- <div class="x-chart">
148
- ${this._renderGradesContent(kpi)}
149
- </div>
148
+ <div class="x-chart">${this._renderGradesContent(kpi)}</div>
150
149
  </div>
151
150
  `;
152
151
  }
@@ -164,11 +163,27 @@ let DsspKpiOverview = class DsspKpiOverview extends KpiOverview {
164
163
  const scoreType = kpi.scoreType;
165
164
  const valueType = kpi.valueType;
166
165
  const is2D = scoreType === 'CUSTOM' ||
167
- (kpi.grades && typeof kpi.grades === 'object' && !Array.isArray(kpi.grades) && kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP');
166
+ (kpi.grades &&
167
+ typeof kpi.grades === 'object' &&
168
+ !Array.isArray(kpi.grades) &&
169
+ kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP');
168
170
  const isArray = Array.isArray(kpi.grades) && kpi.grades.length > 0;
169
171
  const isAssessment = valueType === 'ASSESSED' ||
170
- (!scoreType && !valueType && isArray && kpi.grades.length <= 5 &&
172
+ (!scoreType &&
173
+ !valueType &&
174
+ isArray &&
175
+ kpi.grades.length <= 5 &&
171
176
  kpi.grades.every((g) => g.score >= 1 && g.score <= 5 && g.score === Math.floor(g.score) && g.minValue === g.score));
177
+ // SL-PA 결과(X34 품질, X43 안전)만 계단형 등급 분포 차트 (overview 에서는 측정값 없이 구간 구조만)
178
+ const isSlpa = typeof (kpi === null || kpi === void 0 ? void 0 : kpi.name) === 'string' && (kpi.name.includes('X34') || kpi.name.includes('X43'));
179
+ if (isArray && isSlpa) {
180
+ return html `
181
+ <div class="grades-title">성과 분포</div>
182
+ <div class="grades-chart">
183
+ <kpi-step-lookup-chart .grades=${kpi.grades}></kpi-step-lookup-chart>
184
+ </div>
185
+ `;
186
+ }
172
187
  if (isAssessment) {
173
188
  return html `
174
189
  <div class="grades-title">등급 기준</div>
@@ -358,7 +373,7 @@ DsspKpiOverview.styles = [
358
373
  font-size: 0.85rem;
359
374
  font-weight: 600;
360
375
  color: #333;
361
- background: rgba(255,255,255,0.7);
376
+ background: rgba(255, 255, 255, 0.7);
362
377
  padding: 8px 12px;
363
378
  border-radius: 4px;
364
379
  font-family: monospace;
@@ -1 +1 @@
1
- {"version":3,"file":"dssp-kpi-overview.js","sourceRoot":"","sources":["../../../client/pages/kpi-admin/dssp-kpi-overview.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, nothing, CSSResultGroup } from 'lit'\nimport { customElement } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { KpiOverview } from '@things-factory/kpi/dist-client/pages/kpi/kpi-overview.js'\n\nimport '../../components/kpi-lookup-chart'\nimport '../../components/kpi-2d-lookup-chart'\n\nconst GET_KPI_OVERVIEW_EXT = gql`\n query {\n kpiCategories: kpisLevel1 {\n id\n name\n description\n formula\n active\n kpis: children {\n id\n name\n description\n formula\n active\n grades\n scoreType\n valueType\n }\n }\n }\n`\n\n/**\n * KPI scoreType 정의 — value → score 변환 방식\n *\n * NONE — 미설정 (부모 KPI 등)\n * DIRECT — value = score, 별도 변환 없음 (Y/Z: formula 결과가 곧 score)\n * FORMULA — scoreFormula로 value → score 변환\n * LOOKUP — grade table(1D)로 raw value → 0~1 score 변환 (연속값 KPI)\n * 예: X11(연면적 대비 공사기간), X33(검측 불합격률), X34(SL-PA)\n * → 성과 분포 커브 차트로 표시\n * CUSTOM — 2D 룩업 등 특수 구조의 grade (다차원 입력 → 점수)\n * 예: X13(일정 이탈 수준) = 공정률 × 편차율 → 1~5점\n * → 히트맵 차트로 표시\n * ASSESSMENT — 감리자 직접 평가, value(1~5) = score (grade table 불필요)\n * 예: X14(일정성과 수준 평가), X23(비용성과), X35(품질성과) 등\n * → 등급 기준 설명만 표시 (차트 없음)\n *\n * Note: DIRECT와 ASSESSMENT는 모두 value=score이지만,\n * ASSESSMENT는 감리자가 1~5점을 직접 입력하는 정성 평가를 의미하고,\n * DIRECT는 산식 등으로 자동 계산된 value가 변환 없이 score가 되는 것을 의미한다.\n */\n\n/**\n * KPI 개요 페이지 — 등급 구간을 성과 분포 차트로 표현\n *\n * - 0~1 스케일 KPI: 성과 분포 커브 (kpi-lookup-chart)\n * - 1~5 평가형 KPI: 5단계 세그먼트 게이지 (kpi-lookup-chart 자동 감지)\n * - X13 2D 룩업: 공정률×편차율 히트맵 (kpi-2d-lookup-chart)\n */\n@customElement('dssp-kpi-overview')\n// @ts-ignore styles type override\nexport class DsspKpiOverview extends KpiOverview {\n static styles = [\n KpiOverview.styles,\n css`\n :host {\n overflow-y: auto;\n }\n .grades-section {\n margin-top: 16px;\n background: #fff;\n border-radius: 8px;\n padding: 20px;\n border: 2px solid #0c4da2;\n }\n .grades-title {\n font-size: 1rem;\n font-weight: 700;\n color: #333;\n margin-bottom: 12px;\n }\n .grades-chart {\n width: 100%;\n height: 320px;\n }\n .grade-descriptions {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 12px;\n }\n .grade-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 0.8rem;\n font-weight: 500;\n background: #f5f5f5;\n border: 1px solid #e0e0e0;\n }\n .grade-chip .dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n .grade-chip .score {\n font-weight: 700;\n min-width: 24px;\n }\n .grade-chip .desc {\n color: #555;\n }\n .type-info {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n }\n .type-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n border-radius: 6px;\n font-size: 0.75rem;\n border: 1px solid #e0e0e0;\n background: #fafafa;\n }\n .type-badge .label {\n color: #888;\n font-weight: 400;\n }\n .type-badge .value {\n font-weight: 600;\n color: #333;\n }\n .x-section {\n display: flex;\n gap: 0;\n margin-top: 12px;\n background: #fff;\n border: 2px solid #0c4da2;\n border-top: none;\n overflow: hidden;\n }\n .x-detail {\n flex: 0 0 320px;\n padding: 20px 25px;\n border-right: 1px solid rgba(46, 164, 223, 0.1);\n font-size: 0.875rem;\n color: #212529;\n }\n .x-chart {\n flex: 1;\n padding: 16px;\n min-height: 280px;\n }\n .y-info {\n background: linear-gradient(135deg, #f0f7ff 0%, #e8f4f8 100%);\n border-radius: 8px;\n padding: 16px 20px;\n margin-bottom: 16px;\n border-left: 4px solid #0c4da2;\n }\n .y-name {\n font-size: 1rem;\n font-weight: 700;\n color: #0c4da2;\n margin-bottom: 6px;\n }\n .y-desc {\n font-size: 0.875rem;\n color: #444;\n line-height: 1.6;\n margin-bottom: 8px;\n }\n .y-formula {\n font-size: 0.85rem;\n font-weight: 600;\n color: #333;\n background: rgba(255,255,255,0.7);\n padding: 8px 12px;\n border-radius: 4px;\n font-family: monospace;\n }\n .y-formula-label {\n font-size: 0.75rem;\n color: #888;\n margin-bottom: 4px;\n }\n `\n ]\n\n override async firstUpdated() {\n try {\n const { data } = await client.query({ query: GET_KPI_OVERVIEW_EXT })\n this.kpiCategories = data.kpiCategories\n this.loading = false\n } catch (e) {\n this.error = e instanceof Error ? e : new Error(String(e))\n this.loading = false\n }\n }\n\n override render() {\n if (this.error) return html`<div>에러: ${this.error?.message}</div>`\n if (!this.kpiCategories.length) return html`<div>KPI 카테고리가 없습니다.</div>`\n\n const selctedY = this.kpiCategories?.[this.selectedGroup] || ''\n const groupRaw = this.kpiCategories[this.selectedGroup] as any\n // active가 false인 KPI 제외 (X31, X32 등 삭제된 지표)\n const activeKpis = groupRaw?.kpis?.filter((k: any) => k.active !== false) || []\n const group = { ...groupRaw, kpis: activeKpis }\n const kpi = group?.kpis?.[this.selectedKpi] as any\n\n return html`\n <div class=\"overview-container\">\n <div class=\"overview-left\">\n <div class=\"overview-title\">KPI개요</div>\n <div class=\"overview-desc\">\n 건설현장 KPI관리 시스템은 프로젝트 성과를 측정하고, 모니터링하여 효율적인 공정 관리를 지원합니다. 주요 지표를\n 통해 현장 생산성, 품질, 안전 등을 실시간으로 파악할 수 있습니다.\n </div>\n </div>\n </div>\n <div class=\"group-tabs\">\n ${this.kpiCategories.map(\n (g: any, i: number) => html`\n <button\n class=\"group-tab\"\n ?selected=${i === this.selectedGroup}\n @click=${() => {\n this.selectedGroup = i\n this.selectedKpi = 0\n }}\n >\n ${g.name}\n </button>\n `\n )}\n </div>\n <!-- Y 섹션: 좌=Y 설명+산식 | 우=X-KPI 목록 -->\n <div class=\"main-content\">\n <div class=\"markdown\">\n <div class=\"kpi-title\">${group.name}</div>\n ${group.description ? html`<div style=\"line-height:1.7;margin-bottom:12px;\">${group.description}</div>` : ''}\n ${group.formula\n ? html`\n <div class=\"subtitle\"><span class=\"subtitle-icon\"></span> 산식</div>\n <div class=\"kpi-formula\">${group.formula}</div>\n `\n : ''}\n </div>\n <div class=\"toc\">\n <div class=\"submenu-header\">\n <span class=\"submenu-icon\"></span>\n <span class=\"toc-title\">${selctedY.name} 지표</span>\n </div>\n <ul class=\"toc-list\">\n ${group?.kpis?.map(\n (k: any, i: number) => html`\n <li>\n <button class=\"toc-btn\" ?selected=${i === this.selectedKpi} @click=${() => (this.selectedKpi = i)}>\n ${k.name}\n </button>\n </li>\n `\n )}\n </ul>\n </div>\n </div>\n\n <!-- X 섹션: 좌=X 설명+산식 | 우=성과분포/등급 -->\n <div class=\"x-section\">\n <div class=\"x-detail\">\n <div class=\"kpi-title\">${kpi?.name || ''}</div>\n <div style=\"line-height:1.7;margin-bottom:12px;\">${kpi?.description || ''}</div>\n ${kpi?.formula\n ? html`\n <div class=\"subtitle\"><span class=\"subtitle-icon\"></span> 주요산식</div>\n <div class=\"kpi-formula\">${kpi?.formula}</div>\n `\n : ''}\n ${this._renderTypeInfo(kpi)}\n </div>\n <div class=\"x-chart\">\n ${this._renderGradesContent(kpi)}\n </div>\n </div>\n `\n }\n\n /**\n * 성과분포/등급 콘텐츠 렌더링 — scoreType + valueType 기반 분기\n *\n * valueType=ASSESSED → 등급 기준 설명만 (감리자 직접 평가, 차트 없음)\n * scoreType=CUSTOM → 2D 히트맵 (공정률×편차율)\n * scoreType=LOOKUP → 성과 분포 커브 (value→score 매핑)\n * scoreType=DIRECT → 등급 데이터 없음 (Y/Z 등)\n */\n private _renderGradesContent(kpi: any) {\n if (!kpi?.grades) return html`<div style=\"color:#999;padding:20px;\">등급 데이터 없음</div>`\n\n const scoreType = kpi.scoreType\n const valueType = kpi.valueType\n const is2D = scoreType === 'CUSTOM' ||\n (kpi.grades && typeof kpi.grades === 'object' && !Array.isArray(kpi.grades) && kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP')\n const isArray = Array.isArray(kpi.grades) && kpi.grades.length > 0\n const isAssessment = valueType === 'ASSESSED' ||\n (!scoreType && !valueType && isArray && kpi.grades.length <= 5 &&\n kpi.grades.every((g: any) => g.score >= 1 && g.score <= 5 && g.score === Math.floor(g.score) && g.minValue === g.score))\n\n if (isAssessment) {\n return html`\n <div class=\"grades-title\">등급 기준</div>\n ${isArray ? this._renderAssessmentDescriptions(kpi.grades) : nothing}\n `\n }\n\n if (is2D) {\n return html`\n <div class=\"grades-title\">성과 분포</div>\n <div class=\"grades-chart\">\n <kpi-2d-lookup-chart .grades=${kpi.grades} .progressRate=${50}></kpi-2d-lookup-chart>\n </div>\n `\n }\n\n if (isArray) {\n return html`\n <div class=\"grades-title\">성과 분포</div>\n <div class=\"grades-chart\">\n <kpi-lookup-chart .grades=${kpi.grades} .showDots=${true} .scoreType=${kpi.scoreType || ''}></kpi-lookup-chart>\n </div>\n `\n }\n\n return html`<div style=\"color:#999;padding:20px;\">등급 데이터 없음</div>`\n }\n\n private _renderTypeInfo(kpi: any) {\n const valueLabels: Record<string, string> = {\n MEASURED: '외부 시스템 수집',\n ASSESSED: '감리자 직접 평가 (1~5)',\n CALCULATED: '산식 자동 계산',\n COMPOSITE: '다차원 복합 입력'\n }\n const scoreLabels: Record<string, string> = {\n DIRECT: 'value = score (변환 없음)',\n FORMULA: 'scoreFormula 수식 변환',\n LOOKUP: 'Grade Table 룩업',\n CUSTOM: '2D 룩업 (특수 변환)'\n }\n\n const vLabel = kpi?.valueType ? valueLabels[kpi.valueType] || kpi.valueType : null\n const sLabel = kpi?.scoreType ? scoreLabels[kpi.scoreType] || kpi.scoreType : null\n\n if (!vLabel && !sLabel) return nothing\n\n return html`\n <div class=\"type-info\">\n ${vLabel\n ? html`<span class=\"type-badge\"><span class=\"label\">Value 산정</span><span class=\"value\">${vLabel}</span></span>`\n : ''}\n ${sLabel\n ? html`<span class=\"type-badge\"><span class=\"label\">Score 산정</span><span class=\"value\">${sLabel}</span></span>`\n : ''}\n </div>\n `\n }\n\n private _renderAssessmentDescriptions(grades: any[]) {\n const colors = ['#e53935', '#ff9800', '#ffca28', '#66bb6a', '#2e7d32']\n const sorted = [...grades].sort((a, b) => a.score - b.score)\n\n return html`\n <div class=\"grade-descriptions\">\n ${sorted.map(\n (g: any) => html`\n <div class=\"grade-chip\">\n <span class=\"dot\" style=\"background: ${colors[(g.score || 1) - 1]}\"></span>\n <span class=\"score\">${g.score}점</span>\n <span class=\"desc\">${g.description || g.name || ''}</span>\n </div>\n `\n )}\n </div>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"dssp-kpi-overview.js","sourceRoot":"","sources":["../../../client/pages/kpi-admin/dssp-kpi-overview.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, nothing, CSSResultGroup } from 'lit'\nimport { customElement } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { KpiOverview } from '@things-factory/kpi/dist-client/pages/kpi/kpi-overview.js'\n\nimport '../../components/kpi-lookup-chart'\nimport '../../components/kpi-2d-lookup-chart'\nimport '../../components/kpi-step-lookup-chart'\n\nconst GET_KPI_OVERVIEW_EXT = gql`\n query {\n kpiCategories: kpisLevel1 {\n id\n name\n description\n formula\n active\n kpis: children {\n id\n name\n description\n formula\n active\n grades\n scoreType\n valueType\n }\n }\n }\n`\n\n/**\n * KPI scoreType 정의 — value → score 변환 방식\n *\n * NONE — 미설정 (부모 KPI 등)\n * DIRECT — value = score, 별도 변환 없음 (Y/Z: formula 결과가 곧 score)\n * FORMULA — scoreFormula로 value → score 변환\n * LOOKUP — grade table(1D)로 raw value → 0~1 score 변환 (연속값 KPI)\n * 예: X11(연면적 대비 공사기간), X33(검측 불합격률), X34(SL-PA)\n * → 성과 분포 커브 차트로 표시\n * CUSTOM — 2D 룩업 등 특수 구조의 grade (다차원 입력 → 점수)\n * 예: X13(일정 이탈 수준) = 공정률 × 편차율 → 1~5점\n * → 히트맵 차트로 표시\n * ASSESSMENT — 감리자 직접 평가, value(1~5) = score (grade table 불필요)\n * 예: X14(일정성과 정성 평가), X23(비용성과), X35(품질성과) 등\n * → 등급 기준 설명만 표시 (차트 없음)\n *\n * Note: DIRECT와 ASSESSMENT는 모두 value=score이지만,\n * ASSESSMENT는 감리자가 1~5점을 직접 입력하는 정성 평가를 의미하고,\n * DIRECT는 산식 등으로 자동 계산된 value가 변환 없이 score가 되는 것을 의미한다.\n */\n\n/**\n * KPI 개요 페이지 — 등급 구간을 성과 분포 차트로 표현\n *\n * - 0~1 스케일 KPI: 성과 분포 커브 (kpi-lookup-chart)\n * - 1~5 평가형 KPI: 5단계 세그먼트 게이지 (kpi-lookup-chart 자동 감지)\n * - X13 2D 룩업: 공정률×편차율 히트맵 (kpi-2d-lookup-chart)\n */\n@customElement('dssp-kpi-overview')\n// @ts-ignore styles type override\nexport class DsspKpiOverview extends KpiOverview {\n static styles = [\n KpiOverview.styles,\n css`\n :host {\n overflow-y: auto;\n }\n .grades-section {\n margin-top: 16px;\n background: #fff;\n border-radius: 8px;\n padding: 20px;\n border: 2px solid #0c4da2;\n }\n .grades-title {\n font-size: 1rem;\n font-weight: 700;\n color: #333;\n margin-bottom: 12px;\n }\n .grades-chart {\n width: 100%;\n height: 320px;\n }\n .grade-descriptions {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 12px;\n }\n .grade-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 0.8rem;\n font-weight: 500;\n background: #f5f5f5;\n border: 1px solid #e0e0e0;\n }\n .grade-chip .dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n .grade-chip .score {\n font-weight: 700;\n min-width: 24px;\n }\n .grade-chip .desc {\n color: #555;\n }\n .type-info {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n }\n .type-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n border-radius: 6px;\n font-size: 0.75rem;\n border: 1px solid #e0e0e0;\n background: #fafafa;\n }\n .type-badge .label {\n color: #888;\n font-weight: 400;\n }\n .type-badge .value {\n font-weight: 600;\n color: #333;\n }\n .x-section {\n display: flex;\n gap: 0;\n margin-top: 12px;\n background: #fff;\n border: 2px solid #0c4da2;\n border-top: none;\n overflow: hidden;\n }\n .x-detail {\n flex: 0 0 320px;\n padding: 20px 25px;\n border-right: 1px solid rgba(46, 164, 223, 0.1);\n font-size: 0.875rem;\n color: #212529;\n }\n .x-chart {\n flex: 1;\n padding: 16px;\n min-height: 280px;\n }\n .y-info {\n background: linear-gradient(135deg, #f0f7ff 0%, #e8f4f8 100%);\n border-radius: 8px;\n padding: 16px 20px;\n margin-bottom: 16px;\n border-left: 4px solid #0c4da2;\n }\n .y-name {\n font-size: 1rem;\n font-weight: 700;\n color: #0c4da2;\n margin-bottom: 6px;\n }\n .y-desc {\n font-size: 0.875rem;\n color: #444;\n line-height: 1.6;\n margin-bottom: 8px;\n }\n .y-formula {\n font-size: 0.85rem;\n font-weight: 600;\n color: #333;\n background: rgba(255, 255, 255, 0.7);\n padding: 8px 12px;\n border-radius: 4px;\n font-family: monospace;\n }\n .y-formula-label {\n font-size: 0.75rem;\n color: #888;\n margin-bottom: 4px;\n }\n `\n ]\n\n override async firstUpdated() {\n try {\n const { data } = await client.query({ query: GET_KPI_OVERVIEW_EXT })\n this.kpiCategories = data.kpiCategories\n this.loading = false\n } catch (e) {\n this.error = e instanceof Error ? e : new Error(String(e))\n this.loading = false\n }\n }\n\n override render() {\n if (this.error) return html`<div>에러: ${this.error?.message}</div>`\n if (!this.kpiCategories.length) return html`<div>KPI 카테고리가 없습니다.</div>`\n\n const selctedY = this.kpiCategories?.[this.selectedGroup] || ''\n const groupRaw = this.kpiCategories[this.selectedGroup] as any\n // active가 false인 KPI 제외 (X31, X32 등 삭제된 지표)\n const activeKpis = groupRaw?.kpis?.filter((k: any) => k.active !== false) || []\n const group = { ...groupRaw, kpis: activeKpis }\n const kpi = group?.kpis?.[this.selectedKpi] as any\n\n return html`\n <div class=\"overview-container\">\n <div class=\"overview-left\">\n <div class=\"overview-title\">KPI개요</div>\n <div class=\"overview-desc\">\n 건설프로젝트 KPI관리 시스템은 프로젝트 성과를 측정하고, 모니터링하여 효율적인 공정 관리를 지원합니다. 주요 지표를 통해\n 프로젝트 생산성, 품질, 안전 등을 실시간으로 파악할 수 있습니다.\n </div>\n </div>\n </div>\n <div class=\"group-tabs\">\n ${this.kpiCategories.map(\n (g: any, i: number) => html`\n <button\n class=\"group-tab\"\n ?selected=${i === this.selectedGroup}\n @click=${() => {\n this.selectedGroup = i\n this.selectedKpi = 0\n }}\n >\n ${g.name}\n </button>\n `\n )}\n </div>\n <!-- Y 섹션: 좌=Y 설명+산식 | 우=X-KPI 목록 -->\n <div class=\"main-content\">\n <div class=\"markdown\">\n <div class=\"kpi-title\">${group.name}</div>\n ${group.description ? html`<div style=\"line-height:1.7;margin-bottom:12px;\">${group.description}</div>` : ''}\n ${group.formula\n ? html`\n <div class=\"subtitle\"><span class=\"subtitle-icon\"></span> 산식</div>\n <div class=\"kpi-formula\">${group.formula}</div>\n `\n : ''}\n </div>\n <div class=\"toc\">\n <div class=\"submenu-header\">\n <span class=\"submenu-icon\"></span>\n <span class=\"toc-title\">${selctedY.name} 지표</span>\n </div>\n <ul class=\"toc-list\">\n ${group?.kpis?.map(\n (k: any, i: number) => html`\n <li>\n <button class=\"toc-btn\" ?selected=${i === this.selectedKpi} @click=${() => (this.selectedKpi = i)}>\n ${k.name}\n </button>\n </li>\n `\n )}\n </ul>\n </div>\n </div>\n\n <!-- X 섹션: 좌=X 설명+산식 | 우=성과분포/등급 -->\n <div class=\"x-section\">\n <div class=\"x-detail\">\n <div class=\"kpi-title\">${kpi?.name || ''}</div>\n <div style=\"line-height:1.7;margin-bottom:12px;\">${kpi?.description || ''}</div>\n ${kpi?.formula\n ? html`\n <div class=\"subtitle\"><span class=\"subtitle-icon\"></span> 주요산식</div>\n <div class=\"kpi-formula\">${kpi?.formula}</div>\n `\n : ''}\n ${this._renderTypeInfo(kpi)}\n </div>\n <div class=\"x-chart\">${this._renderGradesContent(kpi)}</div>\n </div>\n `\n }\n\n /**\n * 성과분포/등급 콘텐츠 렌더링 — scoreType + valueType 기반 분기\n *\n * valueType=ASSESSED → 등급 기준 설명만 (감리자 직접 평가, 차트 없음)\n * scoreType=CUSTOM → 2D 히트맵 (공정률×편차율)\n * scoreType=LOOKUP → 성과 분포 커브 (value→score 매핑)\n * scoreType=DIRECT → 등급 데이터 없음 (Y/Z 등)\n */\n private _renderGradesContent(kpi: any) {\n if (!kpi?.grades) return html`<div style=\"color:#999;padding:20px;\">등급 데이터 없음</div>`\n\n const scoreType = kpi.scoreType\n const valueType = kpi.valueType\n const is2D =\n scoreType === 'CUSTOM' ||\n (kpi.grades &&\n typeof kpi.grades === 'object' &&\n !Array.isArray(kpi.grades) &&\n kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP')\n const isArray = Array.isArray(kpi.grades) && kpi.grades.length > 0\n const isAssessment =\n valueType === 'ASSESSED' ||\n (!scoreType &&\n !valueType &&\n isArray &&\n kpi.grades.length <= 5 &&\n kpi.grades.every((g: any) => g.score >= 1 && g.score <= 5 && g.score === Math.floor(g.score) && g.minValue === g.score))\n\n // SL-PA 결과(X34 품질, X43 안전)만 계단형 등급 분포 차트 (overview 에서는 측정값 없이 구간 구조만)\n const isSlpa = typeof kpi?.name === 'string' && (kpi.name.includes('X34') || kpi.name.includes('X43'))\n if (isArray && isSlpa) {\n return html`\n <div class=\"grades-title\">성과 분포</div>\n <div class=\"grades-chart\">\n <kpi-step-lookup-chart .grades=${kpi.grades}></kpi-step-lookup-chart>\n </div>\n `\n }\n\n if (isAssessment) {\n return html`\n <div class=\"grades-title\">등급 기준</div>\n ${isArray ? this._renderAssessmentDescriptions(kpi.grades) : nothing}\n `\n }\n\n if (is2D) {\n return html`\n <div class=\"grades-title\">성과 분포</div>\n <div class=\"grades-chart\">\n <kpi-2d-lookup-chart .grades=${kpi.grades} .progressRate=${50}></kpi-2d-lookup-chart>\n </div>\n `\n }\n\n if (isArray) {\n return html`\n <div class=\"grades-title\">성과 분포</div>\n <div class=\"grades-chart\">\n <kpi-lookup-chart .grades=${kpi.grades} .showDots=${true} .scoreType=${kpi.scoreType || ''}></kpi-lookup-chart>\n </div>\n `\n }\n\n return html`<div style=\"color:#999;padding:20px;\">등급 데이터 없음</div>`\n }\n\n private _renderTypeInfo(kpi: any) {\n const valueLabels: Record<string, string> = {\n MEASURED: '외부 시스템 수집',\n ASSESSED: '감리자 직접 평가 (1~5)',\n CALCULATED: '산식 자동 계산',\n COMPOSITE: '다차원 복합 입력'\n }\n const scoreLabels: Record<string, string> = {\n DIRECT: 'value = score (변환 없음)',\n FORMULA: 'scoreFormula 수식 변환',\n LOOKUP: 'Grade Table 룩업',\n CUSTOM: '2D 룩업 (특수 변환)'\n }\n\n const vLabel = kpi?.valueType ? valueLabels[kpi.valueType] || kpi.valueType : null\n const sLabel = kpi?.scoreType ? scoreLabels[kpi.scoreType] || kpi.scoreType : null\n\n if (!vLabel && !sLabel) return nothing\n\n return html`\n <div class=\"type-info\">\n ${vLabel\n ? html`<span class=\"type-badge\"><span class=\"label\">Value 산정</span><span class=\"value\">${vLabel}</span></span>`\n : ''}\n ${sLabel\n ? html`<span class=\"type-badge\"><span class=\"label\">Score 산정</span><span class=\"value\">${sLabel}</span></span>`\n : ''}\n </div>\n `\n }\n\n private _renderAssessmentDescriptions(grades: any[]) {\n const colors = ['#e53935', '#ff9800', '#ffca28', '#66bb6a', '#2e7d32']\n const sorted = [...grades].sort((a, b) => a.score - b.score)\n\n return html`\n <div class=\"grade-descriptions\">\n ${sorted.map(\n (g: any) => html`\n <div class=\"grade-chip\">\n <span class=\"dot\" style=\"background: ${colors[(g.score || 1) - 1]}\"></span>\n <span class=\"score\">${g.score}점</span>\n <span class=\"desc\">${g.description || g.name || ''}</span>\n </div>\n `\n )}\n </div>\n `\n }\n}\n"]}