@dssp/dkpi 1.0.0-alpha.50 → 1.0.0-alpha.51

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 (28) hide show
  1. package/dist-client/components/kpi-boxplot-chart.d.ts +24 -0
  2. package/dist-client/components/kpi-boxplot-chart.js +328 -0
  3. package/dist-client/components/kpi-boxplot-chart.js.map +1 -0
  4. package/dist-client/components/kpi-radar-chart.d.ts +16 -0
  5. package/dist-client/components/kpi-radar-chart.js +139 -0
  6. package/dist-client/components/kpi-radar-chart.js.map +1 -0
  7. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.d.ts +3 -1
  8. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +25 -12
  9. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +1 -1
  10. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.d.ts +6 -3
  11. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js +101 -92
  12. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js.map +1 -1
  13. package/dist-client/pages/sv-project-complete.d.ts +0 -2
  14. package/dist-client/pages/sv-project-complete.js +14 -20
  15. package/dist-client/pages/sv-project-complete.js.map +1 -1
  16. package/dist-client/pages/sv-project-detail.d.ts +3 -0
  17. package/dist-client/pages/sv-project-detail.js +98 -34
  18. package/dist-client/pages/sv-project-detail.js.map +1 -1
  19. package/dist-client/shared/complete-api.d.ts +4 -1
  20. package/dist-client/shared/complete-api.js +68 -16
  21. package/dist-client/shared/complete-api.js.map +1 -1
  22. package/dist-client/tsconfig.tsbuildinfo +1 -1
  23. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +2 -1
  24. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +28 -20
  25. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  26. package/dist-server/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +3 -3
  28. package/schema.graphql +2 -2
@@ -3,9 +3,12 @@ import { navigate, PageView } from '@operato/shell';
3
3
  import { css, html } from 'lit';
4
4
  import { customElement, state } from 'lit/decorators.js';
5
5
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
6
- import { PROJECT_STATE, ProjectState } from './sv-project-list';
6
+ import { PROJECT_STATE } from './sv-project-list';
7
7
  import { client } from '@operato/graphql';
8
8
  import gql from 'graphql-tag';
9
+ import '../components/kpi-boxplot-chart';
10
+ import '../components/kpi-single-boxplot-chart';
11
+ import '../components/kpi-radar-chart';
9
12
  let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(PageView) {
10
13
  constructor() {
11
14
  super(...arguments);
@@ -17,7 +20,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
17
20
  };
18
21
  }
