@dssp/dkpi 1.0.0-alpha.80 → 1.0.0-alpha.81

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 (63) hide show
  1. package/dist-client/bootstrap.d.ts +1 -0
  2. package/dist-client/bootstrap.js +11 -0
  3. package/dist-client/bootstrap.js.map +1 -1
  4. package/dist-client/components/kpi-single-boxplot-chart.d.ts +3 -2
  5. package/dist-client/components/kpi-single-boxplot-chart.js +30 -23
  6. package/dist-client/components/kpi-single-boxplot-chart.js.map +1 -1
  7. package/dist-client/pages/component/project-update-header.d.ts +1 -0
  8. package/dist-client/pages/component/project-update-header.js +127 -0
  9. package/dist-client/pages/component/project-update-header.js.map +1 -0
  10. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +1 -1
  11. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +1 -1
  12. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
  13. package/dist-client/pages/kpi-value/kpi-value-list-page.js +1 -1
  14. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
  15. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +16 -2
  16. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +138 -128
  17. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -1
  18. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.d.ts +4 -2
  19. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +109 -44
  20. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +1 -1
  21. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.d.ts +3 -0
  22. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js +32 -4
  23. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js.map +1 -1
  24. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.d.ts +24 -0
  25. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js +365 -157
  26. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js.map +1 -1
  27. package/dist-client/pages/sv-project-complete.d.ts +4 -1
  28. package/dist-client/pages/sv-project-complete.js +43 -12
  29. package/dist-client/pages/sv-project-complete.js.map +1 -1
  30. package/dist-client/pages/sv-project-detail.d.ts +11 -0
  31. package/dist-client/pages/sv-project-detail.js +184 -48
  32. package/dist-client/pages/sv-project-detail.js.map +1 -1
  33. package/dist-client/pages/sv-project-list.d.ts +9 -0
  34. package/dist-client/pages/sv-project-list.js +93 -3
  35. package/dist-client/pages/sv-project-list.js.map +1 -1
  36. package/dist-client/pages/sv-project-update.d.ts +86 -0
  37. package/dist-client/pages/sv-project-update.js +1331 -0
  38. package/dist-client/pages/sv-project-update.js.map +1 -0
  39. package/dist-client/route.d.ts +1 -1
  40. package/dist-client/route.js +3 -0
  41. package/dist-client/route.js.map +1 -1
  42. package/dist-client/shared/complete-api.d.ts +10 -9
  43. package/dist-client/shared/complete-api.js +44 -18
  44. package/dist-client/shared/complete-api.js.map +1 -1
  45. package/dist-client/tsconfig.tsbuildinfo +1 -1
  46. package/dist-client/viewparts/menu-tools.js +9 -18
  47. package/dist-client/viewparts/menu-tools.js.map +1 -1
  48. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +23 -0
  49. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +72 -28
  50. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  51. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +9 -2
  52. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -1
  53. package/dist-server/service/kpi-stat/kpi-stat-query.js +19 -18
  54. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -1
  55. package/dist-server/service/kpi-value/kpi-value-query.js +2 -2
  56. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  57. package/dist-server/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +3 -3
  59. package/schema.graphql +13 -1
  60. package/things-factory.config.js +1 -0
  61. package/dist-client/shared/domain-context.d.ts +0 -7
  62. package/dist-client/shared/domain-context.js +0 -13
  63. package/dist-client/shared/domain-context.js.map +0 -1
@@ -5,9 +5,11 @@ import { css, html } from 'lit';
5
5
  import { customElement, state } from 'lit/decorators.js';
6
6
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
7
7
  import { PROJECT_STATE } from './sv-project-list';
8
+ import { SITE_TYPE_DISPLAY } from '@dssp/project/dist-client/pages/project/project-list';
8
9
  import { client } from '@operato/graphql';
9
10
  import gql from 'graphql-tag';
10
- import { isProjectTypeDomain } from '../shared/domain-context';
11
+ import moment from 'moment-timezone';
12
+ import { isProjectTypeDomain, tenantHeaders } from '@dssp/project/dist-client/shared/domain-context';
11
13
  import '../components/kpi-boxplot-chart';
