@dssp/project 0.0.2

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 (195) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/assets/images/hatiolab-logo.png +0 -0
  3. package/assets/images/o-mark.png +0 -0
  4. package/assets/images/x-mark.png +0 -0
  5. package/client/bootstrap.ts +0 -0
  6. package/client/index.ts +0 -0
  7. package/client/pages/checklist/checklist-importer.ts +96 -0
  8. package/client/pages/checklist/checklist-list-page.ts +355 -0
  9. package/client/pages/lib/waether.ts +159 -0
  10. package/client/pages/project/ox-progress-circle.ts +133 -0
  11. package/client/pages/project/project-create-popup.ts +148 -0
  12. package/client/pages/project/project-detail.ts +618 -0
  13. package/client/pages/project/project-list.ts +354 -0
  14. package/client/pages/project/project-plan-management.ts +437 -0
  15. package/client/pages/project/project-schedule-list.ts +280 -0
  16. package/client/pages/project/project-schedule.ts +248 -0
  17. package/client/pages/project/project-setting-list.ts +298 -0
  18. package/client/pages/project/project-update.ts +797 -0
  19. package/client/pages/resource/resource-importer.ts +96 -0
  20. package/client/pages/resource/resource-list-page.ts +355 -0
  21. package/client/pages/task/task-importer.ts +96 -0
  22. package/client/pages/task/task-list-page.ts +355 -0
  23. package/client/route.ts +39 -0
  24. package/client/tsconfig.json +11 -0
  25. package/dist-client/bootstrap.d.ts +0 -0
  26. package/dist-client/bootstrap.js +2 -0
  27. package/dist-client/bootstrap.js.map +1 -0
  28. package/dist-client/index.d.ts +0 -0
  29. package/dist-client/index.js +2 -0
  30. package/dist-client/index.js.map +1 -0
  31. package/dist-client/pages/checklist/checklist-importer.d.ts +9 -0
  32. package/dist-client/pages/checklist/checklist-importer.js +100 -0
  33. package/dist-client/pages/checklist/checklist-importer.js.map +1 -0
  34. package/dist-client/pages/checklist/checklist-list-page.d.ts +62 -0
  35. package/dist-client/pages/checklist/checklist-list-page.js +331 -0
  36. package/dist-client/pages/checklist/checklist-list-page.js.map +1 -0
  37. package/dist-client/pages/lib/waether.d.ts +6 -0
  38. package/dist-client/pages/lib/waether.js +152 -0
  39. package/dist-client/pages/lib/waether.js.map +1 -0
  40. package/dist-client/pages/project/ox-progress-circle.d.ts +41 -0
  41. package/dist-client/pages/project/ox-progress-circle.js +182 -0
  42. package/dist-client/pages/project/ox-progress-circle.js.map +1 -0
  43. package/dist-client/pages/project/project-create-popup.d.ts +14 -0
  44. package/dist-client/pages/project/project-create-popup.js +153 -0
  45. package/dist-client/pages/project/project-create-popup.js.map +1 -0
  46. package/dist-client/pages/project/project-detail.d.ts +35 -0
  47. package/dist-client/pages/project/project-detail.js +617 -0
  48. package/dist-client/pages/project/project-detail.js.map +1 -0
  49. package/dist-client/pages/project/project-list.d.ts +88 -0
  50. package/dist-client/pages/project/project-list.js +303 -0
  51. package/dist-client/pages/project/project-list.js.map +1 -0
  52. package/dist-client/pages/project/project-plan-management.d.ts +27 -0
  53. package/dist-client/pages/project/project-plan-management.js +438 -0
  54. package/dist-client/pages/project/project-plan-management.js.map +1 -0
  55. package/dist-client/pages/project/project-schedule-list.d.ts +18 -0
  56. package/dist-client/pages/project/project-schedule-list.js +292 -0
  57. package/dist-client/pages/project/project-schedule-list.js.map +1 -0
  58. package/dist-client/pages/project/project-schedule.d.ts +23 -0
  59. package/dist-client/pages/project/project-schedule.js +256 -0
  60. package/dist-client/pages/project/project-schedule.js.map +1 -0
  61. package/dist-client/pages/project/project-setting-list.d.ts +23 -0
  62. package/dist-client/pages/project/project-setting-list.js +307 -0
  63. package/dist-client/pages/project/project-setting-list.js.map +1 -0
  64. package/dist-client/pages/project/project-update.d.ts +24 -0
  65. package/dist-client/pages/project/project-update.js +797 -0
  66. package/dist-client/pages/project/project-update.js.map +1 -0
  67. package/dist-client/pages/resource/resource-importer.d.ts +9 -0
  68. package/dist-client/pages/resource/resource-importer.js +100 -0
  69. package/dist-client/pages/resource/resource-importer.js.map +1 -0
  70. package/dist-client/pages/resource/resource-list-page.d.ts +62 -0
  71. package/dist-client/pages/resource/resource-list-page.js +331 -0
  72. package/dist-client/pages/resource/resource-list-page.js.map +1 -0
  73. package/dist-client/pages/task/task-importer.d.ts +9 -0
  74. package/dist-client/pages/task/task-importer.js +100 -0
  75. package/dist-client/pages/task/task-importer.js.map +1 -0
  76. package/dist-client/pages/task/task-list-page.d.ts +62 -0
  77. package/dist-client/pages/task/task-list-page.js +331 -0
  78. package/dist-client/pages/task/task-list-page.js.map +1 -0
  79. package/dist-client/route.d.ts +1 -0
  80. package/dist-client/route.js +32 -0
  81. package/dist-client/route.js.map +1 -0
  82. package/dist-client/tsconfig.tsbuildinfo +1 -0
  83. package/dist-server/controllers/index.js +1 -0
  84. package/dist-server/controllers/index.js.map +1 -0
  85. package/dist-server/controllers/project-to-excel.js +30 -0
  86. package/dist-server/controllers/project-to-excel.js.map +1 -0
  87. package/dist-server/index.js +6 -0
  88. package/dist-server/index.js.map +1 -0
  89. package/dist-server/middlewares/index.js +8 -0
  90. package/dist-server/middlewares/index.js.map +1 -0
  91. package/dist-server/routes.js +105 -0
  92. package/dist-server/routes.js.map +1 -0
  93. package/dist-server/service/check-item/check-item-mutation.js +129 -0
  94. package/dist-server/service/check-item/check-item-mutation.js.map +1 -0
  95. package/dist-server/service/check-item/check-item-query.js +86 -0
  96. package/dist-server/service/check-item/check-item-query.js.map +1 -0
  97. package/dist-server/service/check-item/check-item-type.js +69 -0
  98. package/dist-server/service/check-item/check-item-type.js.map +1 -0
  99. package/dist-server/service/check-item/check-item.js +84 -0
  100. package/dist-server/service/check-item/check-item.js.map +1 -0
  101. package/dist-server/service/check-item/index.js +9 -0
  102. package/dist-server/service/check-item/index.js.map +1 -0
  103. package/dist-server/service/checklist/checklist-mutation.js +129 -0
  104. package/dist-server/service/checklist/checklist-mutation.js.map +1 -0
  105. package/dist-server/service/checklist/checklist-query.js +86 -0
  106. package/dist-server/service/checklist/checklist-query.js.map +1 -0
  107. package/dist-server/service/checklist/checklist-type.js +69 -0
  108. package/dist-server/service/checklist/checklist-type.js.map +1 -0
  109. package/dist-server/service/checklist/checklist.js +120 -0
  110. package/dist-server/service/checklist/checklist.js.map +1 -0
  111. package/dist-server/service/checklist/index.js +9 -0
  112. package/dist-server/service/checklist/index.js.map +1 -0
  113. package/dist-server/service/index.js +36 -0
  114. package/dist-server/service/index.js.map +1 -0
  115. package/dist-server/service/project/index.js +11 -0
  116. package/dist-server/service/project/index.js.map +1 -0
  117. package/dist-server/service/project/project-mutation.js +190 -0
  118. package/dist-server/service/project/project-mutation.js.map +1 -0
  119. package/dist-server/service/project/project-query.js +143 -0
  120. package/dist-server/service/project/project-query.js.map +1 -0
  121. package/dist-server/service/project/project-type.js +106 -0
  122. package/dist-server/service/project/project-type.js.map +1 -0
  123. package/dist-server/service/project/project.js +146 -0
  124. package/dist-server/service/project/project.js.map +1 -0
  125. package/dist-server/service/resource/index.js +9 -0
  126. package/dist-server/service/resource/index.js.map +1 -0
  127. package/dist-server/service/resource/resource-mutation.js +129 -0
  128. package/dist-server/service/resource/resource-mutation.js.map +1 -0
  129. package/dist-server/service/resource/resource-query.js +86 -0
  130. package/dist-server/service/resource/resource-query.js.map +1 -0
  131. package/dist-server/service/resource/resource-type.js +69 -0
  132. package/dist-server/service/resource/resource-type.js.map +1 -0
  133. package/dist-server/service/resource/resource.js +62 -0
  134. package/dist-server/service/resource/resource.js.map +1 -0
  135. package/dist-server/service/task/index.js +9 -0
  136. package/dist-server/service/task/index.js.map +1 -0
  137. package/dist-server/service/task/task-mutation.js +129 -0
  138. package/dist-server/service/task/task-mutation.js.map +1 -0
  139. package/dist-server/service/task/task-query.js +86 -0
  140. package/dist-server/service/task/task-query.js.map +1 -0
  141. package/dist-server/service/task/task-type.js +69 -0
  142. package/dist-server/service/task/task-type.js.map +1 -0
  143. package/dist-server/service/task/task.js +106 -0
  144. package/dist-server/service/task/task.js.map +1 -0
  145. package/dist-server/tsconfig.tsbuildinfo +1 -0
  146. package/helps/management/alarm.md +160 -0
  147. package/helps/management/alter-video.md +160 -0
  148. package/helps/management/cctv.md +160 -0
  149. package/helps/management/device.md +160 -0
  150. package/helps/management/parking.md +160 -0
  151. package/helps/management/site.md +160 -0
  152. package/helps/management/sun-pnl.md +160 -0
  153. package/helps/project/checklist.md +160 -0
  154. package/helps/project/project.md +160 -0
  155. package/helps/project/resource.md +160 -0
  156. package/helps/project/task.md +160 -0
  157. package/package.json +38 -0
  158. package/server/controllers/index.ts +0 -0
  159. package/server/controllers/project-to-excel.ts +40 -0
  160. package/server/index.ts +3 -0
  161. package/server/middlewares/index.ts +3 -0
  162. package/server/routes.ts +108 -0
  163. package/server/service/check-item/check-item-mutation.ts +142 -0
  164. package/server/service/check-item/check-item-query.ts +56 -0
  165. package/server/service/check-item/check-item-type.ts +49 -0
  166. package/server/service/check-item/check-item.ts +74 -0
  167. package/server/service/check-item/index.ts +6 -0
  168. package/server/service/checklist/checklist-mutation.ts +142 -0
  169. package/server/service/checklist/checklist-query.ts +56 -0
  170. package/server/service/checklist/checklist-type.ts +49 -0
  171. package/server/service/checklist/checklist.ts +105 -0
  172. package/server/service/checklist/index.ts +6 -0
  173. package/server/service/index.ts +35 -0
  174. package/server/service/project/index.ts +8 -0
  175. package/server/service/project/project-mutation.ts +201 -0
  176. package/server/service/project/project-query.ts +103 -0
  177. package/server/service/project/project-type.ts +71 -0
  178. package/server/service/project/project.ts +131 -0
  179. package/server/service/resource/index.ts +6 -0
  180. package/server/service/resource/resource-mutation.ts +139 -0
  181. package/server/service/resource/resource-query.ts +56 -0
  182. package/server/service/resource/resource-type.ts +49 -0
  183. package/server/service/resource/resource.ts +56 -0
  184. package/server/service/task/index.ts +6 -0
  185. package/server/service/task/task-mutation.ts +136 -0
  186. package/server/service/task/task-query.ts +56 -0
  187. package/server/service/task/task-type.ts +49 -0
  188. package/server/service/task/task.ts +97 -0
  189. package/server/tsconfig.json +10 -0
  190. package/things-factory.config.js +20 -0
  191. package/translations/en.json +1 -0
  192. package/translations/ja.json +1 -0
  193. package/translations/ko.json +9 -0
  194. package/translations/ms.json +1 -0
  195. package/translations/zh.json +1 -0