19
22
  render() {
20
- var _a, _b, _c, _d, _e, _f;
23
+ var _a, _b, _c, _d, _e, _f, _g, _h;
21
24
  return html `
22
25
  <div content>
23
26
  <div left>
@@ -107,42 +110,88 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
107
110
  </div>
108
111
 
109
112
  <div right>
110
- ${this.project.state === ProjectState.ONGOING
111
- ? html `
112
- <div class="button-line">
113
- <div class="ghost-btn" @click=${() => navigate(`project-update/${this.project.id}`)}>
114
- <md-icon slot="">assignment</md-icon>
115
- <div>프로젝트 수정</div>
116
- </div>
117
- <div class="ghost-btn" @click=${() => navigate(`project-complete/${this.project.id}`)}>
118
- <md-icon slot="">assignment_turned_in</md-icon>
119
- <div>프로젝트 완공 처리</div>
120
- </div>
121
- </div>
122
- `
123
- : ''}
113
+ ${html `
114
+ <div class="button-line">
115
+ <div class="ghost-btn" @click=${() => navigate(`project-update/${this.project.id}`)}>
116
+ <md-icon slot="">assignment</md-icon>
117
+ <div>프로젝트 수정</div>
118
+ </div>
119
+ <div class="ghost-btn" @click=${() => navigate(`project-complete/${this.project.id}`)}>
120
+ <md-icon slot="">assignment_turned_in</md-icon>
121
+ <div>프로젝트 완공 처리</div>
122
+ </div>
123
+ </div>
124
+ `}
124
125
 
125
126
  <div class="card kpi-box">
126
127
  <div class="kpi-header">
127
- <div>종합 KPI</div>
128
- <div class="triangle"></div>
129
- </div>
130
- <div class="kpi-desc">
131
- 프로젝트의 생산성, 품질, 안전, 환경, 비용, 일정 등 6개의 성과를 종합한 종합KPI 포인트 정보와 각 지표별
132
- 분포차트입니다.
128
+ <div>
129
+ <div>종합 KPI</div>
130
+ <div class="triangle"></div>
131
+ </div>
132
+ <div class="kpi-desc">프로젝트의 6 성과를 종합한 종합 KPI포인트와 각 지표별 분포</div>
133
133
  </div>
134
134
 
135
135
  <div class="kpi-summary">
136
136
  <div class="mini-boxplot" title="boxplot placeholder">
137
- <div class="boxplot-area">boxplot area</div>
137
+ <div class="boxplot-area">
138
+ <kpi-single-boxplot-chart
139
+ .data=${{
140
+ min: 0,
141
+ max: 100,
142
+ mean: 50,
143
+ median: 60,
144
+ q1: 25,
145
+ q3: 75,
146
+ value: this.project.kpi
147
+ }}
148
+ ></kpi-single-boxplot-chart>
149
+ </div>
138
150
 
139
151
  <div class="boxplot-point">
140
- <div class="value">???</div>
152
+ <div class="value">${(_h = (_g = this.project.kpi) === null || _g === void 0 ? void 0 : _g.toFixed(1)) !== null && _h !== void 0 ? _h : '-'}</div>
141
153
  <div class="label">Point</div>
142
154
  </div>
143
155
  </div>
144
156
 
145
- <div class="spider-area">spider chart</div>
157
+ <div class="spider-area">
158
+ <kpi-radar-chart
159
+ .data=${[
160
+ {
161
+ group: '평균',
162
+ category: '생산성 성과',
163
+ value: 41
164
+ },
165
+ {
166
+ group: '평균',
167
+ category: '일정 성과',
168
+ value: 26
169
+ },
170
+ {
171
+ group: '평균',
172
+ category: '비용 성과',
173
+ value: 30
174
+ },
175
+ {
176
+ group: '평균',
177
+ category: '품질 성과',
178
+ value: 21
179
+ },
180
+ {
181
+ group: '평균',
182
+ category: '안전 성과',
183
+ value: 33
184
+ },
185
+ {
186
+ group: '평균',
187
+ category: '환경 성과',
188
+ value: 15
189
+ }
190
+ ]}
191
+ .categories=${['생산성 성과', '일정 성과', '비용 성과', '품질 성과', '안전 성과', '환경 성과']}
192
+ .currentGroup=${'평균'}
193
+ ></kpi-radar-chart>
194
+ </div>
146
195
  </div>
147
196
  </div>
148
197
 
@@ -407,16 +456,23 @@ SvProjectDetailPage.styles = [
407
456
  flex-direction: column;
408
457
  gap: 10px;
409
458
  padding: 15px;
459
+ max-height: 420px;
460
+ min-width: 560px;
410
461
  }
411
462
  .kpi-header {
412
463
  display: flex;
413
464
  align-items: center;
414
- gap: 5px;
465
+ justify-content: space-between;
415
466
  color: #35618e;
416
467
  font-weight: 700;
417
468
  font-size: 20px;
418
469
  letter-spacing: -0.05em;
419
470
  }
471
+ .kpi-header div {
472
+ display: flex;
473
+ align-items: center;
474
+ gap: 5px;
475
+ }
420
476
  .kpi-desc {
421
477
  color: #35618e;
422
478
  font-size: 13px;
@@ -425,18 +481,22 @@ SvProjectDetailPage.styles = [
425
481
  .kpi-summary {
426
482
  display: flex;
427
483
  align-items: center;
428
- gap: 35px;
429
484
  padding: 0 30px;
485
+ max-height: 360px;
430
486
  }
431
487
  .mini-boxplot {
432
- width: 70px;
488
+ flex: 1;
489
+ display: flex;
490
+ flex-direction: column;
433
491
  height: 100%;
434
492
  position: relative;
493
+ min-width: 120px;
435
494
  }
436
495
  .boxplot-area {
496
+ flex: 1;
437
497
  width: 100%;
438
- height: 190px;
439
498
  display: flex;
499
+ flex-direction: column;
440
500
  align-items: center;
441
501
  background: #ffffff;
442
502
  }
@@ -445,15 +505,13 @@ SvProjectDetailPage.styles = [
445
505
  display: flex;
446
506
  flex-direction: column;
447
507
  align-items: center;
448
- gap: 6px;
449
508
  color: #35618e;
450
509
  }
451
510
  .boxplot-point .value {
452
- font-size: 30px;
453
- font-weight: 700;
511
+ font-size: 42px;
512
+ font-weight: 800;
454
513
  color: #35618e;
455
514
  border-radius: 6px;
456
- padding: 4px 8px;
457
515
  }
458
516
  .boxplot-point .label {
459
517
  font-size: 14px;
@@ -463,11 +521,13 @@ SvProjectDetailPage.styles = [
463
521
 
464
522
  /* spider chart placeholder */
465
523
  .spider-area {
524
+ flex: 5;
466
525
  display: flex;
526
+ flex-direction: column;
467
527
  align-items: center;
468
528
  justify-content: center;
469
529
  gap: 10px;
470
- flex: 1;
530
+ height: 100%;
471
531
  }
472
532
 
473
533
  /* group distribution */
@@ -481,6 +541,10 @@ SvProjectDetailPage.styles = [
481
541
  height: 205px;
482
542
  margin-top: 25px;
483
543
  }
544
+
545
+ kpi-single-boxplot-chart {
546
+ flex: 1;
547
+ }
484
548
  `
485
549
  ];
