@things-factory/kpi 9.0.28 → 9.0.30

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 (131) hide show
  1. package/client/google-map/common-google-map.ts +332 -0
  2. package/client/google-map/google-map-loader.ts +29 -0
  3. package/client/google-map/script-loader.ts +173 -0
  4. package/client/pages/kpi-dashboard/cards/kpi-level1-card.ts +248 -0
  5. package/client/pages/kpi-dashboard/cards/kpi-level2-comparison.ts +369 -0
  6. package/client/pages/kpi-dashboard/cards/kpi-level3-comparison.ts +443 -0
  7. package/client/pages/kpi-dashboard/components/kpi-chart-toggle.ts +73 -0
  8. package/client/pages/kpi-dashboard/components/kpi-map-panel.ts +222 -0
  9. package/client/pages/kpi-dashboard/kpi-dashboard-map.ts +786 -0
  10. package/client/pages/kpi-dashboard/kpi-dashboard.ts +416 -0
  11. package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +761 -0
  12. package/client/pages/kpi-statistic/kpi-statistic-importer.ts +90 -0
  13. package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +505 -0
  14. package/client/route.ts +12 -0
  15. package/dist-client/google-map/common-google-map.d.ts +34 -0
  16. package/dist-client/google-map/common-google-map.js +300 -0
  17. package/dist-client/google-map/common-google-map.js.map +1 -0
  18. package/dist-client/google-map/google-map-loader.d.ts +6 -0
  19. package/dist-client/google-map/google-map-loader.js +22 -0
  20. package/dist-client/google-map/google-map-loader.js.map +1 -0
  21. package/dist-client/google-map/script-loader.d.ts +3 -0
  22. package/dist-client/google-map/script-loader.js +144 -0
  23. package/dist-client/google-map/script-loader.js.map +1 -0
  24. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.d.ts +17 -0
  25. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +279 -0
  26. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -0
  27. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.d.ts +19 -0
  28. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +385 -0
  29. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -0
  30. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.d.ts +23 -0
  31. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +465 -0
  32. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -0
  33. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.d.ts +8 -0
  34. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js +79 -0
  35. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js.map +1 -0
  36. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +23 -0
  37. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +223 -0
  38. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -0
  39. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +38 -0
  40. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +813 -0
  41. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -0
  42. package/dist-client/pages/kpi-dashboard/kpi-dashboard.d.ts +21 -0
  43. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +398 -0
  44. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
  45. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.d.ts +53 -0
  46. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +718 -0
  47. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -0
  48. package/dist-client/pages/kpi-statistic/kpi-statistic-importer.d.ts +23 -0
  49. package/dist-client/pages/kpi-statistic/kpi-statistic-importer.js +92 -0
  50. package/dist-client/pages/kpi-statistic/kpi-statistic-importer.js.map +1 -0
  51. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +66 -0
  52. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +487 -0
  53. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -0
  54. package/dist-client/route.d.ts +1 -1
  55. package/dist-client/route.js +9 -0
  56. package/dist-client/route.js.map +1 -1
  57. package/dist-client/tsconfig.tsbuildinfo +1 -1
  58. package/dist-server/index.d.ts +1 -0
  59. package/dist-server/index.js +1 -0
  60. package/dist-server/index.js.map +1 -1
  61. package/dist-server/migrations/index.d.ts +1 -0
  62. package/dist-server/migrations/index.js +12 -0
  63. package/dist-server/migrations/index.js.map +1 -0
  64. package/dist-server/service/index.d.ts +3 -2
  65. package/dist-server/service/index.js +4 -0
  66. package/dist-server/service/index.js.map +1 -1
  67. package/dist-server/service/kpi/kpi-mutation.js +9 -0
  68. package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
  69. package/dist-server/service/kpi/kpi-query.js +2 -0
  70. package/dist-server/service/kpi/kpi-query.js.map +1 -1
  71. package/dist-server/service/kpi-alert/kpi-alert-query.js +1 -0
  72. package/dist-server/service/kpi-alert/kpi-alert-query.js.map +1 -1
  73. package/dist-server/service/kpi-category/kpi-category-mutation.js +4 -0
  74. package/dist-server/service/kpi-category/kpi-category-mutation.js.map +1 -1
  75. package/dist-server/service/kpi-category/kpi-category-query.js +2 -0
  76. package/dist-server/service/kpi-category/kpi-category-query.js.map +1 -1
  77. package/dist-server/service/kpi-metric/kpi-metric-mutation.js +6 -0
  78. package/dist-server/service/kpi-metric/kpi-metric-mutation.js.map +1 -1
  79. package/dist-server/service/kpi-metric/kpi-metric-query.js +2 -0
  80. package/dist-server/service/kpi-metric/kpi-metric-query.js.map +1 -1
  81. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +7 -0
  82. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  83. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +2 -0
  84. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -1
  85. package/dist-server/service/kpi-statistic/index.d.ts +6 -0
  86. package/dist-server/service/kpi-statistic/index.js +10 -0
  87. package/dist-server/service/kpi-statistic/index.js.map +1 -0
  88. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.d.ts +10 -0
  89. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js +198 -0
  90. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js.map +1 -0
  91. package/dist-server/service/kpi-statistic/kpi-statistic-query.d.ts +13 -0
  92. package/dist-server/service/kpi-statistic/kpi-statistic-query.js +92 -0
  93. package/dist-server/service/kpi-statistic/kpi-statistic-query.js.map +1 -0
  94. package/dist-server/service/kpi-statistic/kpi-statistic-type.d.ts +59 -0
  95. package/dist-server/service/kpi-statistic/kpi-statistic-type.js +200 -0
  96. package/dist-server/service/kpi-statistic/kpi-statistic-type.js.map +1 -0
  97. package/dist-server/service/kpi-statistic/kpi-statistic.d.ts +38 -0
  98. package/dist-server/service/kpi-statistic/kpi-statistic.js +177 -0
  99. package/dist-server/service/kpi-statistic/kpi-statistic.js.map +1 -0
  100. package/dist-server/service/kpi-value/kpi-value-mutation.js +9 -0
  101. package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
  102. package/dist-server/service/kpi-value/kpi-value-query.js +2 -0
  103. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  104. package/dist-server/tsconfig.tsbuildinfo +1 -1
  105. package/helps/kpi/kpi-statistic.md +160 -0
  106. package/package.json +2 -2
  107. package/server/index.ts +1 -0
  108. package/server/migrations/index.ts +9 -0
  109. package/server/service/index.ts +8 -0
  110. package/server/service/kpi/kpi-mutation.ts +9 -0
  111. package/server/service/kpi/kpi-query.ts +2 -0
  112. package/server/service/kpi-alert/kpi-alert-query.ts +2 -1
  113. package/server/service/kpi-category/kpi-category-mutation.ts +4 -0
  114. package/server/service/kpi-category/kpi-category-query.ts +2 -0
  115. package/server/service/kpi-metric/kpi-metric-mutation.ts +6 -0
  116. package/server/service/kpi-metric/kpi-metric-query.ts +2 -0
  117. package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +7 -0
  118. package/server/service/kpi-metric-value/kpi-metric-value-query.ts +3 -1
  119. package/server/service/kpi-statistic/index.ts +7 -0
  120. package/server/service/kpi-statistic/kpi-statistic-mutation.ts +194 -0
  121. package/server/service/kpi-statistic/kpi-statistic-query.ts +59 -0
  122. package/server/service/kpi-statistic/kpi-statistic-type.ts +152 -0
  123. package/server/service/kpi-statistic/kpi-statistic.ts +167 -0
  124. package/server/service/kpi-value/kpi-value-mutation.ts +9 -0
  125. package/server/service/kpi-value/kpi-value-query.ts +2 -0
  126. package/things-factory.config.js +4 -1
  127. package/translations/en.json +24 -1
  128. package/translations/ja.json +43 -20
  129. package/translations/ko.json +30 -7
  130. package/translations/ms.json +35 -12
  131. package/translations/zh.json +39 -16