12
14
  import '../components/kpi-single-boxplot-chart';
13
15
  import '../components/kpi-radar-chart';
@@ -22,15 +24,19 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
22
24
  this.projectXKpiValues = [];
23
25
  this.showScoreDistribution = false;
24
26
  this.selectedKpi = null;
27
+ /** 이 프로젝트에 아직 한 번도 입력되지 않은 metric (active 한 manual/import 한정) */
28
+ this.pendingMetrics = [];
25
29
  }
26
30
  get context() {
27
31
  var _a;
28
32
  return {
29
- title: this.project ? `프로젝트 상세 정보 - ${(_a = this.project) === null || _a === void 0 ? void 0 : _a.name}` : '프로젝트 상세 정보'
33
+ title: !isProjectTypeDomain() && this.project
34
+ ? `프로젝트 상세 정보 - ${(_a = this.project) === null || _a === void 0 ? void 0 : _a.name}`
35
+ : '프로젝트 상세 정보'
30
36
  };
31
37
  }
32
38
  render() {
33
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
39
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
34
40
  return html `
35
41
  <div content>
36
42
  <div left>
@@ -56,12 +62,19 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
56
62
  <div class="value status-value">${PROJECT_STATE[this.project.state]}</div>
57
63
  </div>
58
64
  <div class="row">
59
- <div class="label">• 요청상세</div>
60
- <div class="value bold">000</div>
65
+ <div class="label">• 건폐율</div>
66
+ <div class="value">
67
+ ${((_d = (_c = this.project.buildingComplex) === null || _c === void 0 ? void 0 : _c.coverageRatio) === null || _d === void 0 ? void 0 : _d.toLocaleString()) || '-'} %
68
+ </div>
61
69
  </div>
62
70
  <div class="row">
63
- <div class="label">• 알람</div>
64
- <div class="value">000</div>
71
+ <div class="label">• 현장유형</div>
72
+ <div class="value">
73
+ ${((_e = this.project.buildingComplex) === null || _e === void 0 ? void 0 : _e.siteType)
74
+ ? SITE_TYPE_DISPLAY[this.project.buildingComplex.siteType] ||
75
+ this.project.buildingComplex.siteType
76
+ : '-'}
77
+ </div>
65
78
  </div>
66
79
  </div>
67
80
  </div>
@@ -69,19 +82,23 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
69
82
  <div class="detail-grid">
70
83
  <div class="grid-item row">
71
84
  <div class="label">• 공사비</div>
72
- <div class="value">${((_d = (_c = this.project.buildingComplex) === null || _c === void 0 ? void 0 : _c.constructionCost) === null || _d === void 0 ? void 0 : _d.toLocaleString()) || '-'} 억원</div>
85
+ <div class="value">${((_g = (_f = this.project.buildingComplex) === null || _f === void 0 ? void 0 : _f.constructionCost) === null || _g === void 0 ? void 0 : _g.toLocaleString()) || '-'} 억원</div>
73
86
  </div>
74
87
  <div class="grid-item row">
75
88
  <div class="label">• 연면적</div>
76
- <div class="value">${((_f = (_e = this.project.buildingComplex) === null || _e === void 0 ? void 0 : _e.area) === null || _f === void 0 ? void 0 : _f.toLocaleString()) || '-'} ㎡</div>
89
+ <div class="value">${((_j = (_h = this.project.buildingComplex) === null || _h === void 0 ? void 0 : _h.area) === null || _j === void 0 ? void 0 : _j.toLocaleString()) || '-'} ㎡</div>
77
90
  </div>
78
91
  <div class="grid-item row">
79
92
  <div class="label">• 용적률</div>
80
- <div class="value">000 %</div>
93
+ <div class="value">
94
+ ${((_l = (_k = this.project.buildingComplex) === null || _k === void 0 ? void 0 : _k.floorAreaRatio) === null || _l === void 0 ? void 0 : _l.toLocaleString()) || '-'} %
95
+ </div>
81
96
  </div>
82
97
  <div class="grid-item row">
83
98
  <div class="label">• 투입인력</div>
84
- <div class="value">000 명</div>
99
+ <div class="value">
100
+ ${((_o = (_m = this.project.buildingComplex) === null || _m === void 0 ? void 0 : _m.workerCount) === null || _o === void 0 ? void 0 : _o.toLocaleString()) || '-'} 명
101
+ </div>
85
102
  </div>
86
103
  </div>
87
104
  </div>
@@ -92,32 +109,30 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
92
109
  <div class="triangle"></div>
93
110
  </div>
94
111
  <div class="sub-desc">
95
- 현재 입력 기한이 도래했거나, 입력이 지연되고 있는 KPI 항목입니다. 해당 항목에 대한 데이터를 입력 해 주시기 바랍니다.
112
+ 프로젝트에 아직 입력되지 않은 KPI 항목입니다. 해당 항목에 대한 데이터를 입력 해 주시기 바랍니다.
96
113
  </div>
97
114
 
98
115
  <div class="list-block">
99
- <div class="list-title">• 입력 대기 중 2건</div>
100
- <div class="list-text"># 2033312-Y5.1 : 검수자재 불합격률</div>
101
- <div class="list-text"># 2033312-Y5.1 : 품질시험 불합격 건수</div>
102
- </div>
103
- <div class="list-block">
104
- <div class="list-title">• 입력 기한 초과 1건</div>
105
- <div class="list-text">
106
- # 2033312-Y5.2 : 검측 불합격률 <span class="warn">2026.2.12 <md-icon>report</md-icon></span>
107
- </div>
108
- </div>
109
- <div class="list-block">
110
- <div class="list-title">• 입력 예정 4건</div>
111
- <div class="list-text"># 2033320-Y4.32 : 연면적 대비 공기입력</div>
112
- <div class="list-text"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>
113
- <div class="list-text"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>
114
- <div class="list-text"># 2096412-Y5.31 : 현장별 일정 이탈 수준</div>
115
- </div>
116
- <div class="list-block">
117
- <div class="list-title">• 입력 기한 없음 3건</div>
118
- <div class="list-text"># 2033320-Y4.32 : 연면적 대비 공기입력</div>
119
- <div class="list-text"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>
120
- <div class="list-text"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>
116
+ <div class="list-title">• 미입력 ${this.pendingMetrics.length}건</div>
117
+ ${this.pendingMetrics.length === 0
118
+ ? html `<div class="list-text">모든 항목이 입력되었습니다.</div>`
119
+ : this.pendingMetrics.map(m => html `
120
+ <div
121
+ class="list-text"
122
+ style="cursor: pointer;"
123
+ @click=${async () => {
124
+ if (isProjectTypeDomain()) {
125
+ navigate('project-complete');
126
+ return;
127
+ }
128
+ const id = this.project.id || (await this._resolveProjectIdFromDomain());
129
+ if (id)
130
+ navigate(`project-complete/${id}`);
131
+ }}
132
+ >
133
+ # ${m.name}${m.description ? ` : ${m.description}` : ''}
134
+ </div>
135
+ `)}
121
136
  </div>
122
137
  </div>
123
138
  </div>
@@ -154,7 +169,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
154
169
  }}
155
170
  >
156
171
  <md-icon slot="">assignment_turned_in</md-icon>
157
- <div>프로젝트 완공 처리</div>
172
+ <div>KPI 데이타입력</div>
158
173
  </div>
159
174
  </div>
160
175
  `}
