@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
@@ -0,0 +1,1331 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/icon/icon.js';
3
+ import '@material/web/button/elevated-button.js';
4
+ import '@material/web/textfield/outlined-text-field.js';
5
+ import { PageView } from '@operato/shell';
6
+ import { css, html } from 'lit';
7
+ import { customElement, state } from 'lit/decorators.js';
8
+ import { ScopedElementsMixin } from '@open-wc/scoped-elements';
9
+ import { client } from '@operato/graphql';
10
+ import { notify } from '@operato/layout';
11
+ import { OxPrompt } from '@operato/popup';
12
+ import gql from 'graphql-tag';
13
+ import { SITE_TYPE_DISPLAY } from '@dssp/project/dist-client/pages/project/project-list';
14
+ import '@dssp/project/dist-client/pages/lib/select2-component';
15
+ import './component/project-update-header';
16
+ import { isProjectTypeDomain, tenantHeaders } from '@dssp/project/dist-client/shared/domain-context';
17
+ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView) {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.defaultProject = {
21
+ name: '',
22
+ documentNaming: '',
23
+ buildingComplex: {
24
+ address: '',
25
+ area: 0,
26
+ constructionCompany: '',
27
+ clientCompany: '',
28
+ supervisoryCompany: '',
29
+ designCompany: '',
30
+ constructionType: '',
31
+ buildings: []
32
+ }
33
+ };
34
+ this.projectId = '';
35
+ this.project = Object.assign({}, this.defaultProject);
36
+ this.selectedValues = [];
37
+ this.overallConstructorList = [];
38
+ this.taskConstructorList = [];
39
+ this.taskSupervisoryList = [];
40
+ this.overallSupervisoryList = [];
41
+ this.collectingBasicInfo = false;
42
+ /**
43
+ * 완료(COMPLETED) 상태 프로젝트를 진행중(ONGOING) 으로 되돌림.
44
+ * ProjectPatch 의 state 필드만 갱신 — 다른 폼 필드는 건드리지 않음.
45
+ */
46
+ this._onUnfinalize = async () => {
47
+ var _a, _b;
48
+ if (!((_a = this.project) === null || _a === void 0 ? void 0 : _a.id))
49
+ return;
50
+ const ok = await OxPrompt.open({
51
+ title: '완료 상태 해제',
52
+ confirmButton: { text: '확인' },
53
+ cancelButton: { text: '취소' }
54
+ });
55
+ if (!ok)
56
+ return;
57
+ const response = await client.mutate({
58
+ mutation: gql `
59
+ mutation UpdateProject($project: ProjectPatch!) {
60
+ updateProject(project: $project) {
61
+ id
62
+ state
63
+ }
64
+ }
65
+ `,
66
+ variables: { project: { id: this.project.id, state: 'ONGOING' } },
67
+ context: { headers: tenantHeaders((_b = this.project) === null || _b === void 0 ? void 0 : _b.code) }
68
+ });
69
+ if (!response.errors) {
70
+ notify({ message: '진행중 상태로 변경되었습니다.' });
71
+ await this.initProject(this.project.id);
72
+ }
73
+ };
74
+ }
75
+ get context() {
76
+ var _a, _b;
77
+ return {
78
+ title: !isProjectTypeDomain() && ((_a = this.project) === null || _a === void 0 ? void 0 : _a.name)
79
+ ? `프로젝트 정보 관리 - ${(_b = this.project) === null || _b === void 0 ? void 0 : _b.name}`
80
+ : '프로젝트 정보 관리'
81
+ };
82
+ }
83
+ render() {
84
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25;
85
+ return html `
86
+ <dkpi-project-update-header
87
+ .projectId=${this.project.id || ''}
88
+ .projectState=${this.project.state || ''}
89
+ title="프로젝트 정보 관리"
90
+ @custom-click=${this._saveProject}
91
+ @unfinalize=${this._onUnfinalize}
92
+ ></dkpi-project-update-header>
93
+
94
+ <div body>
95
+ <div project-info>
96
+ <h3>기본 정보</h3>
97
+ <div row>
98
+ <span>프로젝트명</span>
99
+ <span
100
+ ><md-outlined-text-field
101
+ type="text"
102
+ name="name"
103
+ project
104
+ .value=${this.project.name || ''}
105
+ @input=${this._onInputChange}
106
+ ></md-outlined-text-field>
107
+ </span>
108
+ </div>
109
+ <div row>
110
+ <span>프로젝트 문서 네이밍</span>
111
+ <span>
112
+ <md-outlined-text-field
113
+ type="text"
114
+ name="documentNaming"
115
+ project
116
+ .value=${this.project.documentNaming || ''}
117
+ @input=${this._onInputChange}
118
+ placeholder="프로젝트 문서 네이밍"
119
+ ></md-outlined-text-field>
120
+ </span>
121
+ </div>
122
+ <div row>
123
+ <span></span>
124
+ <span>
125
+ <div document-preview>📄 문서 생성 예시: <br />${this.project.documentNaming} 검측 제01-00001호</div>
126
+ </span>
127
+ </div>
128
+ <div row>
129
+ <span>프로젝트 주소</span>
130
+ <span class="address-row">
131
+ <md-outlined-text-field
132
+ type="text"
133
+ name="address"
134
+ building-complex
135
+ .value=${((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.buildingComplex) === null || _b === void 0 ? void 0 : _b.address) || ''}
136
+ @input=${this._onInputChange}
137
+ ></md-outlined-text-field>
138
+ <md-elevated-button
139
+ class="info-link-btn"
140
+ ?disabled=${this.collectingBasicInfo}
141
+ @click=${() => this._collectBasicInfo()}
142
+ title="입력된 주소로 세움터 건축물대장 정보를 가져와 폼을 채웁니다"
143
+ >
144
+ ${this.collectingBasicInfo ? '연동 중…' : '🔗 정보 연동'}
145
+ </md-elevated-button>
146
+ </span>
147
+ </div>
148
+ <div row>
149
+ <span>위도</span>
150
+ <span>
151
+ <md-outlined-text-field
152
+ type="text"
153
+ name="latitude"
154
+ numeric
155
+ building-complex
156
+ .value=${((_e = (_d = (_c = this.project) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.latitude) === null || _e === void 0 ? void 0 : _e.toString()) || ''}
157
+ @input=${this._onInputChange}
158
+ ></md-outlined-text-field>
159
+ </span>
160
+ </div>
161
+ <div row>
162
+ <span>경도</span>
163
+ <span>
164
+ <md-outlined-text-field
165
+ type="text"
166
+ name="longitude"
167
+ numeric
168
+ building-complex
169
+ .value=${((_h = (_g = (_f = this.project) === null || _f === void 0 ? void 0 : _f.buildingComplex) === null || _g === void 0 ? void 0 : _g.longitude) === null || _h === void 0 ? void 0 : _h.toString()) || ''}
170
+ @input=${this._onInputChange}
171
+ ></md-outlined-text-field>
172
+ </span>
173
+ </div>
174
+ <div row>
175
+ <span>연 면적</span>
176
+ <span align-end
177
+ ><md-outlined-text-field
178
+ type="text"
179
+ name="area"
180
+ numeric
181
+ building-complex
182
+ .value=${((_l = (_k = (_j = this.project) === null || _j === void 0 ? void 0 : _j.buildingComplex) === null || _k === void 0 ? void 0 : _k.area) === null || _l === void 0 ? void 0 : _l.toString()) || ''}
183
+ @input=${this._onInputChange}
184
+ suffix-text="㎡"
185
+ ></md-outlined-text-field>
186
+ </span>
187
+ </div>
188
+
189
+ <div row>
190
+ <span>건폐율</span>
191
+ <span align-end>
192
+ <md-outlined-text-field
193
+ type="text"
194
+ name="coverageRatio"
195
+ numeric
196
+ building-complex
197
+ .value=${((_p = (_o = (_m = this.project) === null || _m === void 0 ? void 0 : _m.buildingComplex) === null || _o === void 0 ? void 0 : _o.coverageRatio) === null || _p === void 0 ? void 0 : _p.toString()) || ''}
198
+ @input=${this._onInputChange}
199
+ suffix-text="%"
200
+ ></md-outlined-text-field>
201
+ </span>
202
+ </div>
203
+ <div row>
204
+ <span>용적률</span>
205
+ <span align-end>
206
+ <md-outlined-text-field
207
+ type="text"
208
+ name="floorAreaRatio"
209
+ numeric
210
+ building-complex
211
+ .value=${((_s = (_r = (_q = this.project) === null || _q === void 0 ? void 0 : _q.buildingComplex) === null || _r === void 0 ? void 0 : _r.floorAreaRatio) === null || _s === void 0 ? void 0 : _s.toString()) || ''}
212
+ @input=${this._onInputChange}
213
+ suffix-text="%"
214
+ ></md-outlined-text-field>
215
+ </span>
216
+ </div>
217
+
218
+ <div row>
219
+ <span>현장유형</span>
220
+ <span
221
+ ><md-filled-select name="siteType" building-complex @change=${this._onInputChange}>
222
+ ${Object.entries(SITE_TYPE_DISPLAY).map(([key, display]) => {
223
+ var _a, _b;
224
+ return html `
225
+ <md-select-option ?selected=${((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.buildingComplex) === null || _b === void 0 ? void 0 : _b.siteType) === key} .value=${key}>
226
+ <div slot="headline">${display}</div>
227
+ </md-select-option>
228
+ `;
229
+ })}
230
+ </md-filled-select>
231
+ </span>
232
+ </div>
233
+
234
+ <div row>
235
+ <span>착공일정 ~ 준공일정</span>
236
+ <span
237
+ ><input
238
+ type="date"
239
+ name="startDate"
240
+ project
241
+ .value=${this.project.startDate || ''}
242
+ @input=${this._onInputChange}
243
+ max="9999-12-31"
244
+ />
245
+ ~
246
+ <input
247
+ type="date"
248
+ name="endDate"
249
+ project
250
+ .value=${this.project.endDate || ''}
251
+ @input=${this._onInputChange}
252
+ max="9999-12-31"
253
+ />
254
+ </span>
255
+ </div>
256
+ <div row>
257
+ <span>발주처</span>
258
+ <span
259
+ ><md-outlined-text-field
260
+ type="text"
261
+ name="clientCompany"
262
+ building-complex
263
+ .value=${((_u = (_t = this.project) === null || _t === void 0 ? void 0 : _t.buildingComplex) === null || _u === void 0 ? void 0 : _u.clientCompany) || ''}
264
+ @input=${this._onInputChange}
265
+ ></md-outlined-text-field>
266
+ </span>
267
+ </div>
268
+ <div row>
269
+ <span>건설사</span>
270
+ <span
271
+ ><md-outlined-text-field
272
+ type="text"
273
+ name="constructionCompany"
274
+ building-complex
275
+ .value=${((_w = (_v = this.project) === null || _v === void 0 ? void 0 : _v.buildingComplex) === null || _w === void 0 ? void 0 : _w.constructionCompany) || ''}
276
+ @input=${this._onInputChange}
277
+ ></md-outlined-text-field>
278
+ </span>
279
+ </div>
280
+ <div row>
281
+ <span>설계사</span>
282
+ <span
283
+ ><md-outlined-text-field
284
+ type="text"
285
+ name="designCompany"
286
+ building-complex
287
+ .value=${((_y = (_x = this.project) === null || _x === void 0 ? void 0 : _x.buildingComplex) === null || _y === void 0 ? void 0 : _y.designCompany) || ''}
288
+ @input=${this._onInputChange}
289
+ ></md-outlined-text-field>
290
+ </span>
291
+ </div>
292
+ <div row>
293
+ <span>감리사</span>
294
+ <span
295
+ ><md-outlined-text-field
296
+ type="text"
297
+ name="supervisoryCompany"
298
+ building-complex
299
+ .value=${((_0 = (_z = this.project) === null || _z === void 0 ? void 0 : _z.buildingComplex) === null || _0 === void 0 ? void 0 : _0.supervisoryCompany) || ''}
300
+ @input=${this._onInputChange}
301
+ ></md-outlined-text-field>
302
+ </span>
303
+ </div>
304
+ <div row>
305
+ <span>건설구분</span>
306
+ <span
307
+ ><md-outlined-text-field
308
+ type="text"
309
+ name="constructionType"
310
+ building-complex
311
+ .value=${((_2 = (_1 = this.project) === null || _1 === void 0 ? void 0 : _1.buildingComplex) === null || _2 === void 0 ? void 0 : _2.constructionType) || ''}
312
+ @input=${this._onInputChange}
313
+ ></md-outlined-text-field>
314
+ </span>
315
+ </div>
316
+ <div row>
317
+ <span>구조 유형</span>
318
+ <span
319
+ ><md-outlined-text-field
320
+ type="text"
321
+ name="structureType"
322
+ building-complex
323
+ .value=${((_4 = (_3 = this.project) === null || _3 === void 0 ? void 0 : _3.buildingComplex) === null || _4 === void 0 ? void 0 : _4.structureType) || ''}
324
+ @input=${this._onInputChange}
325
+ ></md-outlined-text-field>
326
+ </span>
327
+ </div>
328
+
329
+ <div row>
330
+ <span>대표사진 업로드</span>
331
+ <span>
332
+ <ox-input-image
333
+ name="mainPhoto"
334
+ value=${((_6 = (_5 = this.project) === null || _5 === void 0 ? void 0 : _5.mainPhoto) === null || _6 === void 0 ? void 0 : _6.fullpath) || ''}
335
+ @change=${this.onCreateAttachment.bind(this)}
336
+ ></ox-input-image>
337
+ </span>
338
+ </div>
339
+ <div row>
340
+ <span>공사금액</span>
341
+ <span
342
+ ><md-outlined-text-field
343
+ type="text"
344
+ name="constructionCost"
345
+ numeric
346
+ building-complex
347
+ .value=${((_9 = (_8 = (_7 = this.project) === null || _7 === void 0 ? void 0 : _7.buildingComplex) === null || _8 === void 0 ? void 0 : _8.constructionCost) === null || _9 === void 0 ? void 0 : _9.toString()) || ''}
348
+ @input=${this._onInputChange}
349
+ suffix-text="억원"
350
+ ></md-outlined-text-field>
351
+ </span>
352
+ </div>
353
+ <div row>
354
+ <span>투입 인력</span>
355
+ <span
356
+ ><md-outlined-text-field
357
+ type="text"
358
+ name="workerCount"
359
+ numeric
360
+ building-complex
361
+ .value=${((_12 = (_11 = (_10 = this.project) === null || _10 === void 0 ? void 0 : _10.buildingComplex) === null || _11 === void 0 ? void 0 : _11.workerCount) === null || _12 === void 0 ? void 0 : _12.toString()) || ''}
362
+ @input=${this._onInputChange}
363
+ suffix-text="명"
364
+ ></md-outlined-text-field>
365
+ </span>
366
+ </div>
367
+ </div>
368
+
369
+ <div detail-info>
370
+ <div>
371
+ <h3>테넌트 관리</h3>
372
+ <div row>
373
+ <span>관리번호</span>
374
+ <span>
375
+ ${this.project.tenantDomain
376
+ ? html `<a href=${`/project/${this.project.code}/`} target="_blank" title="테넌트로 이동"
377
+ >${this.project.code} <md-icon style="font-size:14px;vertical-align:middle">open_in_new</md-icon></a
378
+ >`
379
+ : this.project.code
380
+ ? html `${this.project.code}`
381
+ : html `<span style="color:#999">미발번 (승격 시 자동 부여)</span>`}
382
+ </span>
383
+ </div>
384
+ <div row>
385
+ <span>현재 상태</span>
386
+ <span>
387
+ ${this.project.tenantDomain
388
+ ? html `<b style="color:#42b382">활성 테넌트</b>`
389
+ : this.project.code
390
+ ? html `<b style="color:#aa6633">강등됨</b> (재승격 시 ${this.project.code} 재사용)`
391
+ : html `<b style="color:#999">미승격</b>`}
392
+ </span>
393
+ </div>
394
+ <div row>
395
+ <span></span>
396
+ <span tenant-actions>
397
+ ${this.project.tenantDomain
398
+ ? html `<md-elevated-button @click=${this._demoteTenant} ?disabled=${!this.project.id}>
399
+ <md-icon slot="icon">link_off</md-icon>테넌트 강등
400
+ </md-elevated-button>`
401
+ : html `<md-elevated-button green @click=${this._promoteTenant} ?disabled=${!this.project.id}>
402
+ <md-icon slot="icon">verified</md-icon>테넌트 승격
403
+ </md-elevated-button>`}
404
+ </span>
405
+ </div>
406
+ </div>
407
+
408
+ <div project>
409
+ <h3>프로젝트 현황</h3>
410
+ <div row separate-container>
411
+ <div>
412
+ <span>전체 진행현황</span>
413
+ <span>
414
+ <md-outlined-text-field
415
+ type="text"
416
+ numeric
417
+ project
418
+ name="totalProgress"
419
+ .value=${((_13 = this.project.totalProgress) === null || _13 === void 0 ? void 0 : _13.toString()) || ''}
420
+ @input=${this._onInputChange}
421
+ suffix-text="%"
422
+ ></md-outlined-text-field>
423
+ </span>
424
+ </div>
425
+ <div>
426
+ <span>검측/통과비율</span>
427
+ <span>
428
+ <md-outlined-text-field
429
+ type="text"
430
+ numeric
431
+ project
432
+ name="inspPassRate"
433
+ .value=${((_14 = this.project.inspPassRate) === null || _14 === void 0 ? void 0 : _14.toString()) || ''}
434
+ @input=${this._onInputChange}
435
+ suffix-text="%"
436
+ ></md-outlined-text-field>
437
+ </span>
438
+ </div>
439
+ </div>
440
+ <div row separate-container>
441
+ <div>
442
+ <span>주간 진행현황</span>
443
+ <span>
444
+ <md-outlined-text-field
445
+ type="text"
446
+ numeric
447
+ project
448
+ name="weeklyProgress"
449
+ .value=${((_15 = this.project.weeklyProgress) === null || _15 === void 0 ? void 0 : _15.toString()) || ''}
450
+ @input=${this._onInputChange}
451
+ suffix-text="%"
452
+ ></md-outlined-text-field>
453
+ </span>
454
+ </div>
455
+ <div>
456
+ <span>로봇작업진행율</span>
457
+ <span>
458
+ <md-outlined-text-field
459
+ type="text"
460
+ numeric
461
+ project
462
+ name="robotProgressRate"
463
+ .value=${((_16 = this.project.robotProgressRate) === null || _16 === void 0 ? void 0 : _16.toString()) || ''}
464
+ @input=${this._onInputChange}
465
+ suffix-text="%"
466
+ ></md-outlined-text-field>
467
+ </span>
468
+ </div>
469
+ </div>
470
+ <div row separate-container>
471
+ <div>
472
+ <span>KPI</span>
473
+ <span
474
+ ><md-outlined-text-field
475
+ type="text"
476
+ numeric
477
+ project
478
+ name="kpi"
479
+ .value=${((_17 = this.project.kpi) === null || _17 === void 0 ? void 0 : _17.toString()) || ''}
480
+ @input=${this._onInputChange}
481
+ suffix-text="%"
482
+ ></md-outlined-text-field>
483
+ </span>
484
+ </div>
485
+ <div>
486
+ <span>구조안전도</span>
487
+ <span
488
+ ><md-outlined-text-field
489
+ type="text"
490
+ numeric
491
+ project
492
+ name="structuralSafetyRate"
493
+ .value=${((_18 = this.project.structuralSafetyRate) === null || _18 === void 0 ? void 0 : _18.toString()) || ''}
494
+ @input=${this._onInputChange}
495
+ suffix-text="%"
496
+ ></md-outlined-text-field>
497
+ </span>
498
+ </div>
499
+ </div>
500
+
501
+ <div row separate-container>
502
+ <div>
503
+ <span>로봇 작업 대수</span>
504
+ <span
505
+ ><md-outlined-text-field
506
+ type="text"
507
+ numeric
508
+ project
509
+ name="robotCount"
510
+ .value=${((_19 = this.project.robotCount) === null || _19 === void 0 ? void 0 : _19.toString()) || ''}
511
+ @input=${this._onInputChange}
512
+ ></md-outlined-text-field>
513
+ </span>
514
+ </div>
515
+ </div>
516
+
517
+ <hr />
518
+
519
+ <div row separate-container>
520
+ <div>
521
+ <span>설계 변경 횟수</span>
522
+ <span
523
+ ><md-outlined-text-field
524
+ type="text"
525
+ numeric
526
+ building-complex
527
+ name="designChangeCount"
528
+ .value=${((_21 = (_20 = this.project.buildingComplex) === null || _20 === void 0 ? void 0 : _20.designChangeCount) === null || _21 === void 0 ? void 0 : _21.toString()) || ''}
529
+ @input=${this._onInputChange}
530
+ ></md-outlined-text-field>
531
+ </span>
532
+ </div>
533
+ <div>
534
+ <span>계획 공정률</span>
535
+ <span
536
+ ><md-outlined-text-field
537
+ type="text"
538
+ numeric
539
+ building-complex
540
+ name="plannedProgress"
541
+ .value=${((_23 = (_22 = this.project.buildingComplex) === null || _22 === void 0 ? void 0 : _22.plannedProgress) === null || _23 === void 0 ? void 0 : _23.toString()) || ''}
542
+ @input=${this._onInputChange}
543
+ suffix-text="%"
544
+ ></md-outlined-text-field>
545
+ </span>
546
+ </div>
547
+ </div>
548
+
549
+ <div row separate-container>
550
+ <div>
551
+ <span>실제 공정률</span>
552
+ <span
553
+ ><md-outlined-text-field
554
+ type="text"
555
+ numeric
556
+ building-complex
557
+ name="actualProgress"
558
+ .value=${((_25 = (_24 = this.project.buildingComplex) === null || _24 === void 0 ? void 0 : _24.actualProgress) === null || _25 === void 0 ? void 0 : _25.toString()) || ''}
559
+ @input=${this._onInputChange}
560
+ suffix-text="%"
561
+ ></md-outlined-text-field>
562
+ </span>
563
+ </div>
564
+ </div>
565
+ </div>
566
+
567
+ </div>
568
+ </div>
569
+ `;
570
+ }
571
+ async pageInitialized(lifecycle) { }
572
+ async pageUpdated(changes, lifecycle) {
573
+ if (!this.active)
574
+ return;
575
+ this.projectId = await this._resolveProjectId(lifecycle.resourceId || '');
576
+ await this.initProject(this.projectId);
577
+ }
578
+ /**
579
+ * resourceId 를 정상 Project.id (UUID) 로 변환한다.
580
+ * - UUID 형식이면 그대로 사용
581
+ * - 그 외 (code 또는 비어있음) 에는 현재 테넌트 컨텍스트의 프로젝트 조회
582
+ */
583
+ async _resolveProjectId(resourceId) {
584
+ var _a, _b;
585
+ if (resourceId && resourceId.length === 36)
586
+ return resourceId;
587
+ const response = await client.query({
588
+ query: gql `
589
+ query CurrentProject {
590
+ currentProject {
591
+ id
592
+ }
593
+ }
594
+ `
595
+ });
596
+ return ((_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.currentProject) === null || _b === void 0 ? void 0 : _b.id) || '';
597
+ }
598
+ async initProject(projectId = '') {
599
+ var _a, _b, _c, _d;
600
+ const response = await client.query({
601
+ query: gql `
602
+ query Project($id: String!, $filters: [Filter!]) {
603
+ project(id: $id) {
604
+ id
605
+ code
606
+ state
607
+ tenantDomain {
608
+ id
609
+ subdomain
610
+ name
611
+ }
612
+ name
613
+ documentNaming
614
+ startDate
615
+ endDate
616
+ mainPhoto {
617
+ fullpath
618
+ }
619
+ totalProgress
620
+ weeklyProgress
621
+ kpi
622
+ inspPassRate
623
+ robotProgressRate
624
+ structuralSafetyRate
625
+ robotCount
626
+ buildingComplex {
627
+ id
628
+ address
629
+ siteType
630
+ latitude
631
+ longitude
632
+ area
633
+ coverageRatio
634
+ floorAreaRatio
635
+ structureType
636
+ workerCount
637
+ designChangeCount
638
+ plannedProgress
639
+ actualProgress
640
+ clientCompany
641
+ constructionCompany
642
+ supervisoryCompany
643
+ designCompany
644
+ drawing {
645
+ id
646
+ name
647
+ }
648
+ constructionType
649
+ constructionCost
650
+ etc
651
+ notice
652
+ householdCount
653
+ buildingCount
654
+ overallConstructorEmails
655
+ taskConstructorEmails
656
+ overallSupervisoryEmails
657
+ taskSupervisoryEmails
658
+ virtualTourLink
659
+ buildings {
660
+ id
661
+ name
662
+ floorCount
663
+ hasBasement
664
+ basementFloorCount
665
+ }
666
+ }
667
+ }
668
+
669
+ employees(filters: $filters) {
670
+ items {
671
+ id
672
+ name
673
+ jobResponsibility
674
+ active
675
+ user {
676
+ id
677
+ name
678
+ email
679
+ }
680
+ }
681
+ }
682
+ }
683
+ `,
684
+ variables: {
685
+ id: projectId,
686
+ filters: [
687
+ {
688
+ name: 'active',
689
+ operator: 'eq',
690
+ value: true
691
+ },
692
+ {
693
+ name: 'userId',
694
+ operator: 'is_not_null',
695
+ value: ''
696
+ }
697
+ ]
698
+ },
699
+ context: { headers: tenantHeaders((_a = this.project) === null || _a === void 0 ? void 0 : _a.code) }
700
+ });
701
+ this.project = ((_b = response.data) === null || _b === void 0 ? void 0 : _b.project) || Object.assign({}, this.defaultProject);
702
+ const items = ((_d = (_c = response.data) === null || _c === void 0 ? void 0 : _c.employees) === null || _d === void 0 ? void 0 : _d.items) || [];
703
+ this.overallConstructorList = this._filterUserByPermission(items, 'OVERALL_CONSTRUCTOR');
704
+ this.taskConstructorList = this._filterUserByPermission(items, 'TASK_CONSTRUCTOR');
705
+ this.overallSupervisoryList = this._filterUserByPermission(items, 'OVERALL_SUPERVISORY');
706
+ this.taskSupervisoryList = this._filterUserByPermission(items, 'TASK_SUPERVISORY');
707
+ this.updateContext();
708
+ }
709
+ _filterUserByPermission(userList, permission) {
710
+ return userList
711
+ .filter(v => v.jobResponsibility == permission || v.jobResponsibility == 'ADMIN')
712
+ .map(v => ({ name: v.name, value: v.user.email }));
713
+ }
714
+ _stripTypename(obj) {
715
+ if (Array.isArray(obj)) {
716
+ return obj.map(item => this._stripTypename(item));
717
+ }
718
+ if (obj && typeof obj === 'object' && !(obj instanceof File)) {
719
+ const cleaned = {};
720
+ for (const [key, value] of Object.entries(obj)) {
721
+ if (key === '__typename')
722
+ continue;
723
+ cleaned[key] = this._stripTypename(value);
724
+ }
725
+ return cleaned;
726
+ }
727
+ return obj;
728
+ }
729
+ async _saveProject() {
730
+ // 첨부 파일 필드 제거 (첨부 파일은 {filename}Upload 로 전송)
731
+ delete this.project.mainPhoto;
732
+ delete this.project.buildingComplex.drawing;
733
+ // ProjectPatch 입력 타입에 없는 표시 전용 필드 제거 (테넌트 승격 UI 표시용)
734
+ const projectCode = this.project.code; // 도메인 헤더 용으로 미리 보존
735
+ delete this.project.code;
736
+ delete this.project.tenantDomain;
737
+ // state 는 raw 값('10'/'20')으로 로드되지만 ProjectPatch 는 enum 키 기대 — 일반
738
+ // save 에서는 state 변경 의도 없으므로 patch 에서 제외. (state 변경은 _onUnfinalize 별도)
739
+ delete this.project.state;
740
+ const response = await client.mutate({
741
+ mutation: gql `
742
+ mutation UpdateProject($project: ProjectPatch!) {
743
+ updateProject(project: $project) {
744
+ id
745
+ }
746
+ }
747
+ `,
748
+ variables: {
749
+ project: this._stripTypename(this.project)
750
+ },
751
+ context: {
752
+ hasUpload: true,
753
+ headers: tenantHeaders(projectCode)
754
+ }
755
+ });
756
+ if (!response.errors) {
757
+ notify({ message: '저장에 성공하였습니다.' });
758
+ }
759
+ }
760
+ /**
761
+ * 주소 옆 "정보 연동" 버튼 handler.
762
+ * - 현재 폼의 주소를 backend 로 보냄 → backend 가 EnvVar 갱신 + 세움터 시나리오 호출
763
+ * - 결과 (한글 raw + 숫자) 를 받아 BuildingComplex 폼 필드들에 매핑
764
+ * · siteType (한글) → SiteType enum 변환 (BC.siteType, enum 컬럼)
765
+ * · siteType (한글) → BC.constructionType 그대로 (자유 텍스트 컬럼)
766
+ * · area / floorAreaRatio / coverageRatio / householdCount / buildingCount /
767
+ * structureType → BC 동명 컬럼에 직접 대입
768
+ * · upperFloorCount / lowerFloorCount / bldNm / useAprDay / pmsDay → BC 컬럼
769
+ * 없음, 매핑 skip (참고용 콘솔 로그만)
770
+ */
771
+ async _collectBasicInfo() {
772
+ var _a, _b, _c, _d;
773
+ const address = (((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.buildingComplex) === null || _b === void 0 ? void 0 : _b.address) || '').trim();
774
+ if (!address) {
775
+ notify({ message: '먼저 프로젝트 주소를 입력해 주세요.' });
776
+ return;
777
+ }
778
+ this.collectingBasicInfo = true;
779
+ try {
780
+ const response = await client.mutate({
781
+ mutation: gql `
782
+ mutation CollectProjectBasicInfo($projectId: String!, $address: String) {
783
+ collectProjectBasicInfo(projectId: $projectId, address: $address) {
784
+ source
785
+ label
786
+ ok
787
+ message
788
+ data
789
+ }
790
+ }
791
+ `,
792
+ variables: { projectId: this.project.id, address },
793
+ context: { headers: tenantHeaders((_c = this.project) === null || _c === void 0 ? void 0 : _c.code) }
794
+ });
795
+ if (response.errors) {
796
+ throw new Error(response.errors.map((e) => e.message).join('\n'));
797
+ }
798
+ const result = (_d = response.data) === null || _d === void 0 ? void 0 : _d.collectProjectBasicInfo;
799
+ if (!(result === null || result === void 0 ? void 0 : result.ok)) {
800
+ notify({ message: (result === null || result === void 0 ? void 0 : result.message) || '업데이트할 정보가 없습니다.' });
801
+ return;
802
+ }
803
+ const data = result.data || {};
804
+ this._applyBasicInfoToForm(data);
805
+ this.requestUpdate();
806
+ notify({ message: '외부 시스템에서 기본 정보를 가져왔습니다. 검토 후 [저장]을 눌러주세요.' });
807
+ }
808
+ catch (err) {
809
+ console.warn('[정보 연동] 실패', err);
810
+ notify({ message: '외부 시스템 연동이 일시적으로 안 됩니다.' });
811
+ }
812
+ finally {
813
+ this.collectingBasicInfo = false;
814
+ }
815
+ }
816
+ /**
817
+ * 한글 주용도명 → SiteType enum.
818
+ * - NFC normalize + 공백 제거로 보이지 않는 문자/표기 차이 대응
819
+ * - 매핑 미존재시 null
820
+ */
821
+ _siteTypeFromKorean(korean) {
822
+ if (!korean)
823
+ return null;
824
+ const KEYS = {
825
+ 공동주택: 'APARTMENT_COMPLEX',
826
+ 단독주택: 'DETACHED_HOUSE',
827
+ 제1종근린생활시설: 'NEIGHBORHOOD_FACILITY',
828
+ 제2종근린생활시설: 'NEIGHBORHOOD_FACILITY',
829
+ 근린생활시설: 'NEIGHBORHOOD_FACILITY',
830
+ 업무시설: 'OFFICE',
831
+ 판매시설: 'COMMERCIAL',
832
+ 교육연구시설: 'EDUCATION',
833
+ 의료시설: 'MEDICAL',
834
+ 문화및집회시설: 'CULTURAL',
835
+ 종교시설: 'RELIGIOUS',
836
+ 공장: 'INDUSTRIAL',
837
+ 창고시설: 'INDUSTRIAL',
838
+ 운수시설: 'TRANSPORT'
839
+ };
840
+ const key = korean.normalize('NFC').replace(/\s+/g, '').trim();
841
+ return KEYS[key] || null;
842
+ }
843
+ /**
844
+ * 시나리오 result data 를 폼에 매핑 — BuildingComplex 와 Project 양쪽.
845
+ * 빈 값(null/undefined/'')은 기존 값 유지 — 자동 수집이 사용자 입력을 무리하게 덮지 않도록.
846
+ */
847
+ _applyBasicInfoToForm(data) {
848
+ const bc = Object.assign({}, this.project.buildingComplex);
849
+ const setBC = (key, value) => {
850
+ if (value === null || value === undefined || value === '')
851
+ return;
852
+ bc[key] = value;
853
+ };
854
+ setBC('area', this._toNum(data.area));
855
+ setBC('floorAreaRatio', this._toNum(data.floorAreaRatio));
856
+ setBC('coverageRatio', this._toNum(data.coverageRatio));
857
+ setBC('householdCount', this._toNum(data.householdCount));
858
+ setBC('buildingCount', this._toNum(data.buildingCount));
859
+ setBC('structureType', data.structureType);
860
+ // siteType: 한글 → SiteType enum 매핑. 매핑 안 되면 BC.siteType 빈 채로.
861
+ if (data.siteType) {
862
+ const enumVal = this._siteTypeFromKorean(data.siteType);
863
+ if (enumVal)
864
+ bc.siteType = enumVal;
865
+ }
866
+ // Project 엔티티 컬럼 — 착공일/준공일.
867
+ // 세움터 useAprDay (사용승인일) = 준공으로 매핑. stcnsDay = 착공.
868
+ const project = Object.assign(Object.assign({}, this.project), { buildingComplex: bc });
869
+ if (data.startDate)
870
+ project.startDate = data.startDate;
871
+ if (data.endDate)
872
+ project.endDate = data.endDate;
873
+ this.project = project;
874
+ // 참고 메타 — BC/Project 직접 컬럼 없음, 콘솔로만 (permitDate=건축허가일, bldNm 등)
875
+ console.log('[정보 연동] meta:', JSON.stringify({
876
+ upperFloorCount: data.upperFloorCount,
877
+ lowerFloorCount: data.lowerFloorCount,
878
+ bldNm: data.bldNm,
879
+ permitDate: data.permitDate
880
+ }));
881
+ }
882
+ _toNum(v) {
883
+ if (v === null || v === undefined || v === '')
884
+ return null;
885
+ const n = Number(v);
886
+ return Number.isFinite(n) ? n : null;
887
+ }
888
+ async _promoteTenant() {
889
+ if (!this.project.id)
890
+ return;
891
+ if (!confirm('이 프로젝트를 테넌트로 승격하시겠습니까?\n승격 시 관리번호(YYYY-NNNNN)가 자동 발번되며 변경할 수 없습니다.')) {
892
+ return;
893
+ }
894
+ const response = await client.mutate({
895
+ mutation: gql `
896
+ mutation PromoteProjectToTenant($projectId: String!) {
897
+ promoteProjectToTenant(projectId: $projectId) {
898
+ id
899
+ code
900
+ }
901
+ }
902
+ `,
903
+ variables: { projectId: this.project.id }
904
+ });
905
+ if (!response.errors) {
906
+ notify({ message: `테넌트로 승격되었습니다. 관리번호: ${response.data.promoteProjectToTenant.code}` });
907
+ await this.initProject(this.projectId);
908
+ }
909
+ }
910
+ async _demoteTenant() {
911
+ if (!this.project.id)
912
+ return;
913
+ if (!confirm('이 프로젝트의 테넌트를 강등하시겠습니까?\n관리번호는 보존되며 재승격 시 같은 번호가 재사용됩니다.')) {
914
+ return;
915
+ }
916
+ const response = await client.mutate({
917
+ mutation: gql `
918
+ mutation DemoteProjectTenant($projectId: String!) {
919
+ demoteProjectTenant(projectId: $projectId)
920
+ }
921
+ `,
922
+ variables: { projectId: this.project.id }
923
+ });
924
+ if (!response.errors) {
925
+ notify({ message: '테넌트가 강등되었습니다.' });
926
+ await this.initProject(this.projectId);
927
+ }
928
+ }
929
+ // 동 적용 버튼을 누르면 입력한 수 만큼 해당 단지에 동 데이터 생성
930
+ _setBuilding() {
931
+ var _a, _b, _c, _d, _e;
932
+ const buildingCount = ((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.buildingComplex) === null || _b === void 0 ? void 0 : _b.buildingCount) || 0;
933
+ const buildingInitData = { name: undefined, floorCount: undefined };
934
+ // 빌딩 데이터가 없으면 빈 배열 넣어줌
935
+ if (!((_e = (_d = (_c = this.project) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.buildings) === null || _e === void 0 ? void 0 : _e.length)) {
936
+ this.project.buildingComplex.buildings = [];
937
+ }
938
+ if (this.project.buildingComplex.buildings.length >= buildingCount) {
939
+ // 동 수가 더 작게 들어오면 기존 배열을 필요한 크기만큼 잘라내기
940
+ this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings.slice(0, buildingCount)];
941
+ }
942
+ else {
943
+ // 동수가 더 크게 들어오면 기존 배열 + 빈 값을 채움
944
+ const additionalCount = buildingCount - this.project.buildingComplex.buildings.length;
945
+ const additionalBuildings = Array.from({ length: additionalCount }, () => (Object.assign({}, buildingInitData)));
946
+ this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings, ...additionalBuildings];
947
+ }
948
+ // 리렌더링
949
+ this.project = Object.assign({}, this.project);
950
+ }
951
+ // Input 요소의 값이 변경될 때 호출되는 콜백 함수
952
+ _onInputChange(event, idx) {
953
+ const target = event.target;
954
+ let inputVal = target.value;
955
+ // 숫자 타입은 다른 문자 입력 제거
956
+ if (target.hasAttribute('numeric')) {
957
+ inputVal = Number(inputVal.replace(/[^\d.]/g, ''));
958
+ }
959
+ if (target.hasAttribute('project')) {
960
+ this.project[target.name] = inputVal;
961
+ // documentNaming 필드가 변경되면 실시간으로 미리보기 업데이트
962
+ if (target.name === 'documentNaming') {
963
+ this.requestUpdate();
964
+ }
965
+ }
966
+ else if (target.hasAttribute('building-complex')) {
967
+ this.project.buildingComplex[target.name] = inputVal;
968
+ }
969
+ else if (target.hasAttribute('building')) {
970
+ this.project.buildingComplex.buildings[idx][target.name] = inputVal;
971
+ }
972
+ }
973
+ // 이미지 업로드
974
+ async onCreateAttachment(e) {
975
+ const target = e.target;
976
+ const file = (target.name === 'mainPhoto' ? e.detail : e.detail[0]) || null;
977
+ if (target.name === 'mainPhoto') {
978
+ this.project.mainPhotoUpload = file;
979
+ }
980
+ else {
981
+ this.project.buildingComplex.drawingUpload = file;
982
+ }
983
+ }
984
+ _handleSelectionChange(e) {
985
+ const name = e.target.getAttribute('name');
986
+ const selectedValues = e.detail.selectedValues;
987
+ this.project.buildingComplex[name] = selectedValues;
988
+ }
989
+ _toggleBasement(idx) {
990
+ const building = this.project.buildingComplex.buildings[idx];
991
+ building.hasBasement = !building.hasBasement;
992
+ // 층 수가 0이거나 체크 해제시 지하층수 초기화 (플레이스 홀더 나오게 하기 위함)
993
+ if (building.basementFloorCount == 0 || !building.hasBasement) {
994
+ building.basementFloorCount = undefined;
995
+ }
996
+ this.project.buildingComplex.buildings[idx]['hasBasement'] = building.hasBasement;
997
+ this.requestUpdate();
998
+ }
999
+ };
1000
+ SvProjectUpdate.styles = [
1001
+ css `
1002
+ :host {
1003
+ display: grid;
1004
+ grid-template-rows: 55px auto;
1005
+ color: #4e5055;
1006
+
1007
+ width: 100%;
1008
+ background-color: var(--md-sys-color-background, #f6f6f6);
1009
+ overflow-y: auto;
1010
+
1011
+ --grid-record-emphasized-background-color: red;
1012
+ --grid-record-emphasized-color: yellow;
1013
+ }
1014
+
1015
+ md-outlined-text-field {
1016
+ width: 100%;
1017
+
1018
+ --md-outlined-text-field-container-shape: 5px;
1019
+ --md-outlined-text-field-outline-color: rgba(51, 51, 51, 0.2);
1020
+ --md-outlined-text-field-focus-outline-color: #1f7fd9;
1021
+ --md-outlined-text-field-focus-outline-width: 1px;
1022
+ --md-sys-color-primary: #586878;
1023
+ --md-outlined-text-field-input-text-size: 14px;
1024
+ --md-outlined-field-bottom-space: 3px;
1025
+ --md-outlined-field-top-space: 3px;
1026
+ --md-outlined-field-leading-space: var(--spacing-medium, 8px);
1027
+ --md-outlined-field-trailing-space: var(--spacing-medium, 8px);
1028
+ }
1029
+ select2-component {
1030
+ width: 100%;
1031
+ }
1032
+ md-filled-select {
1033
+ width: 100%;
1034
+ --md-filled-select-text-field-container-color: transparent;
1035
+ --md-filled-select-text-field-active-indicator-color: #999;
1036
+ --md-filled-select-text-field-input-text-size: 14px;
1037
+ --md-filled-select-text-field-input-text-line-height: 6px;
1038
+ }
1039
+ input[type='date'] {
1040
+ border: 1px solid rgba(51, 51, 51, 0.2);
1041
+ padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);
1042
+ border-radius: 5px;
1043
+ }
1044
+ md-outlined-text-field[type='textarea'] {
1045
+ width: 100%;
1046
+ height: 120px;
1047
+ resize: none;
1048
+ }
1049
+
1050
+ ox-input-image {
1051
+ width: 120px;
1052
+ height: 90px;
1053
+ }
1054
+ ox-input-file {
1055
+ width: 120px;
1056
+ height: 90px;
1057
+ padding: 0;
1058
+ }
1059
+
1060
+ div[body] {
1061
+ display: flex;
1062
+ margin: var(--spacing-large, 12px);
1063
+ margin-top: 0;
1064
+ gap: var(--spacing-medium, 8px);
1065
+
1066
+ & > div {
1067
+ display: flex;
1068
+ height: fit-content;
1069
+ flex-direction: column;
1070
+ padding: var(--spacing-large, 12px);
1071
+ background-color: var(--md-sys-color-on-primary);
1072
+ border: 1px solid #cccccc80;
1073
+ border-radius: 5px;
1074
+ gap: var(--spacing-medium, 8px);
1075
+
1076
+ h3 {
1077
+ color: #2e79be;
1078
+ font-size: 16px;
1079
+ margin: 0px;
1080
+ }
1081
+
1082
+ div[row] {
1083
+ display: flex;
1084
+ align-items: center;
1085
+
1086
+ span:first-child {
1087
+ flex: 0.3;
1088
+ text-align: right;
1089
+ font-size: 14px;
1090
+ }
1091
+
1092
+ span:last-child {
1093
+ flex: 0.7;
1094
+ display: flex;
1095
+ gap: var(--spacing-medium, 8px);
1096
+ margin-left: var(--spacing-medium, 8px);
1097
+ align-items: center;
1098
+
1099
+ &.address-row {
1100
+ md-outlined-text-field {
1101
+ flex: 1;
1102
+ }
1103
+ .info-link-btn {
1104
+ flex: 0 0 auto;
1105
+ --md-elevated-button-container-color: #2e79be;
1106
+ --md-elevated-button-label-text-color: #fff;
1107
+ --md-elevated-button-container-height: 36px;
1108
+ }
1109
+ }
1110
+
1111
+ &[align-end] {
1112
+ align-items: end;
1113
+ }
1114
+ }
1115
+ }
1116
+ }
1117
+
1118
+ div[project-info] {
1119
+ flex: 0.55;
1120
+ }
1121
+
1122
+ div[document-preview] {
1123
+ width: 100%;
1124
+ font-size: 12px;
1125
+ color: #2e79be;
1126
+ font-weight: 500;
1127
+ background-color: #f8f9fa;
1128
+ padding: 8px 12px;
1129
+ border-radius: 4px;
1130
+ border-left: 3px solid #2e79be;
1131
+ margin-top: 4px;
1132
+ }
1133
+
1134
+ div[detail-info] {
1135
+ flex: 0.45;
1136
+ padding: 0px;
1137
+ gap: 10px;
1138
+ background-color: transparent;
1139
+ border: none;
1140
+
1141
+ & > div {
1142
+ display: flex;
1143
+ flex-direction: column;
1144
+ gap: var(--spacing-medium, 8px);
1145
+ border: 1px solid #cccccc80;
1146
+ border-radius: 5px;
1147
+ padding: var(--spacing-large, 12px);
1148
+ background-color: var(--md-sys-color-on-primary);
1149
+
1150
+ md-outlined-text-field[type='text'] {
1151
+ width: 60%;
1152
+ }
1153
+
1154
+ md-elevated-button {
1155
+ --md-elevated-button-container-height: 30px;
1156
+ --md-elevated-button-container-color: var(--md-sys-color-on-primary);
1157
+ --md-elevated-button-label-text-size: 16px;
1158
+ }
1159
+ hr {
1160
+ border: 1px rgba(51, 51, 51, 0.1) dashed;
1161
+ width: 100%;
1162
+ margin-bottom: var(--spacing-tiny, 2px);
1163
+ }
1164
+ div[warn] {
1165
+ font-size: 12px;
1166
+ color: red;
1167
+ margin-left: var(--spacing-small, 4px);
1168
+ margin-bottom: var(--spacing-small, 4px);
1169
+ }
1170
+
1171
+ md-outlined-button {
1172
+ min-height: 30px;
1173
+ padding: 0 var(--spacing-large, 12px);
1174
+ box-shadow: 1px 1px 1px #0000001a;
1175
+ --md-outlined-button-label-text-color: #586878;
1176
+ --md-outlined-button-label-text-weight: bold;
1177
+ --md-sys-color-outline: rgba(51, 51, 51, 0.2);
1178
+ }
1179
+
1180
+ div[row] {
1181
+ span:first-child {
1182
+ flex: 0.2;
1183
+ }
1184
+ span:last-child {
1185
+ flex: 0.8;
1186
+ }
1187
+ }
1188
+
1189
+ div[separate-container] {
1190
+ display: grid;
1191
+ grid-template-columns: repeat(2, 1fr);
1192
+ gap: 8px 30px;
1193
+ margin-left: 15px;
1194
+
1195
+ md-outlined-text-field {
1196
+ width: 80px;
1197
+ }
1198
+
1199
+ & > div {
1200
+ display: flex;
1201
+ gap: 15px;
1202
+
1203
+ span[floor-row] {
1204
+ display: inline-flex;
1205
+ align-items: center;
1206
+ margin-left: 5px;
1207
+ }
1208
+
1209
+ span[floor-title] {
1210
+ min-width: 33px;
1211
+ margin-right: var(--spacing-small, 4px);
1212
+ }
1213
+ span:first-child {
1214
+ flex: 0.4;
1215
+ justify-content: flex-start;
1216
+ display: flex;
1217
+ }
1218
+ span:last-child {
1219
+ flex: 0.6;
1220
+ display: flex;
1221
+ align-items: center;
1222
+ padding-left: var(--spacing-medium, 8px);
1223
+ }
1224
+ }
1225
+
1226
+ div[basement-container] {
1227
+ display: flex;
1228
+ align-items: center;
1229
+ gap: 4px;
1230
+
1231
+ div[basement-checkbox] {
1232
+ display: flex;
1233
+ align-items: center;
1234
+ cursor: pointer;
1235
+
1236
+ md-icon {
1237
+ --md-icon-size: 25px;
1238
+ color: #808080;
1239
+ transition: opacity 0.2s ease;
1240
+ }
1241
+
1242
+ &[disabled] {
1243
+ cursor: not-allowed;
1244
+ opacity: 0.4;
1245
+
1246
+ md-icon {
1247
+ color: #cccccc;
1248
+ }
1249
+ }
1250
+
1251
+ &[checked] md-icon {
1252
+ background-color: #2e79be;
1253
+ color: white;
1254
+ border-radius: 3px;
1255
+ }
1256
+ }
1257
+
1258
+ md-outlined-text-field[basement-floor] {
1259
+ width: 70px;
1260
+ margin-left: var(--spacing-small, 4px);
1261
+ opacity: 1;
1262
+ transition: opacity 0.2s ease;
1263
+
1264
+ &[disabled] {
1265
+ opacity: 0.4;
1266
+ pointer-events: none;
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+
1272
+ &[project] {
1273
+ div[separate-container] {
1274
+ margin-left: 15px;
1275
+
1276
+ & > div {
1277
+ align-items: center;
1278
+
1279
+ span:first-child {
1280
+ flex: 0.4;
1281
+ min-width: 100px;
1282
+ }
1283
+ span:last-child {
1284
+ flex: 0.4;
1285
+ margin-left: 0;
1286
+ }
1287
+ }
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ }
1293
+ `
1294
+ ];
1295
+ __decorate([
1296
+ state(),
1297
+ __metadata("design:type", String)
1298
+ ], SvProjectUpdate.prototype, "projectId", void 0);
1299
+ __decorate([
1300
+ state(),
1301
+ __metadata("design:type", Object)
1302
+ ], SvProjectUpdate.prototype, "project", void 0);
1303
+ __decorate([
1304
+ state(),
1305
+ __metadata("design:type", Array)
1306
+ ], SvProjectUpdate.prototype, "selectedValues", void 0);
1307
+ __decorate([
1308
+ state(),
1309
+ __metadata("design:type", Array)
1310
+ ], SvProjectUpdate.prototype, "overallConstructorList", void 0);
1311
+ __decorate([
1312
+ state(),
1313
+ __metadata("design:type", Array)
1314
+ ], SvProjectUpdate.prototype, "taskConstructorList", void 0);
1315
+ __decorate([
1316
+ state(),
1317
+ __metadata("design:type", Array)
1318
+ ], SvProjectUpdate.prototype, "taskSupervisoryList", void 0);
1319
+ __decorate([
1320
+ state(),
1321
+ __metadata("design:type", Array)
1322
+ ], SvProjectUpdate.prototype, "overallSupervisoryList", void 0);
1323
+ __decorate([
1324
+ state(),
1325
+ __metadata("design:type", Boolean)
1326
+ ], SvProjectUpdate.prototype, "collectingBasicInfo", void 0);
1327
+ SvProjectUpdate = __decorate([
1328
+ customElement('sv-project-update')
1329
+ ], SvProjectUpdate);
1330
+ export { SvProjectUpdate };
1331
+ //# sourceMappingURL=sv-project-update.js.map