486
550
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"sv-project-detail.js","sourceRoot":"","sources":["../../client/pages/sv-project-detail.ts"],"names":[],"mappings":"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","sourcesContent":["import { navigate, PageLifecycle, PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { Project, PROJECT_STATE, ProjectState } from './sv-project-list'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\n\n@customElement('sv-project-detail')\nexport class SvProjectDetailPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n }\n\n /* content layout */\n div[content] {\n display: flex;\n gap: 35px;\n padding: 25px;\n }\n div[left] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n }\n div[right] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 0 1px;\n }\n\n /* card */\n .card {\n background: #ffffff;\n border-radius: 10px;\n padding: 15px;\n box-shadow: 3px 3px 3px 0 rgba(0, 0, 0, 0.1);\n }\n .card-title {\n display: flex;\n align-items: center;\n gap: 5px;\n color: #35618e;\n font-weight: 700;\n }\n .triangle {\n width: 0;\n height: 0;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-top: 8px solid #35618e;\n }\n\n /* left top info box */\n .bold {\n font-weight: bold;\n }\n .top-info {\n display: flex;\n gap: 10px;\n }\n .top-info img[pic] {\n width: 284px;\n height: 160px;\n object-fit: fill;\n background: #e5e7eb;\n }\n .top-info .info {\n display: flex;\n flex-direction: column;\n gap: 15px;\n padding: 10px 0;\n flex: 1;\n }\n .row {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n .label {\n min-width: fit-content;\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n .value {\n color: #212529;\n font-size: 16px;\n }\n .status-value {\n color: #4cbb49;\n font-weight: 700;\n }\n\n .address {\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n\n .detail-grid {\n display: grid;\n grid-template-columns: 284px 1fr;\n gap: 15px 10px;\n padding: 5px 0;\n }\n .detail-grid .grid-item .label {\n width: auto;\n }\n\n /* left second card (requests) */\n .sub-desc {\n color: #35618e;\n font-size: 14px;\n letter-spacing: -0.05em;\n margin-bottom: 8px;\n }\n .list-block {\n display: flex;\n flex-direction: column;\n gap: 5px;\n padding: 5px 25px;\n }\n .list-title {\n color: #212529;\n font-weight: 700;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n .list-text {\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n margin-left: 8px;\n }\n .list-text .warn {\n margin-left: 10px;\n color: #e13232;\n\n md-icon {\n font-size: 17px;\n width: 13px;\n height: 13px;\n }\n }\n\n /* right buttons */\n .button-line {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n }\n .ghost-btn {\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 5px 10px;\n background: #35618e;\n color: #ffffff;\n border-radius: 5px;\n box-shadow: 2px 2px 2px 0 rgba(0, 0, 0, 0.1);\n cursor: pointer;\n\n /* Material Symbols Outlined (stroke style) */\n md-icon {\n font-variation-settings:\n 'FILL' 0,\n 'wght' 300,\n 'GRAD' 0,\n 'opsz' 24;\n }\n }\n\n /* right KPI box */\n .kpi-box {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 15px;\n }\n .kpi-header {\n display: flex;\n align-items: center;\n gap: 5px;\n color: #35618e;\n font-weight: 700;\n font-size: 20px;\n letter-spacing: -0.05em;\n }\n .kpi-desc {\n color: #35618e;\n font-size: 13px;\n letter-spacing: -0.05em;\n }\n .kpi-summary {\n display: flex;\n align-items: center;\n gap: 35px;\n padding: 0 30px;\n }\n .mini-boxplot {\n width: 70px;\n height: 100%;\n position: relative;\n }\n .boxplot-area {\n width: 100%;\n height: 190px;\n display: flex;\n align-items: center;\n background: #ffffff;\n }\n\n .boxplot-point {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n color: #35618e;\n }\n .boxplot-point .value {\n font-size: 30px;\n font-weight: 700;\n color: #35618e;\n border-radius: 6px;\n padding: 4px 8px;\n }\n .boxplot-point .label {\n font-size: 14px;\n font-weight: 300;\n width: auto;\n }\n\n /* spider chart placeholder */\n .spider-area {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n flex: 1;\n }\n\n /* group distribution */\n .group-box .desc {\n color: #35618e;\n font-size: 13px;\n letter-spacing: -0.05em;\n margin-top: 4px;\n }\n .group-chart {\n height: 205px;\n margin-top: 25px;\n }\n `\n ]\n\n get context() {\n return {\n title: '프로젝트 상세 정보'\n }\n }\n\n @state() private project: Project = {} as Project\n\n render() {\n return html`\n <div content>\n <div left>\n <div class=\"card\">\n <div class=\"card-title\">\n <div>${this.project.name}</div>\n <div class=\"triangle\"></div>\n </div>\n\n <div class=\"top-info\" style=\"margin-top: 10px;\">\n <img pic src=${this.project.mainPhoto?.fullpath || '/assets/images/no-image.png'} alt=\"project\" />\n <div class=\"info\">\n <div class=\"address\">• ${this.project.buildingComplex?.address}</div>\n <div class=\"row\">\n <div class=\"label\">• 공사기간</div>\n <div class=\"value\">${this.project.startDate} ~ ${this.project.endDate}</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 현장상태</div>\n <div class=\"value status-value\">${PROJECT_STATE[this.project.state]}</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 요청상세</div>\n <div class=\"value bold\">???</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 알람</div>\n <div class=\"value\">???</div>\n </div>\n </div>\n </div>\n\n <div class=\"detail-grid\">\n <div class=\"grid-item row\">\n <div class=\"label\">• 공사비</div>\n <div class=\"value\">${this.project.buildingComplex?.constructionCost?.toLocaleString() || '-'} 원</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 연면적</div>\n <div class=\"value\">${this.project.buildingComplex?.area?.toLocaleString() || '-'} ㎡</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 용적률</div>\n <div class=\"value\">??? %</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 투입인력</div>\n <div class=\"value\">??? 명</div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">\n <div>입력 대기 중</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"sub-desc\">\n 현재 입력 기한이 도래했거나, 입력이 지연되고 있는 KPI 항목입니다. 해당 항목에 대한 데이터를 입력 해 주시기 바랍니다.\n </div>\n\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 대기 중 2건</div>\n <div class=\"list-text\"># 2033312-Y5.1 : 검수자재 불합격률</div>\n <div class=\"list-text\"># 2033312-Y5.1 : 품질시험 불합격 건수</div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 기한 초과 1건</div>\n <div class=\"list-text\">\n # 2033312-Y5.2 : 검측 불합격률 <span class=\"warn\">2025.2.12 <md-icon>report</md-icon></span>\n </div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 예정 4건</div>\n <div class=\"list-text\"># 2033320-Y4.32 : 연면적 대비 공기입력</div>\n <div class=\"list-text\"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>\n <div class=\"list-text\"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>\n <div class=\"list-text\"># 2096412-Y5.31 : 현장별 일정 이탈 수준</div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 기한 없음 3건</div>\n <div class=\"list-text\"># 2033320-Y4.32 : 연면적 대비 공기입력</div>\n <div class=\"list-text\"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>\n <div class=\"list-text\"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>\n </div>\n </div>\n </div>\n\n <div right>\n ${this.project.state === ProjectState.ONGOING\n ? html`\n <div class=\"button-line\">\n <div class=\"ghost-btn\" @click=${() => navigate(`project-update/${this.project.id}`)}>\n <md-icon slot=\"\">assignment</md-icon>\n <div>프로젝트 수정</div>\n </div>\n <div class=\"ghost-btn\" @click=${() => navigate(`project-complete/${this.project.id}`)}>\n <md-icon slot=\"\">assignment_turned_in</md-icon>\n <div>프로젝트 완공 처리</div>\n </div>\n </div>\n `\n : ''}\n\n <div class=\"card kpi-box\">\n <div class=\"kpi-header\">\n <div>종합 KPI</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"kpi-desc\">\n 프로젝트의 생산성, 품질, 안전, 환경, 비용, 일정 등 6개의 성과를 종합한 종합KPI 포인트 정보와 각 지표별\n 분포차트입니다.\n </div>\n\n <div class=\"kpi-summary\">\n <div class=\"mini-boxplot\" title=\"boxplot placeholder\">\n <div class=\"boxplot-area\">boxplot area</div>\n\n <div class=\"boxplot-point\">\n <div class=\"value\">???</div>\n <div class=\"label\">Point</div>\n </div>\n </div>\n\n <div class=\"spider-area\">spider chart</div>\n </div>\n </div>\n\n <div class=\"card group-box\">\n <div class=\"kpi-header\">\n <div>그룹별 분포</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"desc\">\n Boxplot(박스플롯)은 각 카테고리별로 값의 분포(최소, 1사분위, 중앙값, 3사분위, 최대, 평균, 이상치 등)를 보여줍니다.\n 박스는 중앙 50% 구간, 수염은 전체 범위, 굵은 검정색 가로선은 중앙값(메디안), 초록색 원은 평균값(Mean)을 의미합니다.\n 이 프로젝트의 값은 진한 오렌지색 원으로 별도 강조되어 표시되며, 중앙값/평균과 다를 수 있습니다.\n </div>\n <div class=\"group-chart\"></div>\n </div>\n </div>\n </div>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: PageLifecycle) {\n if (this.active) {\n await this.initProject(lifecycle.resourceId)\n }\n }\n\n async initProject(projectId: string = '') {\n const response = await client.query({\n query: gql`\n query Project($id: String!) {\n project(id: $id) {\n id\n name\n state\n startDate\n endDate\n projectType\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n robotCount\n buildingComplex {\n id\n address\n latitude\n longitude\n area\n clientCompany\n constructionCompany\n supervisoryCompany\n designCompany\n drawing {\n id\n name\n fullpath\n }\n constructionType\n constructionCost\n etc\n notice\n householdCount\n buildingCount\n virtualTourLink\n buildings {\n id\n name\n floorCount\n }\n }\n }\n }\n `,\n variables: { id: projectId }\n })\n\n if (response.errors) return\n\n this.project = response.data?.project || ({} as Project)\n }\n}\n"]}
1
+ {"version":3,"file":"sv-project-detail.js","sourceRoot":"","sources":["../../client/pages/sv-project-detail.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAiB,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAClE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAW,aAAa,EAAgB,MAAM,mBAAmB,CAAA;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,iCAAiC,CAAA;AACxC,OAAO,wCAAwC,CAAA;AAC/C,OAAO,+BAA+B,CAAA;AAG/B,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,mBAAmB,CAAC,QAAQ,CAAC;IAA/D;;QAuRY,YAAO,GAAY,EAAa,CAAA;IAmQnD,CAAC;IAzQC,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,YAAY;SACpB,CAAA;IACH,CAAC;IAID,MAAM;;QACJ,OAAO,IAAI,CAAA;;;;;qBAKM,IAAI,CAAC,OAAO,CAAC,IAAI;;;;;6BAKT,CAAA,MAAA,IAAI,CAAC,OAAO,CAAC,SAAS,0CAAE,QAAQ,KAAI,6BAA6B;;yCAErD,MAAA,IAAI,CAAC,OAAO,CAAC,eAAe,0CAAE,OAAO;;;uCAGvC,IAAI,CAAC,OAAO,CAAC,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO;;;;oDAInC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;qCAgBhD,CAAA,MAAA,MAAA,IAAI,CAAC,OAAO,CAAC,eAAe,0CAAE,gBAAgB,0CAAE,cAAc,EAAE,KAAI,GAAG;;;;qCAIvE,CAAA,MAAA,MAAA,IAAI,CAAC,OAAO,CAAC,eAAe,0CAAE,IAAI,0CAAE,cAAc,EAAE,KAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAkDpF,IAAI,CAAA;;8CAE8B,GAAG,EAAE,CAAC,QAAQ,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;;;;8CAInD,GAAG,EAAE,CAAC,QAAQ,CAAC,oBAAoB,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;;;;;WAKxF;;;;;;;;;;;;;;;4BAeiB;YACN,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,EAAE;YACR,MAAM,EAAE,EAAE;YACV,EAAE,EAAE,EAAE;YACN,EAAE,EAAE,EAAE;YACN,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;SACxB;;;;;uCAKkB,MAAA,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,0CAAE,OAAO,CAAC,CAAC,CAAC,mCAAI,GAAG;;;;;;;0BAOhD;YACN;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,EAAE;aACV;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,EAAE;aACV;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,EAAE;aACV;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,EAAE;aACV;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,EAAE;aACV;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,EAAE;aACV;SACF;gCACa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;kCACrD,IAAI;;;;;;;;;;;;;;;;;;;;KAoBjC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAY,EAAE,SAAwB;QACtD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,YAAoB,EAAE;;QACtC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDT;YACD,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;SAC7B,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,MAAM;YAAE,OAAM;QAE3B,IAAI,CAAC,OAAO,GAAG,CAAA,MAAA,QAAQ,CAAC,IAAI,0CAAE,OAAO,KAAK,EAAc,CAAA;IAC1D,CAAC;;AAxhBM,0BAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4QF;CACF,AA9QY,CA8QZ;AAQgB;IAAhB,KAAK,EAAE;;oDAAyC;AAvRtC,mBAAmB;IAD/B,aAAa,CAAC,mBAAmB,CAAC;GACtB,mBAAmB,CA0hB/B","sourcesContent":["import { navigate, PageLifecycle, PageView } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { Project, PROJECT_STATE, ProjectState } from './sv-project-list'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport '../components/kpi-boxplot-chart'\nimport '../components/kpi-single-boxplot-chart'\nimport '../components/kpi-radar-chart'\n\n@customElement('sv-project-detail')\nexport class SvProjectDetailPage extends ScopedElementsMixin(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n }\n\n /* content layout */\n div[content] {\n display: flex;\n gap: 35px;\n padding: 25px;\n }\n div[left] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n }\n div[right] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 0 1px;\n }\n\n /* card */\n .card {\n background: #ffffff;\n border-radius: 10px;\n padding: 15px;\n box-shadow: 3px 3px 3px 0 rgba(0, 0, 0, 0.1);\n }\n .card-title {\n display: flex;\n align-items: center;\n gap: 5px;\n color: #35618e;\n font-weight: 700;\n }\n .triangle {\n width: 0;\n height: 0;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-top: 8px solid #35618e;\n }\n\n /* left top info box */\n .bold {\n font-weight: bold;\n }\n .top-info {\n display: flex;\n gap: 10px;\n }\n .top-info img[pic] {\n width: 284px;\n height: 160px;\n object-fit: fill;\n background: #e5e7eb;\n }\n .top-info .info {\n display: flex;\n flex-direction: column;\n gap: 15px;\n padding: 10px 0;\n flex: 1;\n }\n .row {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n .label {\n min-width: fit-content;\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n .value {\n color: #212529;\n font-size: 16px;\n }\n .status-value {\n color: #4cbb49;\n font-weight: 700;\n }\n\n .address {\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n\n .detail-grid {\n display: grid;\n grid-template-columns: 284px 1fr;\n gap: 15px 10px;\n padding: 5px 0;\n }\n .detail-grid .grid-item .label {\n width: auto;\n }\n\n /* left second card (requests) */\n .sub-desc {\n color: #35618e;\n font-size: 14px;\n letter-spacing: -0.05em;\n margin-bottom: 8px;\n }\n .list-block {\n display: flex;\n flex-direction: column;\n gap: 5px;\n padding: 5px 25px;\n }\n .list-title {\n color: #212529;\n font-weight: 700;\n font-size: 16px;\n letter-spacing: -0.05em;\n }\n .list-text {\n color: #35618e;\n font-size: 16px;\n letter-spacing: -0.05em;\n margin-left: 8px;\n }\n .list-text .warn {\n margin-left: 10px;\n color: #e13232;\n\n md-icon {\n font-size: 17px;\n width: 13px;\n height: 13px;\n }\n }\n\n /* right buttons */\n .button-line {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n }\n .ghost-btn {\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 5px 10px;\n background: #35618e;\n color: #ffffff;\n border-radius: 5px;\n box-shadow: 2px 2px 2px 0 rgba(0, 0, 0, 0.1);\n cursor: pointer;\n\n /* Material Symbols Outlined (stroke style) */\n md-icon {\n font-variation-settings:\n 'FILL' 0,\n 'wght' 300,\n 'GRAD' 0,\n 'opsz' 24;\n }\n }\n\n /* right KPI box */\n .kpi-box {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 15px;\n max-height: 420px;\n min-width: 560px;\n }\n .kpi-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: #35618e;\n font-weight: 700;\n font-size: 20px;\n letter-spacing: -0.05em;\n }\n .kpi-header div {\n display: flex;\n align-items: center;\n gap: 5px;\n }\n .kpi-desc {\n color: #35618e;\n font-size: 13px;\n letter-spacing: -0.05em;\n }\n .kpi-summary {\n display: flex;\n align-items: center;\n padding: 0 30px;\n max-height: 360px;\n }\n .mini-boxplot {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n position: relative;\n min-width: 120px;\n }\n .boxplot-area {\n flex: 1;\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n background: #ffffff;\n }\n\n .boxplot-point {\n display: flex;\n flex-direction: column;\n align-items: center;\n color: #35618e;\n }\n .boxplot-point .value {\n font-size: 42px;\n font-weight: 800;\n color: #35618e;\n border-radius: 6px;\n }\n .boxplot-point .label {\n font-size: 14px;\n font-weight: 300;\n width: auto;\n }\n\n /* spider chart placeholder */\n .spider-area {\n flex: 5;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n height: 100%;\n }\n\n /* group distribution */\n .group-box .desc {\n color: #35618e;\n font-size: 13px;\n letter-spacing: -0.05em;\n margin-top: 4px;\n }\n .group-chart {\n height: 205px;\n margin-top: 25px;\n }\n\n kpi-single-boxplot-chart {\n flex: 1;\n }\n `\n ]\n\n get context() {\n return {\n title: '프로젝트 상세 정보'\n }\n }\n\n @state() private project: Project = {} as Project\n\n render() {\n return html`\n <div content>\n <div left>\n <div class=\"card\">\n <div class=\"card-title\">\n <div>${this.project.name}</div>\n <div class=\"triangle\"></div>\n </div>\n\n <div class=\"top-info\" style=\"margin-top: 10px;\">\n <img pic src=${this.project.mainPhoto?.fullpath || '/assets/images/no-image.png'} alt=\"project\" />\n <div class=\"info\">\n <div class=\"address\">• ${this.project.buildingComplex?.address}</div>\n <div class=\"row\">\n <div class=\"label\">• 공사기간</div>\n <div class=\"value\">${this.project.startDate} ~ ${this.project.endDate}</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 현장상태</div>\n <div class=\"value status-value\">${PROJECT_STATE[this.project.state]}</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 요청상세</div>\n <div class=\"value bold\">???</div>\n </div>\n <div class=\"row\">\n <div class=\"label\">• 알람</div>\n <div class=\"value\">???</div>\n </div>\n </div>\n </div>\n\n <div class=\"detail-grid\">\n <div class=\"grid-item row\">\n <div class=\"label\">• 공사비</div>\n <div class=\"value\">${this.project.buildingComplex?.constructionCost?.toLocaleString() || '-'} 원</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 연면적</div>\n <div class=\"value\">${this.project.buildingComplex?.area?.toLocaleString() || '-'} ㎡</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 용적률</div>\n <div class=\"value\">??? %</div>\n </div>\n <div class=\"grid-item row\">\n <div class=\"label\">• 투입인력</div>\n <div class=\"value\">??? 명</div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">\n <div>입력 대기 중</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"sub-desc\">\n 현재 입력 기한이 도래했거나, 입력이 지연되고 있는 KPI 항목입니다. 해당 항목에 대한 데이터를 입력 해 주시기 바랍니다.\n </div>\n\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 대기 중 2건</div>\n <div class=\"list-text\"># 2033312-Y5.1 : 검수자재 불합격률</div>\n <div class=\"list-text\"># 2033312-Y5.1 : 품질시험 불합격 건수</div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 기한 초과 1건</div>\n <div class=\"list-text\">\n # 2033312-Y5.2 : 검측 불합격률 <span class=\"warn\">2025.2.12 <md-icon>report</md-icon></span>\n </div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 예정 4건</div>\n <div class=\"list-text\"># 2033320-Y4.32 : 연면적 대비 공기입력</div>\n <div class=\"list-text\"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>\n <div class=\"list-text\"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>\n <div class=\"list-text\"># 2096412-Y5.31 : 현장별 일정 이탈 수준</div>\n </div>\n <div class=\"list-block\">\n <div class=\"list-title\">• 입력 기한 없음 3건</div>\n <div class=\"list-text\"># 2033320-Y4.32 : 연면적 대비 공기입력</div>\n <div class=\"list-text\"># 2012345-Y4.32 : 책임감리원의 일정성과 수준 평가</div>\n <div class=\"list-text\"># 2035641-Y5.22 : 설계 변경에 따른 공기 증감률</div>\n </div>\n </div>\n </div>\n\n <div right>\n ${html`\n <div class=\"button-line\">\n <div class=\"ghost-btn\" @click=${() => navigate(`project-update/${this.project.id}`)}>\n <md-icon slot=\"\">assignment</md-icon>\n <div>프로젝트 수정</div>\n </div>\n <div class=\"ghost-btn\" @click=${() => navigate(`project-complete/${this.project.id}`)}>\n <md-icon slot=\"\">assignment_turned_in</md-icon>\n <div>프로젝트 완공 처리</div>\n </div>\n </div>\n `}\n\n <div class=\"card kpi-box\">\n <div class=\"kpi-header\">\n <div>\n <div>종합 KPI</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"kpi-desc\">프로젝트의 6개 성과를 종합한 종합 KPI포인트와 각 지표별 분포</div>\n </div>\n\n <div class=\"kpi-summary\">\n <div class=\"mini-boxplot\" title=\"boxplot placeholder\">\n <div class=\"boxplot-area\">\n <kpi-single-boxplot-chart\n .data=${{\n min: 0,\n max: 100,\n mean: 50,\n median: 60,\n q1: 25,\n q3: 75,\n value: this.project.kpi\n }}\n ></kpi-single-boxplot-chart>\n </div>\n\n <div class=\"boxplot-point\">\n <div class=\"value\">${this.project.kpi?.toFixed(1) ?? '-'}</div>\n <div class=\"label\">Point</div>\n </div>\n </div>\n\n <div class=\"spider-area\">\n <kpi-radar-chart\n .data=${[\n {\n group: '평균',\n category: '생산성 성과',\n value: 41\n },\n {\n group: '평균',\n category: '일정 성과',\n value: 26\n },\n {\n group: '평균',\n category: '비용 성과',\n value: 30\n },\n {\n group: '평균',\n category: '품질 성과',\n value: 21\n },\n {\n group: '평균',\n category: '안전 성과',\n value: 33\n },\n {\n group: '평균',\n category: '환경 성과',\n value: 15\n }\n ]}\n .categories=${['생산성 성과', '일정 성과', '비용 성과', '품질 성과', '안전 성과', '환경 성과']}\n .currentGroup=${'평균'}\n ></kpi-radar-chart>\n </div>\n </div>\n </div>\n\n <div class=\"card group-box\">\n <div class=\"kpi-header\">\n <div>그룹별 분포</div>\n <div class=\"triangle\"></div>\n </div>\n <div class=\"desc\">\n Boxplot(박스플롯)은 각 카테고리별로 값의 분포(최소, 1사분위, 중앙값, 3사분위, 최대, 평균, 이상치 등)를 보여줍니다.\n 박스는 중앙 50% 구간, 수염은 전체 범위, 굵은 검정색 가로선은 중앙값(메디안), 초록색 원은 평균값(Mean)을 의미합니다.\n 이 프로젝트의 값은 진한 오렌지색 원으로 별도 강조되어 표시되며, 중앙값/평균과 다를 수 있습니다.\n </div>\n <div class=\"group-chart\"></div>\n </div>\n </div>\n </div>\n `\n }\n\n async pageUpdated(changes: any, lifecycle: PageLifecycle) {\n if (this.active) {\n await this.initProject(lifecycle.resourceId)\n }\n }\n\n async initProject(projectId: string = '') {\n const response = await client.query({\n query: gql`\n query Project($id: String!) {\n project(id: $id) {\n id\n name\n state\n startDate\n endDate\n projectType\n mainPhoto {\n fullpath\n }\n totalProgress\n weeklyProgress\n kpi\n inspPassRate\n robotProgressRate\n structuralSafetyRate\n robotCount\n buildingComplex {\n id\n address\n latitude\n longitude\n area\n clientCompany\n constructionCompany\n supervisoryCompany\n designCompany\n drawing {\n id\n name\n fullpath\n }\n constructionType\n constructionCost\n etc\n notice\n householdCount\n buildingCount\n virtualTourLink\n buildings {\n id\n name\n floorCount\n }\n }\n }\n }\n `,\n variables: { id: projectId }\n })\n\n if (response.errors) return\n\n this.project = response.data?.project || ({} as Project)\n }\n}\n"]}
@@ -1,5 +1,8 @@
1
1
  export declare const getProject: (projectId: string) => Promise<any>;
2
2
  export declare const getKpiMetrics: () => Promise<any>;
3
3
  export declare const getKpiMetricValues: (projectId: string) => Promise<any>;
4
- export declare const updateProjectCompleteStep1: (patches: any) => Promise<import("@apollo/client").InteropMutateResult<any>>;
5
4
  export declare const getKpiCategories: () => Promise<any>;
5
+ export declare const updateProjectCompleteStep1: (patches: any) => Promise<import("@apollo/client").InteropMutateResult<any>>;
6
+ export declare const updateProjectCompleteStep2: (patches: any) => Promise<import("@apollo/client").InteropMutateResult<any>>;
7
+ export declare const updateProjectCompleteStep3: (file: any, projectId: string) => Promise<import("@apollo/client").InteropMutateResult<any>>;
8
+ export declare const updateProjectCompleteFinalize: (projectId: string) => Promise<import("@apollo/client").InteropMutateResult<any>>;
@@ -11,7 +11,7 @@ export const getProject = async (projectId) => {
11
11
  endDate
12
12
  state
13
13
 
14
- completeReports {
14
+ completeReport {
15
15
  id
16
16
  name
17
17
  fullpath
@@ -81,21 +81,6 @@ export const getKpiMetricValues = async (projectId) => {
81
81
  }
82
82
  return response.data.kpiMetricValues.items;
83
83
  };
84
- export const updateProjectCompleteStep1 = async (patches) => {
85
- const response = await client.mutate({
86
- mutation: gql `
87
- mutation UpdateKpiMetricValuesCumulative($patches: [KpiMetricValuePatch!]!) {
88
- updateKpiMetricValuesCumulative(patches: $patches) {
89
- id
90
- }
91
- }
92
- `,
93
- variables: {
94
- patches
95
- }
96
- });
97
- return response;
98
- };
99
84
  export const getKpiCategories = async () => {
100
85
  const response = await client.query({
101
86
  query: gql `
@@ -122,4 +107,71 @@ export const getKpiCategories = async () => {
122
107
  }
123
108
  return response.data.kpiCategories;
124
109
  };
110
+ export const updateProjectCompleteStep1 = async (patches) => {
111
+ const response = await client.mutate({
112
+ mutation: gql `
113
+ mutation UpdateKpiMetricValuesCumulative($patches: [KpiMetricValuePatch!]!) {
114
+ updateKpiMetricValuesCumulative(patches: $patches) {
115
+ id
116
+ }
117
+ }
118
+ `,
119
+ variables: {
120
+ patches
121
+ }
122
+ });
123
+ return response;
124
+ };
125
+ export const updateProjectCompleteStep2 = async (patches) => {
126
+ const response = await client.mutate({
127
+ mutation: gql `
128
+ mutation UpdateKpiMetricValuesAssessment($patches: [KpiMetricValuePatch!]!) {
129
+ updateKpiMetricValuesAssessment(patches: $patches) {
130
+ id
131
+ }
132
+ }
133
+ `,
134
+ variables: {
135
+ patches
136
+ }
137
+ });
138
+ return response;
139
+ };
140
+ export const updateProjectCompleteStep3 = async (file, projectId) => {
141
+ const response = await client.mutate({
142
+ mutation: gql `
143
+ mutation UpdateKpiMetricValuesSentiment($attachment: NewAttachment!) {
144
+ updateKpiMetricValuesSentiment(attachment: $attachment) {
145
+ id
146
+ name
147
+ fullpath
148
+ }
149
+ }
150
+ `,
151
+ variables: {
152
+ attachment: {
153
+ file,
154
+ refBy: projectId,
155
+ refType: 'ProjectCompleteReport'
156
+ }
157
+ },
158
+ context: {
159
+ hasUpload: true
160
+ }
161
+ });
162
+ return response;
163
+ };
164
+ export const updateProjectCompleteFinalize = async (projectId) => {
165
+ const response = await client.mutate({
166
+ mutation: gql `
167
+ mutation FinalizeProjectWithKpiRecalculation($projectId: String!) {
168
+ finalizeProjectWithKpiRecalculation(projectId: $projectId)
169
+ }
170
+ `,
171
+ variables: {
172
+ projectId
173
+ }
174
+ });
175
+ return response;
176
+ };
125
177
  //# sourceMappingURL=complete-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"complete-api.js","sourceRoot":"","sources":["../../client/shared/complete-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,SAAiB,EAAE,EAAE;IACpD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;KA0BT;QACD,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;KAC7B,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAA;AAC9B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;IACtC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;KAWT;KACF,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAA;AACvC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,SAAiB,EAAE,EAAE;IAC5D,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IAEnE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;KAYT;QACD,SAAS,EAAE;YACT,OAAO;SACR;KACF,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAA;AAC5C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,OAAY,EAAE,EAAE;IAC/D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;QACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;KAMZ;QACD,SAAS,EAAE;YACT,OAAO;SACR;KACF,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;IACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;KAiBT;KACF,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAA;AACpC,CAAC,CAAA","sourcesContent":["import { gql } from '@apollo/client'\nimport { client } from '@operato/graphql'\n\nexport const getProject = async (projectId: string) => {\n const response = await client.query({\n query: gql`\n query Project($id: String!) {\n project(id: $id) {\n id\n name\n startDate\n endDate\n state\n\n completeReports {\n id\n name\n fullpath\n }\n\n buildingComplex {\n id\n coverageRatio\n floorAreaRatio\n workerCount\n designChangeCount\n constructionCost\n area\n }\n }\n }\n `,\n variables: { id: projectId }\n })\n\n if (response.errors) {\n return {}\n }\n\n return response.data.project\n}\n\nexport const getKpiMetrics = async () => {\n const response = await client.query({\n query: gql`\n query KpiMetrics {\n kpiMetrics {\n items {\n id\n name\n unit\n periodType\n }\n }\n }\n `\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiMetrics.items\n}\n\nexport const getKpiMetricValues = async (projectId: string) => {\n const filters = [{ name: 'org', operator: 'eq', value: projectId }]\n\n const response = await client.query({\n query: gql`\n query KpiMetricValues($filters: [Filter!]) {\n kpiMetricValues(filters: $filters) {\n items {\n id\n value\n unit\n periodType\n metricId\n }\n }\n }\n `,\n variables: {\n filters\n }\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiMetricValues.items\n}\n\nexport const updateProjectCompleteStep1 = async (patches: any) => {\n const response = await client.mutate({\n mutation: gql`\n mutation UpdateKpiMetricValuesCumulative($patches: [KpiMetricValuePatch!]!) {\n updateKpiMetricValuesCumulative(patches: $patches) {\n id\n }\n }\n `,\n variables: {\n patches\n }\n })\n\n return response\n}\n\nexport const getKpiCategories = async () => {\n const response = await client.query({\n query: gql`\n query {\n kpiCategories: kpisLevel1 {\n id\n name\n description\n active\n kpis: children {\n id\n name\n description\n formula\n active\n grades\n }\n }\n }\n `\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiCategories\n}\n"]}
1
+ {"version":3,"file":"complete-api.js","sourceRoot":"","sources":["../../client/shared/complete-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { gql } from '@apollo/client'\nimport { client } from '@operato/graphql'\n\nexport const getProject = async (projectId: string) => {\n const response = await client.query({\n query: gql`\n query Project($id: String!) {\n project(id: $id) {\n id\n name\n startDate\n endDate\n state\n\n completeReport {\n id\n name\n fullpath\n }\n\n buildingComplex {\n id\n coverageRatio\n floorAreaRatio\n workerCount\n designChangeCount\n constructionCost\n area\n }\n }\n }\n `,\n variables: { id: projectId }\n })\n\n if (response.errors) {\n return {}\n }\n\n return response.data.project\n}\n\nexport const getKpiMetrics = async () => {\n const response = await client.query({\n query: gql`\n query KpiMetrics {\n kpiMetrics {\n items {\n id\n name\n unit\n periodType\n }\n }\n }\n `\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiMetrics.items\n}\n\nexport const getKpiMetricValues = async (projectId: string) => {\n const filters = [{ name: 'org', operator: 'eq', value: projectId }]\n\n const response = await client.query({\n query: gql`\n query KpiMetricValues($filters: [Filter!]) {\n kpiMetricValues(filters: $filters) {\n items {\n id\n value\n unit\n periodType\n metricId\n }\n }\n }\n `,\n variables: {\n filters\n }\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiMetricValues.items\n}\n\nexport const getKpiCategories = async () => {\n const response = await client.query({\n query: gql`\n query {\n kpiCategories: kpisLevel1 {\n id\n name\n description\n active\n kpis: children {\n id\n name\n description\n formula\n active\n grades\n }\n }\n }\n `\n })\n\n if (response.errors) {\n return []\n }\n\n return response.data.kpiCategories\n}\n\nexport const updateProjectCompleteStep1 = async (patches: any) => {\n const response = await client.mutate({\n mutation: gql`\n mutation UpdateKpiMetricValuesCumulative($patches: [KpiMetricValuePatch!]!) {\n updateKpiMetricValuesCumulative(patches: $patches) {\n id\n }\n }\n `,\n variables: {\n patches\n }\n })\n\n return response\n}\n\nexport const updateProjectCompleteStep2 = async (patches: any) => {\n const response = await client.mutate({\n mutation: gql`\n mutation UpdateKpiMetricValuesAssessment($patches: [KpiMetricValuePatch!]!) {\n updateKpiMetricValuesAssessment(patches: $patches) {\n id\n }\n }\n `,\n variables: {\n patches\n }\n })\n\n return response\n}\n\nexport const updateProjectCompleteStep3 = async (file: any, projectId: string) => {\n const response = await client.mutate({\n mutation: gql`\n mutation UpdateKpiMetricValuesSentiment($attachment: NewAttachment!) {\n updateKpiMetricValuesSentiment(attachment: $attachment) {\n id\n name\n fullpath\n }\n }\n `,\n variables: {\n attachment: {\n file,\n refBy: projectId,\n refType: 'ProjectCompleteReport'\n }\n },\n context: {\n hasUpload: true\n }\n })\n\n return response\n}\n\nexport const updateProjectCompleteFinalize = async (projectId: string) => {\n const response = await client.mutate({\n mutation: gql`\n mutation FinalizeProjectWithKpiRecalculation($projectId: String!) {\n finalizeProjectWithKpiRecalculation(projectId: $projectId)\n }\n `,\n variables: {\n projectId\n }\n })\n\n return response\n}\n"]}