@@ -266,7 +281,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
266
281
  * ASSESSMENT: 5단계 게이지 (kpi-lookup-chart 자동 감지)
267
282
  */''}
268
283
  ${(this.selectedKpi.scoreType === 'CUSTOM' ||
269
- ((_g = this.selectedKpi.grades) === null || _g === void 0 ? void 0 : _g.type) === 'PROGRESS_DEVIATION_LOOKUP') &&
284
+ ((_p = this.selectedKpi.grades) === null || _p === void 0 ? void 0 : _p.type) === 'PROGRESS_DEVIATION_LOOKUP') &&
270
285
  this.selectedKpi.value !== null &&
271
286
  !(this.selectedKpi.value === Math.floor(this.selectedKpi.value) &&
272
287
  this.selectedKpi.value >= 1 &&
@@ -275,7 +290,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
275
290
  <kpi-2d-lookup-chart
276
291
  .grades=${this.selectedKpi.grades}
277
292
  .value=${this.selectedKpi.value}
278
- .progressRate=${(_j = (_h = this.project) === null || _h === void 0 ? void 0 : _h.totalProgress) !== null && _j !== void 0 ? _j : 50}
293
+ .progressRate=${(_r = (_q = this.project) === null || _q === void 0 ? void 0 : _q.totalProgress) !== null && _r !== void 0 ? _r : 50}
279
294
  unit="%"
280
295
  kpiName=${this.selectedKpi.kpiName || ''}
281
296
  ></kpi-2d-lookup-chart>
@@ -312,11 +327,39 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
312
327
  // initProject 의 GraphQL 응답을 기다리지 않고 project.id 를 즉시 채워서,
313
328
  // 링크의 `project-update/${project.id}` 가 절대 undefined 가 되지 않도록 보장.
314
329
  this.project = Object.assign(Object.assign({}, this.project), { id: projectId });
330
+ // 후속 query 들이 tenant 컨텍스트로 동작하도록 project.code 를 먼저 가볍게 resolve.
331
+ // (tenant 컨텍스트에서 진입한 경우는 헤더 불필요 — tenantHeaders 가 빈 객체 반환.)
332
+ if (!isProjectTypeDomain()) {
333
+ await this._resolveProjectCode(projectId);
334
+ }
315
335
  this.initProject(projectId);
316
336
  this.getKpiComprehensiveStats();
317
337
  this.getKpiYComprehensiveStats();
318
338
  this.getProjectXKpiValues(projectId);
319
339
  }