@@ -0,0 +1,279 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { html, css } from 'lit';
3
+ import { customElement, state } from 'lit/decorators.js';
4
+ import { LitElement } from 'lit';
5
+ import { client } from '@operato/graphql';
6
+ import gql from 'graphql-tag';
7
+ let KpiLevel1Card = class KpiLevel1Card extends LitElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.loading = true;
11
+ this.error = '';
12
+ this.totalScore = 0;
13
+ this.grade = '';
14
+ this.totalKpis = 0;
15
+ this.totalCategories = 0;
16
+ this.averageScore = 0;
17
+ this.currentMonth = '';
18
+ }
19
+ static { this.styles = css `
20
+ :host {
21
+ display: block;
22
+ }
23
+ .score-card {
24
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
25
+ border-radius: 16px;
26
+ padding: 32px;
27
+ color: white;
28
+ box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
29
+ text-align: center;
30
+ position: relative;
31
+ overflow: hidden;
32
+ }
33
+ .score-card::before {
34
+ content: '';
35
+ position: absolute;
36
+ top: 0;
37
+ left: 0;
38
+ right: 0;
39
+ bottom: 0;
40
+ background: rgba(255, 255, 255, 0.1);
41
+ border-radius: 16px;
42
+ }
43
+ .score-content {
44
+ position: relative;
45
+ z-index: 1;
46
+ }
47
+ .score-title {
48
+ font-size: 1.2rem;
49
+ font-weight: 600;
50
+ margin-bottom: 16px;
51
+ opacity: 0.9;
52
+ }
53
+ .score-value {
54
+ font-size: 4rem;
55
+ font-weight: bold;
56
+ margin-bottom: 8px;
57
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
58
+ }
59
+ .score-grade {
60
+ font-size: 1.5rem;
61
+ font-weight: 600;
62
+ margin-bottom: 16px;
63
+ opacity: 0.9;
64
+ }
65
+ .score-period {
66
+ font-size: 0.9rem;
67
+ opacity: 0.7;
68
+ margin-bottom: 16px;
69
+ }
70
+ .score-details {
71
+ display: flex;
72
+ justify-content: space-around;
73
+ margin-top: 24px;
74
+ padding-top: 16px;
75
+ border-top: 1px solid rgba(255, 255, 255, 0.2);
76
+ }
77
+ .detail-item {
78
+ text-align: center;
79
+ }
80
+ .detail-value {
81
+ font-size: 1.4rem;
82
+ font-weight: bold;
83
+ margin-bottom: 4px;
84
+ }
85
+ .detail-label {
86
+ font-size: 0.8rem;
87
+ opacity: 0.8;
88
+ }
89
+ .loading {
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ height: 200px;
94
+ color: #666;
95
+ font-size: 1.1rem;
96
+ }
97
+ .error {
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ height: 200px;
102
+ color: #d32f2f;
103
+ font-size: 1.1rem;
104
+ }
105
+ `; }
106
+ connectedCallback() {
107
+ super.connectedCallback();
108
+ this.currentMonth = this.getCurrentMonth();
109
+ this.fetchTotalScore();
110
+ }
111
+ getCurrentMonth() {
112
+ const now = new Date();
113
+ const year = now.getFullYear();
114
+ const month = String(now.getMonth() + 1).padStart(2, '0');
115
+ return `${year}-${month}`;
116
+ }
117
+ calculateGrade(score) {
118
+ if (score >= 90)
119
+ return 'A+';
120
+ if (score >= 85)
121
+ return 'A';
122
+ if (score >= 80)
123
+ return 'A-';
124
+ if (score >= 75)
125
+ return 'B+';
126
+ if (score >= 70)
127
+ return 'B';
128
+ if (score >= 65)
129
+ return 'B-';
130
+ if (score >= 60)
131
+ return 'C+';
132
+ if (score >= 55)
133
+ return 'C';
134
+ if (score >= 50)
135
+ return 'C-';
136
+ return 'D';
137
+ }
138
+ async fetchTotalScore() {
139
+ this.loading = true;
140
+ this.error = '';
141
+ try {
142
+ const response = await client.query({
143
+ query: gql `
144
+ query {
145
+ kpiStatistics {
146
+ items {
147
+ id
148
+ valueDate
149
+ periodType
150
+ mean
151
+ median
152
+ kpi {
153
+ id
154
+ name
155
+ targetValue
156
+ unit
157
+ category {
158
+ id
159
+ name
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ `
166
+ });
167
+ const statistics = response.data.kpiStatistics.items || [];
168
+ // MONTH 타입의 현재 월 데이터만 필터링
169
+ const currentMonthStats = statistics.filter(stat => stat.periodType === 'MONTH' && stat.valueDate === this.currentMonth);
170
+ if (currentMonthStats.length === 0) {
171
+ this.error = '현재 월의 데이터가 없습니다.';
172
+ return;
173
+ }
174
+ // 총점 계산 (평균값 기준)
175
+ const scores = currentMonthStats.map(stat => {
176
+ const mean = stat.mean || 0;
177
+ const targetValue = stat.kpi?.targetValue || 100;
178
+ if (targetValue === 0)
179
+ return 0;
180
+ // 목표 대비 달성률 계산 (최대 100점)
181
+ const achievement = Math.min((mean / targetValue) * 100, 100);
182
+ return Math.max(achievement, 0); // 음수 방지
183
+ });
184
+ this.totalScore = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length);
185
+ this.grade = this.calculateGrade(this.totalScore);
186
+ this.totalKpis = currentMonthStats.length;
187
+ // 카테고리 수 계산
188
+ const categories = new Set(currentMonthStats.map(stat => stat.kpi?.category?.name).filter(Boolean));
189
+ this.totalCategories = categories.size;
190
+ // 평균 점수 계산
191
+ this.averageScore = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length);
192
+ }
193
+ catch (e) {
194
+ console.error('총점 데이터를 불러오지 못했습니다:', e);
195
+ this.error = '총점 데이터를 불러오지 못했습니다.';
196
+ }
197
+ finally {
198
+ this.loading = false;
199
+ }
200
+ }
201
+ render() {
202
+ if (this.loading) {
203
+ return html `
204
+ <div class="score-card">
205
+ <div class="loading">총점 계산 중...</div>
206
+ </div>
207
+ `;
208
+ }
209
+ if (this.error) {
210
+ return html `
211
+ <div class="score-card">
212
+ <div class="error">${this.error}</div>
213
+ </div>
214
+ `;
215
+ }
216
+ return html `
217
+ <div class="score-card">
218
+ <div class="score-content">
219
+ <div class="score-title">그룹 총점</div>
220
+ <div class="score-value">${this.totalScore}</div>
221
+ <div class="score-grade">${this.grade}</div>
222
+ <div class="score-period">${this.currentMonth} 기준</div>
223
+
224
+ <div class="score-details">
225
+ <div class="detail-item">
226
+ <div class="detail-value">${this.totalKpis}</div>
227
+ <div class="detail-label">KPI</div>
228
+ </div>
229
+ <div class="detail-item">
230
+ <div class="detail-value">${this.totalCategories}</div>
231
+ <div class="detail-label">카테고리</div>
232
+ </div>
233
+ <div class="detail-item">
234
+ <div class="detail-value">${this.averageScore}</div>
235
+ <div class="detail-label">평균</div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ `;
241
+ }
242
+ };
243
+ __decorate([
244
+ state(),
245
+ __metadata("design:type", Object)
246
+ ], KpiLevel1Card.prototype, "loading", void 0);
247
+ __decorate([
248
+ state(),
249
+ __metadata("design:type", Object)
250
+ ], KpiLevel1Card.prototype, "error", void 0);
251
+ __decorate([
252
+ state(),
253
+ __metadata("design:type", Object)
254
+ ], KpiLevel1Card.prototype, "totalScore", void 0);
255
+ __decorate([
256
+ state(),
257
+ __metadata("design:type", Object)
258
+ ], KpiLevel1Card.prototype, "grade", void 0);
259
+ __decorate([
260
+ state(),
261
+ __metadata("design:type", Object)
262
+ ], KpiLevel1Card.prototype, "totalKpis", void 0);
263
+ __decorate([
264
+ state(),
265
+ __metadata("design:type", Object)
266
+ ], KpiLevel1Card.prototype, "totalCategories", void 0);
267
+ __decorate([
268
+ state(),
269
+ __metadata("design:type", Object)
270
+ ], KpiLevel1Card.prototype, "averageScore", void 0);
271
+ __decorate([
272
+ state(),
273
+ __metadata("design:type", Object)
274
+ ], KpiLevel1Card.prototype, "currentMonth", void 0);
275
+ KpiLevel1Card = __decorate([
276
+ customElement('kpi-level1-card')
277
+ ], KpiLevel1Card);
278
+ export { KpiLevel1Card };
279
+ //# sourceMappingURL=kpi-level1-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-level1-card.js","sourceRoot":"","sources":["../../../../client/pages/kpi-dashboard/cards/kpi-level1-card.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { LitElement } from 'lit'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\n\n@customElement('kpi-level1-card')\nexport class KpiLevel1Card extends LitElement {\n static styles = css`\n :host {\n display: block;\n }\n .score-card {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n border-radius: 16px;\n padding: 32px;\n color: white;\n box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);\n text-align: center;\n position: relative;\n overflow: hidden;\n }\n .score-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 16px;\n }\n .score-content {\n position: relative;\n z-index: 1;\n }\n .score-title {\n font-size: 1.2rem;\n font-weight: 600;\n margin-bottom: 16px;\n opacity: 0.9;\n }\n .score-value {\n font-size: 4rem;\n font-weight: bold;\n margin-bottom: 8px;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n .score-grade {\n font-size: 1.5rem;\n font-weight: 600;\n margin-bottom: 16px;\n opacity: 0.9;\n }\n .score-period {\n font-size: 0.9rem;\n opacity: 0.7;\n margin-bottom: 16px;\n }\n .score-details {\n display: flex;\n justify-content: space-around;\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid rgba(255, 255, 255, 0.2);\n }\n .detail-item {\n text-align: center;\n }\n .detail-value {\n font-size: 1.4rem;\n font-weight: bold;\n margin-bottom: 4px;\n }\n .detail-label {\n font-size: 0.8rem;\n opacity: 0.8;\n }\n .loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #666;\n font-size: 1.1rem;\n }\n .error {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #d32f2f;\n font-size: 1.1rem;\n }\n `\n\n @state() loading = true\n @state() error = ''\n @state() totalScore = 0\n @state() grade = ''\n @state() totalKpis = 0\n @state() totalCategories = 0\n @state() averageScore = 0\n @state() currentMonth = ''\n\n connectedCallback() {\n super.connectedCallback()\n this.currentMonth = this.getCurrentMonth()\n this.fetchTotalScore()\n }\n\n private getCurrentMonth(): string {\n const now = new Date()\n const year = now.getFullYear()\n const month = String(now.getMonth() + 1).padStart(2, '0')\n return `${year}-${month}`\n }\n\n private calculateGrade(score: number): string {\n if (score >= 90) return 'A+'\n if (score >= 85) return 'A'\n if (score >= 80) return 'A-'\n if (score >= 75) return 'B+'\n if (score >= 70) return 'B'\n if (score >= 65) return 'B-'\n if (score >= 60) return 'C+'\n if (score >= 55) return 'C'\n if (score >= 50) return 'C-'\n return 'D'\n }\n\n async fetchTotalScore() {\n this.loading = true\n this.error = ''\n\n try {\n const response = await client.query({\n query: gql`\n query {\n kpiStatistics {\n items {\n id\n valueDate\n periodType\n mean\n median\n kpi {\n id\n name\n targetValue\n unit\n category {\n id\n name\n }\n }\n }\n }\n }\n `\n })\n\n const statistics = response.data.kpiStatistics.items || []\n\n // MONTH 타입의 현재 월 데이터만 필터링\n const currentMonthStats = statistics.filter(\n stat => stat.periodType === 'MONTH' && stat.valueDate === this.currentMonth\n )\n\n if (currentMonthStats.length === 0) {\n this.error = '현재 월의 데이터가 없습니다.'\n return\n }\n\n // 총점 계산 (평균값 기준)\n const scores = currentMonthStats.map(stat => {\n const mean = stat.mean || 0\n const targetValue = stat.kpi?.targetValue || 100\n\n if (targetValue === 0) return 0\n\n // 목표 대비 달성률 계산 (최대 100점)\n const achievement = Math.min((mean / targetValue) * 100, 100)\n return Math.max(achievement, 0) // 음수 방지\n })\n\n this.totalScore = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length)\n this.grade = this.calculateGrade(this.totalScore)\n this.totalKpis = currentMonthStats.length\n\n // 카테고리 수 계산\n const categories = new Set(currentMonthStats.map(stat => stat.kpi?.category?.name).filter(Boolean))\n this.totalCategories = categories.size\n\n // 평균 점수 계산\n this.averageScore = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length)\n } catch (e) {\n console.error('총점 데이터를 불러오지 못했습니다:', e)\n this.error = '총점 데이터를 불러오지 못했습니다.'\n } finally {\n this.loading = false\n }\n }\n\n render() {\n if (this.loading) {\n return html`\n <div class=\"score-card\">\n <div class=\"loading\">총점 계산 중...</div>\n </div>\n `\n }\n\n if (this.error) {\n return html`\n <div class=\"score-card\">\n <div class=\"error\">${this.error}</div>\n </div>\n `\n }\n\n return html`\n <div class=\"score-card\">\n <div class=\"score-content\">\n <div class=\"score-title\">그룹 총점</div>\n <div class=\"score-value\">${this.totalScore}</div>\n <div class=\"score-grade\">${this.grade}</div>\n <div class=\"score-period\">${this.currentMonth} 기준</div>\n\n <div class=\"score-details\">\n <div class=\"detail-item\">\n <div class=\"detail-value\">${this.totalKpis}</div>\n <div class=\"detail-label\">KPI</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-value\">${this.totalCategories}</div>\n <div class=\"detail-label\">카테고리</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-value\">${this.averageScore}</div>\n <div class=\"detail-label\">평균</div>\n </div>\n </div>\n </div>\n </div>\n `\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { LitElement } from 'lit';
2
+ export declare class KpiLevel2Comparison extends LitElement {
3
+ static styles: import("lit").CSSResult;
4
+ loading: boolean;
5
+ error: string;
6
+ radarData: any[];
7
+ boxplotData: any[];
8
+ categories: string[];
9
+ currentMonth: string;
10
+ totalCategories: number;
11
+ totalKpis: number;
12
+ averageScore: number;
13
+ connectedCallback(): void;
14
+ private getCurrentMonth;
15
+ fetchCategoryComparison(): Promise<void>;
16
+ private generateRadarData;
17
+ private generateBoxplotData;
18
+ render(): import("lit-html").TemplateResult<1>;
19
+ }