@@ -0,0 +1,797 @@
1
+ import { PageView } from '@operato/shell'
2
+ import { PageLifecycle } from '@operato/shell/dist/src/app/pages/page-view'
3
+ import { css, html } from 'lit'
4
+ import { customElement, state } from 'lit/decorators.js'
5
+ import { ScopedElementsMixin } from '@open-wc/scoped-elements'
6
+ import { client } from '@operato/graphql'
7
+ import { notify } from '@operato/layout'
8
+
9
+ import gql from 'graphql-tag'
10
+ import { Project } from './project-list'
11
+ import '@material/web/button/elevated-button.js'
12
+ import '@material/web/textfield/outlined-text-field.js'
13
+
14
+ @customElement('project-update')
15
+ export class ProjectUpdate extends ScopedElementsMixin(PageView) {
16
+ static styles = [
17
+ css`
18
+ :host {
19
+ display: grid;
20
+ grid-template-rows: 75px auto;
21
+ color: #4e5055;
22
+
23
+ width: 100%;
24
+ background-color: #f7f7f7;
25
+ overflow-y: auto;
26
+
27
+ --grid-record-emphasized-background-color: red;
28
+ --grid-record-emphasized-color: yellow;
29
+ }
30
+
31
+ md-outlined-text-field {
32
+ width: 100%;
33
+
34
+ --md-outlined-text-field-container-shape: 5px;
35
+ --md-sys-color-primary: #586878;
36
+ --md-outlined-text-field-input-text-size: 14px;
37
+ --md-outlined-field-bottom-space: 4px;
38
+ --md-outlined-field-top-space: 4px;
39
+ }
40
+ md-outlined-text-field[type='textarea'] {
41
+ width: 100%;
42
+ height: 130px;
43
+ }
44
+
45
+ ox-input-image {
46
+ width: 100px;
47
+ height: 100px;
48
+ }
49
+ ox-input-file {
50
+ width: 100px;
51
+ height: 100px;
52
+ padding: 0;
53
+ }
54
+
55
+ div[header] {
56
+ display: flex;
57
+ margin: 0px 20px;
58
+
59
+ h2 {
60
+ flex: 0.5;
61
+ color: #3f71a0;
62
+ }
63
+
64
+ div[button-container] {
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: end;
68
+ flex: 0.5;
69
+
70
+ md-elevated-button {
71
+ margin: 0px 3px;
72
+
73
+ --md-elevated-button-container-height: 35px;
74
+ --md-elevated-button-label-text-size: 16px;
75
+ --md-elevated-button-container-color: #0595e5;
76
+
77
+ --md-elevated-button-label-text-color: #fff;
78
+ --md-elevated-button-hover-label-text-color: #fff;
79
+ --md-elevated-button-pressed-label-text-color: #fff;
80
+ --md-elevated-button-focus-label-text-color: #fff;
81
+ --md-elevated-button-icon-color: #fff;
82
+ --md-elevated-button-hover-icon-color: #fff;
83
+ --md-elevated-button-pressed-icon-color: #fff;
84
+ --md-elevated-button-focus-icon-color: #fff;
85
+
86
+ &[green] {
87
+ --md-elevated-button-container-color: #42b382;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ div[body] {
94
+ display: flex;
95
+ margin: 0px 25px 25px 25px;
96
+ gap: 10px;
97
+
98
+ & > div {
99
+ display: flex;
100
+ height: fit-content;
101
+ flex-direction: column;
102
+ padding: 15px;
103
+ background-color: #ffffff;
104
+ border: 1px solid #cccccc80;
105
+ border-radius: 5px;
106
+ gap: 10px;
107
+
108
+ h3 {
109
+ color: #2e79be;
110
+ font-size: 18px;
111
+ margin: 0px;
112
+ }
113
+
114
+ div[row] {
115
+ display: flex;
116
+ align-items: center;
117
+
118
+ span:first-child {
119
+ flex: 0.3;
120
+ text-align: right;
121
+ }
122
+
123
+ span:last-child {
124
+ flex: 0.7;
125
+ display: flex;
126
+ gap: 10px;
127
+ margin-left: 12px;
128
+ align-items: center;
129
+
130
+ &[align-end] {
131
+ align-items: end;
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ div[project-info] {
138
+ flex: 0.55;
139
+ }
140
+
141
+ div[detail-info] {
142
+ flex: 0.45;
143
+ padding: 0px;
144
+ gap: 10px;
145
+ background-color: transparent;
146
+ border: none;
147
+
148
+ & > div {
149
+ display: flex;
150
+ flex-direction: column;
151
+ gap: 10px;
152
+ border: 1px solid #cccccc80;
153
+ border-radius: 5px;
154
+ padding: 15px;
155
+ background-color: #fff;
156
+
157
+ md-outlined-text-field[type='text'] {
158
+ width: 60%;
159
+ }
160
+
161
+ md-elevated-button {
162
+ --md-elevated-button-container-height: 30px;
163
+ --md-elevated-button-container-color: #fff;
164
+ --md-elevated-button-label-text-size: 16px;
165
+ }
166
+ hr {
167
+ border: 1px #cccccc dashed;
168
+ width: 100%;
169
+ margin-bottom: 2px;
170
+ }
171
+ div[warn] {
172
+ font-size: 12px;
173
+ color: red;
174
+ margin-left: 5px;
175
+ margin-bottom: 5px;
176
+ }
177
+
178
+ div[row] {
179
+ span:first-child {
180
+ flex: 0.2;
181
+ }
182
+ span:last-child {
183
+ flex: 0.8;
184
+ }
185
+ }
186
+
187
+ div[separate-container] {
188
+ display: grid;
189
+ grid-template-columns: repeat(2, 1fr);
190
+ gap: 10px;
191
+
192
+ md-outlined-text-field {
193
+ width: 70px;
194
+ }
195
+
196
+ & > div {
197
+ display: flex;
198
+
199
+ span[floor-title] {
200
+ min-width: 33px;
201
+ margin-right: 5px;
202
+ }
203
+ span:first-child {
204
+ flex: 0.4;
205
+ justify-content: end;
206
+ display: flex;
207
+ }
208
+ span:last-child {
209
+ flex: 0.6;
210
+ display: flex;
211
+ align-items: center;
212
+ padding-left: 17px;
213
+ }
214
+ }
215
+ }
216
+
217
+ &[project] {
218
+ div[separate-container] {
219
+ & > div {
220
+ span:first-child {
221
+ flex: 0.6;
222
+ min-width: 100px;
223
+ }
224
+ span:last-child {
225
+ flex: 0.4;
226
+ margin-left: 0;
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ `
235
+ ]
236
+
237
+ get context() {
238
+ return {
239
+ title: '프로젝트 정보 관리'
240
+ }
241
+ }
242
+
243
+ private defaultProject = {
244
+ name: '',
245
+ buildingComplex: {
246
+ address: '',
247
+ area: 0,
248
+ constructionCompany: '',
249
+ clientCompany: '',
250
+ supervisoryCompany: '',
251
+ designCompany: '',
252
+ constructionType: '',
253
+ buildings: []
254
+ }
255
+ }
256
+ @state() projectId: string = ''
257
+ @state() project: Project = { ...this.defaultProject }
258
+
259
+ render() {
260
+ return html`
261
+ <div header>
262
+ <h2>프로젝트 정보 관리</h2>
263
+ <div button-container>
264
+ <md-elevated-button green @click=${this._saveProject}>
265
+ <md-icon slot="icon">save</md-icon>정보 저장
266
+ </md-elevated-button>
267
+ <md-elevated-button href=${`project-plan-management/${this.project.id}`}>
268
+ <md-icon slot="icon">description</md-icon>도면 관리
269
+ </md-elevated-button>
270
+ <md-elevated-button href=${`project-task-update/${this.project.id}`}>
271
+ <md-icon slot="icon">event_note</md-icon>공정표 관리
272
+ </md-elevated-button>
273
+ </div>
274
+ </div>
275
+ <div body>
276
+ <div project-info>
277
+ <h3>기본 정보</h3>
278
+ <div row>
279
+ <span>프로젝트명</span>
280
+ <span
281
+ ><md-outlined-text-field
282
+ type="text"
283
+ name="name"
284
+ project
285
+ .value=${this.project.name || ''}
286
+ @input=${this._onInputChange}
287
+ ></md-outlined-text-field>
288
+ </span>
289
+ </div>
290
+ <div row>
291
+ <span>프로젝트 주소</span>
292
+ <span>
293
+ <md-outlined-text-field
294
+ type="text"
295
+ name="address"
296
+ building-complex
297
+ .value=${this.project?.buildingComplex?.address || ''}
298
+ @input=${this._onInputChange}
299
+ ></md-outlined-text-field>
300
+ </span>
301
+ </div>
302
+ <div row>
303
+ <span>위도</span>
304
+ <span>
305
+ <md-outlined-text-field
306
+ type="text"
307
+ name="latitude"
308
+ numeric
309
+ building-complex
310
+ .value=${this.project?.buildingComplex?.latitude?.toString() || ''}
311
+ @input=${this._onInputChange}
312
+ ></md-outlined-text-field>
313
+ </span>
314
+ </div>
315
+ <div row>
316
+ <span>경도</span>
317
+ <span>
318
+ <md-outlined-text-field
319
+ type="text"
320
+ name="longitude"
321
+ numeric
322
+ building-complex
323
+ .value=${this.project?.buildingComplex?.longitude?.toString() || ''}
324
+ @input=${this._onInputChange}
325
+ ></md-outlined-text-field>
326
+ </span>
327
+ </div>
328
+ <div row>
329
+ <span>면적</span>
330
+ <span align-end
331
+ ><md-outlined-text-field
332
+ type="text"
333
+ name="area"
334
+ numeric
335
+ building-complex
336
+ .value=${this.project?.buildingComplex?.area?.toString() || ''}
337
+ @input=${this._onInputChange}
338
+ ></md-outlined-text-field>
339
+ ㎡</span
340
+ >
341
+ </div>
342
+ <div row>
343
+ <span>착공일정 ~ 준공일정</span>
344
+ <span
345
+ ><input
346
+ type="date"
347
+ name="startDate"
348
+ project
349
+ .value=${this.project.startDate || ''}
350
+ @input=${this._onInputChange}
351
+ max="9999-12-31"
352
+ />
353
+ ~
354
+ <input
355
+ type="date"
356
+ name="endDate"
357
+ project
358
+ .value=${this.project.endDate || ''}
359
+ @input=${this._onInputChange}
360
+ max="9999-12-31"
361
+ />
362
+ </span>
363
+ </div>
364
+ <div row>
365
+ <span>발주처</span>
366
+ <span
367
+ ><md-outlined-text-field
368
+ type="text"
369
+ name="clientCompany"
370
+ building-complex
371
+ .value=${this.project?.buildingComplex?.clientCompany || ''}
372
+ @input=${this._onInputChange}
373
+ ></md-outlined-text-field>
374
+ </span>
375
+ </div>
376
+ <div row>
377
+ <span>건설사</span>
378
+ <span
379
+ ><md-outlined-text-field
380
+ type="text"
381
+ name="constructionCompany"
382
+ building-complex
383
+ .value=${this.project?.buildingComplex?.constructionCompany || ''}
384
+ @input=${this._onInputChange}
385
+ ></md-outlined-text-field>
386
+ </span>
387
+ </div>
388
+ <div row>
389
+ <span>설계사</span>
390
+ <span
391
+ ><md-outlined-text-field
392
+ type="text"
393
+ name="designCompany"
394
+ building-complex
395
+ .value=${this.project?.buildingComplex?.designCompany || ''}
396
+ @input=${this._onInputChange}
397
+ ></md-outlined-text-field>
398
+ </span>
399
+ </div>
400
+ <div row>
401
+ <span>감리사</span>
402
+ <span
403
+ ><md-outlined-text-field
404
+ type="text"
405
+ name="supervisoryCompany"
406
+ building-complex
407
+ .value=${this.project?.buildingComplex?.supervisoryCompany || ''}
408
+ @input=${this._onInputChange}
409
+ ></md-outlined-text-field>
410
+ </span>
411
+ </div>
412
+ <div row>
413
+ <span>건설구분</span>
414
+ <span
415
+ ><md-outlined-text-field
416
+ type="text"
417
+ name="constructionType"
418
+ building-complex
419
+ .value=${this.project?.buildingComplex?.constructionType || ''}
420
+ @input=${this._onInputChange}
421
+ ></md-outlined-text-field>
422
+ </span>
423
+ </div>
424
+ <div row>
425
+ <span>대표사진 업로드</span>
426
+ <span>
427
+ <ox-input-image
428
+ name="mainPhoto"
429
+ value=${this.project?.mainPhoto?.fullpath || ''}
430
+ @change=${this.onCreateAttachment.bind(this)}
431
+ ></ox-input-image>
432
+ </span>
433
+ </div>
434
+ <div row>
435
+ <span>단지 BIM</span>
436
+ <span>
437
+ <ox-input-file
438
+ name="drawing"
439
+ label=" "
440
+ description="IFC 업로드"
441
+ .value=${this.project?.buildingComplex?.drawing || ''}
442
+ @change=${this.onCreateAttachment.bind(this)}
443
+ ></ox-input-file>
444
+ </span>
445
+ </div>
446
+ <div row>
447
+ <span>공사금액</span>
448
+ <span
449
+ ><md-outlined-text-field
450
+ type="text"
451
+ name="constructionCost"
452
+ numeric
453
+ building-complex
454
+ .value=${this.project?.buildingComplex?.constructionCost?.toString() || ''}
455
+ @input=${this._onInputChange}
456
+ ></md-outlined-text-field>
457
+ </span>
458
+ </div>
459
+ <div row>
460
+ <span>기타사항</span>
461
+ <span>
462
+ <md-outlined-text-field
463
+ type="textarea"
464
+ name="etc"
465
+ building-complex
466
+ .value=${this.project?.buildingComplex?.etc || ''}
467
+ @input=${this._onInputChange}
468
+ ></md-outlined-text-field>
469
+ </span>
470
+ </div>
471
+ </div>
472
+ <div detail-info>
473
+ <div>
474
+ <h3>건설구분 상세 정보</h3>
475
+ <div row>
476
+ <span>세대수</span>
477
+ <span
478
+ ><md-outlined-text-field
479
+ type="text"
480
+ numeric
481
+ building-complex
482
+ name="householdCount"
483
+ .value=${this.project?.buildingComplex?.householdCount?.toString() || ''}
484
+ @input=${this._onInputChange}
485
+ ></md-outlined-text-field>
486
+ </span>
487
+ </div>
488
+ <div row>
489
+ <span>동수</span>
490
+ <span
491
+ ><md-outlined-text-field
492
+ type="text"
493
+ numeric
494
+ building-complex
495
+ name="buildingCount"
496
+ value=${this.project?.buildingComplex?.buildingCount?.toString() || ''}
497
+ @input=${this._onInputChange}
498
+ ></md-outlined-text-field>
499
+ <md-elevated-button @click=${this._setBuilding}>적용</md-elevated-button>
500
+ </span>
501
+ </div>
502
+ <hr />
503
+ <div warn>* 동/층의 정보를 수정하면 기존의 동/층 정보는 모두 제거됩니다.</div>
504
+ <div separate-container>
505
+ ${this.project?.buildingComplex?.buildings?.map(
506
+ (building, idx) => html`
507
+ <div>
508
+ <span>
509
+ <md-outlined-text-field
510
+ type="text"
511
+ building
512
+ name="name"
513
+ .value=${building?.name || ''}
514
+ @input=${e => this._onInputChange(e, idx)}
515
+ placeholder="ooo동"
516
+ ></md-outlined-text-field>
517
+ </span>
518
+ <span>
519
+ <span floor-title>층수</span>
520
+ <md-outlined-text-field
521
+ type="text"
522
+ numeric
523
+ building
524
+ name="floorCount"
525
+ .value=${building?.floorCount?.toString() || ''}
526
+ @input=${e => this._onInputChange(e, idx)}
527
+ placeholder="oo"
528
+ ></md-outlined-text-field>
529
+ </span>
530
+ </div>
531
+ `
532
+ )}
533
+ </div>
534
+ </div>
535
+
536
+ <div project>
537
+ <h3>프로젝트 현황</h3>
538
+ <div row separate-container>
539
+ <div>
540
+ <span>전체 진행현황</span>
541
+ <span
542
+ ><md-outlined-text-field
543
+ type="text"
544
+ numeric
545
+ project
546
+ name="totalProgress"
547
+ .value=${this.project.totalProgress?.toString() || ''}
548
+ @input=${this._onInputChange}
549
+ suffix-text="%"
550
+ ></md-outlined-text-field>
551
+ </span>
552
+ </div>
553
+ <div>
554
+ <span>검측/통과비율</span>
555
+ <span
556
+ ><md-outlined-text-field
557
+ type="text"
558
+ numeric
559
+ project
560
+ name="inspPassRate"
561
+ .value=${this.project.inspPassRate?.toString() || ''}
562
+ @input=${this._onInputChange}
563
+ suffix-text="%"
564
+ ></md-outlined-text-field>
565
+ </span>
566
+ </div>
567
+ </div>
568
+ <div row separate-container>
569
+ <div>
570
+ <span>주간 진행현황</span>
571
+ <span
572
+ ><md-outlined-text-field
573
+ type="text"
574
+ numeric
575
+ project
576
+ name="weeklyProgress"
577
+ .value=${this.project.weeklyProgress?.toString() || ''}
578
+ @input=${this._onInputChange}
579
+ suffix-text="%"
580
+ ></md-outlined-text-field>
581
+ </span>
582
+ </div>
583
+ <div>
584
+ <span>로봇작업진행율</span>
585
+ <span
586
+ ><md-outlined-text-field
587
+ type="text"
588
+ numeric
589
+ project
590
+ name="robotProgressRate"
591
+ .value=${this.project.robotProgressRate?.toString() || ''}
592
+ @input=${this._onInputChange}
593
+ suffix-text="%"
594
+ ></md-outlined-text-field>
595
+ </span>
596
+ </div>
597
+ </div>
598
+ <div row separate-container>
599
+ <div>
600
+ <span>KPI</span>
601
+ <span
602
+ ><md-outlined-text-field
603
+ type="text"
604
+ numeric
605
+ project
606
+ name="kpi"
607
+ .value=${this.project.kpi?.toString() || ''}
608
+ @input=${this._onInputChange}
609
+ suffix-text="%"
610
+ ></md-outlined-text-field>
611
+ </span>
612
+ </div>
613
+ <div>
614
+ <span>구조안전도</span>
615
+ <span
616
+ ><md-outlined-text-field
617
+ type="text"
618
+ numeric
619
+ project
620
+ name="structuralSafetyRate"
621
+ .value=${this.project.structuralSafetyRate?.toString() || ''}
622
+ @input=${this._onInputChange}
623
+ suffix-text="%"
624
+ ></md-outlined-text-field>
625
+ </span>
626
+ </div>
627
+ </div>
628
+ </div>
629
+
630
+ <div>
631
+ <h3>공지사항</h3>
632
+ <div>
633
+ <span></span>
634
+ <span>
635
+ <md-outlined-text-field
636
+ type="textarea"
637
+ name="notice"
638
+ building-complex
639
+ .value=${this.project?.buildingComplex?.notice || ''}
640
+ @input=${this._onInputChange}
641
+ ></md-outlined-text-field>
642
+ </span>
643
+ </div>
644
+ </div>
645
+ </div>
646
+ </div>
647
+ `
648
+ }
649
+
650
+ async pageInitialized(lifecycle: PageLifecycle) {}
651
+
652
+ async pageUpdated(changes: any, lifecycle: PageLifecycle) {
653
+ if (this.active) {
654
+ this.projectId = lifecycle.resourceId || ''
655
+ await this.initProject(this.projectId)
656
+ }
657
+ }
658
+
659
+ async initProject(projectId: string = '') {
660
+ const response = await client.query({
661
+ query: gql`
662
+ query Project($id: String!) {
663
+ project(id: $id) {
664
+ id
665
+ name
666
+ startDate
667
+ endDate
668
+ mainPhoto {
669
+ fullpath
670
+ }
671
+ totalProgress
672
+ weeklyProgress
673
+ kpi
674
+ inspPassRate
675
+ robotProgressRate
676
+ structuralSafetyRate
677
+ buildingComplex {
678
+ id
679
+ address
680
+ latitude
681
+ longitude
682
+ area
683
+ clientCompany
684
+ constructionCompany
685
+ supervisoryCompany
686
+ designCompany
687
+ drawing {
688
+ id
689
+ name
690
+ }
691
+ constructionType
692
+ constructionCost
693
+ etc
694
+ notice
695
+ householdCount
696
+ buildingCount
697
+ buildings {
698
+ id
699
+ name
700
+ floorCount
701
+ }
702
+ }
703
+ }
704
+ }
705
+ `,
706
+ variables: {
707
+ id: projectId
708
+ }
709
+ })
710
+
711
+ this.project = response.data?.project
712
+ console.log('init project : ', this.project)
713
+ }
714
+
715
+ private async _saveProject() {
716
+ // 첨부 파일 필드 제거 (첨부 파일은 {filename}Upload 로 전송)
717
+ delete this.project.mainPhoto
718
+ delete this.project.buildingComplex.drawing
719
+
720
+ console.log('this.project :', this.project)
721
+
722
+ const response = await client.mutate({
723
+ mutation: gql`
724
+ mutation UpdateProject($project: ProjectPatch!) {
725
+ updateProject(project: $project) {
726
+ id
727
+ }
728
+ }
729
+ `,
730
+ variables: {
731
+ project: this.project
732
+ },
733
+ context: {
734
+ hasUpload: true
735
+ }
736
+ })
737
+
738
+ if (!response.errors) {
739
+ notify({ message: '저장에 성공하였습니다.' })
740
+ }
741
+ }
742
+
743
+ // 동 적용 버튼을 누르면 입력한 수 만큼 해당 단지에 동 데이터 생성
744
+ private _setBuilding() {
745
+ const buildingCount: number = this.project?.buildingComplex?.buildingCount || 0
746
+ const buildingInitData = { name: undefined, floorCount: undefined }
747
+
748
+ // 빌딩 데이터가 없으면 빈 배열 넣어줌
749
+ if (!this.project?.buildingComplex?.buildings?.length) {
750
+ this.project.buildingComplex.buildings = []
751
+ }
752
+
753
+ if (this.project.buildingComplex.buildings.length >= buildingCount) {
754
+ // 동 수가 더 작게 들어오면 기존 배열을 필요한 크기만큼 잘라내기
755
+ this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings!.slice(0, buildingCount)]
756
+ } else {
757
+ // 동수가 더 크게 들어오면 기존 배열 + 빈 값을 채움
758
+ const additionalCount = buildingCount - this.project.buildingComplex.buildings.length
759
+ const additionalBuildings = Array.from({ length: additionalCount }, () => ({ ...buildingInitData }))
760
+ this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings, ...additionalBuildings]
761
+ }
762
+
763
+ // 리렌더링
764
+ this.project = { ...this.project }
765
+ }
766
+
767
+ // Input 요소의 값이 변경될 때 호출되는 콜백 함수
768
+ private _onInputChange(event: InputEvent, idx: number) {
769
+ const target = event.target as HTMLInputElement
770
+ let inputVal: any = target.value
771
+
772
+ // 숫자 타입은 다른 문자 입력 제거
773
+ if (target.hasAttribute('numeric')) {
774
+ inputVal = Number(inputVal.replace(/[^\d.]/g, ''))
775
+ }
776
+
777
+ if (target.hasAttribute('project')) {
778
+ this.project[target.name] = inputVal
779
+ } else if (target.hasAttribute('building-complex')) {
780
+ this.project.buildingComplex![target.name] = inputVal
781
+ } else if (target.hasAttribute('building')) {
782
+ this.project.buildingComplex.buildings![idx][target.name] = inputVal
783
+ }
784
+ }
785
+
786
+ // 이미지 업로드
787
+ async onCreateAttachment(e: CustomEvent) {
788
+ const target = e.target as HTMLInputElement
789
+ const file = (target.name === 'mainPhoto' ? e.detail : e.detail[0]) || null
790
+
791
+ if (target.name === 'mainPhoto') {
792
+ this.project.mainPhotoUpload = file
793
+ } else {
794
+ this.project.buildingComplex.drawingUpload = file
795
+ }
796
+ }
797
+ }