340
+ async _resolveProjectCode(projectId) {
341
+ var _a, _b;
342
+ try {
343
+ const resp = await client.query({
344
+ query: gql `
345
+ query ProjectCode($id: String!) {
346
+ project(id: $id) {
347
+ id
348
+ code
349
+ }
350
+ }
351
+ `,
352
+ variables: { id: projectId }
353
+ });
354
+ const code = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.project) === null || _b === void 0 ? void 0 : _b.code;
355
+ if (code) {
356
+ this.project = Object.assign(Object.assign({}, this.project), { code });
357
+ }
358
+ }
359
+ catch (e) {
360
+ console.warn('[project-detail] project.code resolve 실패', e);
361
+ }
362
+ }
320
363
  async _resolveProjectIdFromDomain() {
321
364
  var _a, _b;
322
365
  const response = await client.query({
@@ -331,12 +374,13 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
331
374
  return ((_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.currentProject) === null || _b === void 0 ? void 0 : _b.id) || '';
332
375
  }
333
376
  async initProject(projectId = '') {
334
- var _a;
377
+ var _a, _b;
335
378
  const response = await client.query({
336
379
  query: gql `
337
380
  query Project($id: String!) {
338
381
  project(id: $id) {
339
382
  id
383
+ code
340
384
  name
341
385
  state
342
386
  startDate
@@ -362,6 +406,10 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
362
406
  latitude
363
407
  longitude
364
408
  area
409
+ coverageRatio
410
+ floorAreaRatio
411
+ siteType
412
+ workerCount
365
413
  clientCompany
366
414
  constructionCompany
367
415
  supervisoryCompany
@@ -387,14 +435,92 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
387
435
  }
388
436
  }
389
437
  `,
390
- variables: { id: projectId }
438
+ variables: { id: projectId },
439
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
391
440
  });
392
441
  if (response.errors)
393
442
  return;
394
- this.project = ((_a = response.data) === null || _a === void 0 ? void 0 : _a.project) || {};
443
+ this.project = ((_b = response.data) === null || _b === void 0 ? void 0 : _b.project) || {};
395
444
  this.updateContext();
445
+ this._loadPendingMetrics();
446
+ }
447
+ /**
448
+ * 이 프로젝트의 미입력 KPI metric 들을 조회 — Step 1/2 와 동일 기준.
449
+ * - 대상: active=true 인 manual/import metric (자동수집/외부API 제외)
450
+ * - 판정:
451
+ * · MONTH metric → 전월 row (periodType='MONTH', valueDate startsWith 전월) 없으면 pending
452
+ * · 그 외 → (metric, periodType) 매칭 row 없으면 pending
453
+ */
454
+ async _loadPendingMetrics() {
455
+ var _a, _b, _c, _d, _e, _f, _g;
456
+ if (!((_a = this.project) === null || _a === void 0 ? void 0 : _a.id)) {
457
+ this.pendingMetrics = [];
458
+ return;
459
+ }
460
+ try {
461
+ // 1) Active manual/import metric 정의 목록 (periodType 포함)
462
+ const metricsResp = await client.query({
463
+ query: gql `
464
+ query KpiMetrics {
465
+ kpiMetrics {
466
+ items {
467
+ id
468
+ name
469
+ description
470
+ periodType
471
+ collectType
472
+ active
473
+ }
474
+ }
475
+ }
476
+ `,
477
+ context: { headers: tenantHeaders((_b = this.project) === null || _b === void 0 ? void 0 : _b.code) }
478
+ });
479
+ // collectType 필터 제거 — Step 1/2 가 모든 metric 을 보여주므로 동일하게 전체 대상.
480
+ // active=false 인 metric 만 제외.
481
+ const targets = (((_d = (_c = metricsResp.data) === null || _c === void 0 ? void 0 : _c.kpiMetrics) === null || _d === void 0 ? void 0 : _d.items) || []).filter((m) => m.active);
482
+ if (targets.length === 0) {
483
+ this.pendingMetrics = [];
484
+ return;
485
+ }
486
+ // 2) 이 프로젝트의 모든 KpiMetricValue (value 도 가져와서 null/undefined 체크)
487
+ const valuesResp = await client.query({
488
+ query: gql `
489
+ query KpiMetricValues($filters: [Filter!]) {
490
+ kpiMetricValues(filters: $filters) {
491
+ items {
492
+ metricId
493
+ periodType
494
+ valueDate
495
+ value
496
+ }
497
+ }
498
+ }
499
+ `,
500
+ variables: { filters: [{ name: 'org', operator: 'eq', value: this.project.id }] },
501
+ context: { headers: tenantHeaders((_e = this.project) === null || _e === void 0 ? void 0 : _e.code) }
502
+ });
503
+ const values = ((_g = (_f = valuesResp.data) === null || _f === void 0 ? void 0 : _f.kpiMetricValues) === null || _g === void 0 ? void 0 : _g.items) || [];
504
+ const lastMonthYm = moment().tz('Asia/Seoul').subtract(1, 'month').format('YYYY-MM');
505
+ // 3) Step 1/2 와 동일 기준으로 미입력 판정 — row 존재 AND value 존재 (null/undefined 아님).
506
+ const hasValid = (v) => v.value !== null && v.value !== undefined;
507
+ this.pendingMetrics = targets.filter((m) => {
508
+ if (m.periodType === 'MONTH') {
509
+ return !values.some(v => v.metricId === m.id &&
510
+ v.periodType === 'MONTH' &&
511
+ (v.valueDate || '').startsWith(lastMonthYm) &&
512
+ hasValid(v));
513
+ }
514
+ return !values.some(v => v.metricId === m.id && v.periodType === m.periodType && hasValid(v));
515
+ });
516
+ }
517
+ catch (e) {
518
+ console.error('[입력 대기 중] 조회 실패', e);
519
+ this.pendingMetrics = [];
520
+ }
396
521
  }
397
522
  async getKpiComprehensiveStats() {
523
+ var _a;
398
524
  try {
399
525
  const response = await client.query({
400
526
  query: gql `
@@ -407,7 +533,8 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
407
533
  maxVal
408
534
  }
409
535
  }
410
- `
536
+ `,
537
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
411
538
  });
412
539
  this.kpiComprehensiveStats = response.data.totalKpiZValueComprehensiveStats || [];
413
540
  }
@@ -417,6 +544,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
417
544
  }
418
545
  }
419
546
  async getKpiYComprehensiveStats() {
547
+ var _a;
420
548
  try {
421
549
  const response = await client.query({
422
550
  query: gql `
@@ -432,7 +560,8 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
432
560
  projectCount
433
561
  }
434
562
  }
435
- `
563
+ `,
564
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
436
565
  });
437
566
  this.kpiYComprehensiveStats = response.data.totalKpiYValueComprehensiveStats || [];
438
567
  }
@@ -442,6 +571,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
442
571
  }
443
572
  }
444
573
  async getProjectXKpiValues(projectId) {
574
+ var _a;
445
575
  try {
446
576
  const response = await client.query({
447
577
  query: gql `
@@ -458,7 +588,8 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
458
588
  }
459
589
  }
460
590
  `,
461
- variables: { projectId }
591
+ variables: { projectId },
592
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
462
593
  });
463
594
  this.projectXKpiValues = response.data.projectXKpiValues || [];
464
595
  }
@@ -479,7 +610,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
479
610
  this._fetchKpiWithGradesByPattern(kpiNamePattern, metric.label);
480
611
  }
481
612
  async _fetchKpiWithGradesByPattern(kpiNamePattern, displayName) {
482
- var _a, _b, _c;
613
+ var _a, _b, _c, _d;
483
614
  try {
484
615
  // X-KPI 이름 패턴으로 전체 이름 찾기 (projectXKpiValues에서)
485
616
  const kpiValue = this.projectXKpiValues.find(kv => { var _a; return ((_a = kv.kpi) === null || _a === void 0 ? void 0 : _a.name) && kv.kpi.name.includes(kpiNamePattern); });
@@ -501,9 +632,10 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
501
632
  }
502
633
  }
503
634
  `,
504
- variables: { id: kpiValue.kpi.id }
635
+ variables: { id: kpiValue.kpi.id },
636
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
505
637
  });
506
- if (response.errors || !((_a = response.data) === null || _a === void 0 ? void 0 : _a.kpi)) {
638
+ if (response.errors || !((_b = response.data) === null || _b === void 0 ? void 0 : _b.kpi)) {
507
639
  console.error('KPI not found or error:', response.errors);
508
640
  return;
509
641
  }
@@ -518,8 +650,8 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
518
650
  grades: kpi.grades || [],
519
651
  scoreType: kpi.scoreType || '',
520
652
  valueType: kpi.valueType || '',
521
- value: (_b = kpiValue.value) !== null && _b !== void 0 ? _b : null,
522
- unit: ((_c = kpi.vizMeta) === null || _c === void 0 ? void 0 : _c.unit) || ''
653
+ value: (_c = kpiValue.value) !== null && _c !== void 0 ? _c : null,
654
+ unit: ((_d = kpi.vizMeta) === null || _d === void 0 ? void 0 : _d.unit) || ''
523
655
  };
524
656
  this.showScoreDistribution = true;
525
657
  }
@@ -1275,6 +1407,10 @@ __decorate([
1275
1407
  state(),
1276
1408
  __metadata("design:type", Object)
1277
1409
  ], SvProjectDetailPage.prototype, "selectedKpi", void 0);
1410
+ __decorate([
1411
+ state(),
1412
+ __metadata("design:type", Array)
1413
+ ], SvProjectDetailPage.prototype, "pendingMetrics", void 0);
1278
1414
  SvProjectDetailPage = __decorate([
1279
1415
  customElement('sv-project-detail')
1280
1416
  ], SvProjectDetailPage);