@dssp/supervision 1.0.0-alpha.26 → 1.0.0-alpha.28

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 (83) hide show
  1. package/dist-client/graphql/building-inspection.js +6 -0
  2. package/dist-client/graphql/building-inspection.js.map +1 -1
  3. package/dist-client/pages/action-plan/action-plan-importer.d.ts +1 -1
  4. package/dist-client/pages/action-plan/action-plan-list-page.d.ts +1 -1
  5. package/dist-client/pages/building-inspection/building-inspection-detail-camera.d.ts +1 -1
  6. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.d.ts +1 -1
  7. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js +25 -11
  8. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js.map +1 -1
  9. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.d.ts +1 -1
  10. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js +1 -1
  11. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js.map +1 -1
  12. package/dist-client/pages/building-inspection/building-inspection-list.d.ts +11 -2
  13. package/dist-client/pages/building-inspection/building-inspection-list.js +141 -10
  14. package/dist-client/pages/building-inspection/building-inspection-list.js.map +1 -1
  15. package/dist-client/pages/building-inspection/component/daily-worklog-popup.d.ts +22 -0
  16. package/dist-client/pages/building-inspection/component/daily-worklog-popup.js +431 -0
  17. package/dist-client/pages/building-inspection/component/daily-worklog-popup.js.map +1 -0
  18. package/dist-client/pages/building-inspection/component/image-preview-popup.d.ts +1 -1
  19. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.d.ts +1 -1
  20. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js +17 -21
  21. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js.map +1 -1
  22. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.d.ts +4 -1
  23. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js +45 -19
  24. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js.map +1 -1
  25. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.d.ts +1 -1
  26. package/dist-client/pages/building-inspection/component/inspection-event-provider.d.ts +2 -1
  27. package/dist-client/pages/building-inspection/component/inspection-event-provider.js +39 -17
  28. package/dist-client/pages/building-inspection/component/inspection-event-provider.js.map +1 -1
  29. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.d.ts +2 -2
  30. package/dist-client/pages/building-inspection-grid/component/plan-preview-popup.d.ts +1 -1
  31. package/dist-client/pages/checklist/checklist-view.js +28 -3
  32. package/dist-client/pages/checklist/checklist-view.js.map +1 -1
  33. package/dist-client/pages/checklist/inspection-info-popup.d.ts +1 -1
  34. package/dist-client/pages/checklist/inspection-tab-popup.d.ts +1 -1
  35. package/dist-client/pages/checklist-template/checklist-template-list.d.ts +1 -1
  36. package/dist-client/pages/checklist-template/checklist-type-management.d.ts +1 -1
  37. package/dist-client/pages/issue/issue-importer.d.ts +1 -1
  38. package/dist-client/pages/issue/issue-list-page.d.ts +1 -1
  39. package/dist-client/pages/project-report/project-report-importer.d.ts +1 -1
  40. package/dist-client/pages/project-report/project-report-list-page.d.ts +1 -1
  41. package/dist-client/pages/supervisor/supervisor-importer.d.ts +1 -1
  42. package/dist-client/pages/supervisor/supervisor-list-page.d.ts +1 -1
  43. package/dist-client/tsconfig.tsbuildinfo +1 -1
  44. package/dist-server/service/building-inspection/building-inspection-mutation.js +7 -2
  45. package/dist-server/service/building-inspection/building-inspection-mutation.js.map +1 -1
  46. package/dist-server/service/building-inspection/building-inspection-query.js +7 -1
  47. package/dist-server/service/building-inspection/building-inspection-query.js.map +1 -1
  48. package/dist-server/service/building-inspection/building-inspection-type.d.ts +2 -0
  49. package/dist-server/service/building-inspection/building-inspection-type.js +8 -0
  50. package/dist-server/service/building-inspection/building-inspection-type.js.map +1 -1
  51. package/dist-server/service/building-inspection/building-inspection.d.ts +3 -0
  52. package/dist-server/service/building-inspection/building-inspection.js +10 -0
  53. package/dist-server/service/building-inspection/building-inspection.js.map +1 -1
  54. package/dist-server/service/building-inspection/index.d.ts +1 -1
  55. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.d.ts +6 -0
  56. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.js +56 -0
  57. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.js.map +1 -0
  58. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.d.ts +14 -0
  59. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.js +135 -0
  60. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.js.map +1 -0
  61. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.d.ts +19 -0
  62. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.js +74 -0
  63. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.js.map +1 -0
  64. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.d.ts +27 -0
  65. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.js +104 -0
  66. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.js.map +1 -0
  67. package/dist-server/service/building-inspection-daily-worklog/index.d.ts +5 -0
  68. package/dist-server/service/building-inspection-daily-worklog/index.js +9 -0
  69. package/dist-server/service/building-inspection-daily-worklog/index.js.map +1 -0
  70. package/dist-server/service/checklist/checklist.d.ts +4 -1
  71. package/dist-server/service/checklist/checklist.js +15 -4
  72. package/dist-server/service/checklist/checklist.js.map +1 -1
  73. package/dist-server/service/index.d.ts +2 -1
  74. package/dist-server/service/index.js +6 -2
  75. package/dist-server/service/index.js.map +1 -1
  76. package/dist-server/tsconfig.tsbuildinfo +1 -1
  77. package/package.json +5 -4
  78. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.d.ts +0 -21
  79. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.js +0 -327
  80. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.js.map +0 -1
  81. package/dist-client/pages/building-inspection/component/photo-album-popup.d.ts +0 -41
  82. package/dist-client/pages/building-inspection/component/photo-album-popup.js +0 -406
  83. package/dist-client/pages/building-inspection/component/photo-album-popup.js.map +0 -1
@@ -1,406 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import '@material/web/button/elevated-button.js';
3
- import '@material/web/icon/icon.js';
4
- import '@material/web/tabs/tabs.js';
5
- import '@material/web/tabs/primary-tab.js';
6
- import gql from 'graphql-tag';
7
- import { client } from '@operato/graphql';
8
- import { css, html, LitElement } from 'lit';
9
- import { customElement, property, state } from 'lit/decorators.js';
10
- import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles';
11
- import { notify, openPopup } from '@operato/layout';
12
- import { store, User } from '@operato/shell';
13
- import { connect } from 'pwa-helpers/connect-mixin.js';
14
- import './image-preview-popup';
15
- export var PhotoTab;
16
- (function (PhotoTab) {
17
- PhotoTab["CONSTRUCTOR"] = "constructor";
18
- PhotoTab["SUPERVISOR"] = "supervisor";
19
- })(PhotoTab || (PhotoTab = {}));
20
- let PhotoAlbumPopup = class PhotoAlbumPopup extends connect(store)(LitElement) {
21
- constructor() {
22
- super(...arguments);
23
- this.checklistId = '';
24
- this.title = '사진대지';
25
- this.activeTab = PhotoTab.CONSTRUCTOR;
26
- this.constructorPhotos = [];
27
- this.supervisorPhotos = [];
28
- this.user = {};
29
- }
30
- render() {
31
- const currentPhotos = this.activeTab === PhotoTab.CONSTRUCTOR ? this.constructorPhotos : this.supervisorPhotos;
32
- const constructorCount = this.constructorPhotos.length;
33
- const supervisorCount = this.supervisorPhotos.length;
34
- return html `
35
- <h3>${this.title}</h3>
36
-
37
- <div body>
38
- <div class="tabs-container">
39
- <md-tabs @change=${this._onTabChange}>
40
- <md-primary-tab
41
- ?active=${this.activeTab === PhotoTab.CONSTRUCTOR}
42
- @click=${() => this._setActiveTab(PhotoTab.CONSTRUCTOR)}
43
- >
44
- 시공자 (${constructorCount})
45
- </md-primary-tab>
46
- <md-primary-tab
47
- ?active=${this.activeTab === PhotoTab.SUPERVISOR}
48
- @click=${() => this._setActiveTab(PhotoTab.SUPERVISOR)}
49
- >
50
- 감리자 (${supervisorCount})
51
- </md-primary-tab>
52
- </md-tabs>
53
- </div>
54
-
55
- <div class="tab-content">
56
- <div class="photo-count">
57
- ${this.activeTab === PhotoTab.CONSTRUCTOR ? '시공자' : '감리자'} 사진: ${currentPhotos.length}건
58
- </div>
59
-
60
- ${currentPhotos.length > 0
61
- ? html `
62
- <div class="photo-grid">
63
- ${currentPhotos.map((photo, index) => {
64
- var _a, _b;
65
- return html `
66
- <div class="photo-item" @click=${() => this._openPhotoPreview(currentPhotos, index)}>
67
- <img
68
- src="${photo.fullpath}"
69
- alt="${photo.name}"
70
- @error=${(e) => this._onImageError(e, photo)}
71
- />
72
- <div class="photo-overlay">
73
- <div class="photo-info">
74
- <div class="photo-name">${((_a = photo.checklistItem) === null || _a === void 0 ? void 0 : _a.name) || photo.name || ''}</div>
75
- <div class="photo-creator">
76
- <md-icon style="--md-icon-size: 10px;">account_circle</md-icon>
77
- ${((_b = photo.creator) === null || _b === void 0 ? void 0 : _b.name) || ''}
78
- </div>
79
- <div class="photo-date">${this._formatDate(photo.createdAt)}</div>
80
- </div>
81
- </div>
82
- </div>
83
- `;
84
- })}
85
- </div>
86
- `
87
- : html `
88
- <div class="empty-state">
89
- <md-icon>photo_library</md-icon>
90
- <div>${this.activeTab === PhotoTab.CONSTRUCTOR ? '시공자' : '감리자'}가 업로드한 사진이 없습니다.</div>
91
- </div>
92
- `}
93
- </div>
94
- </div>
95
-
96
- <div class="button-container">
97
- <md-elevated-button @click=${this._close}>
98
- <md-icon slot="icon">close</md-icon>닫기
99
- </md-elevated-button>
100
- </div>
101
- `;
102
- }
103
- async firstUpdated() {
104
- var _a;
105
- this.user = (_a = store.getState().auth) === null || _a === void 0 ? void 0 : _a.user;
106
- await this._loadPhotos();
107
- }
108
- async _loadPhotos() {
109
- var _a;
110
- try {
111
- const response = await client.query({
112
- query: gql `
113
- query ChecklistPhotos($checklistId: String!) {
114
- checklist(id: $checklistId) {
115
- id
116
- checklistItems {
117
- id
118
- name
119
- checklistItemAttachments {
120
- id
121
- name
122
- fullpath
123
- creator {
124
- id
125
- name
126
- email
127
- }
128
- createdAt
129
- }
130
- }
131
- }
132
- }
133
- `,
134
- variables: {
135
- checklistId: this.checklistId
136
- }
137
- });
138
- if (response.errors) {
139
- notify({ message: '사진 목록을 불러오는데 실패했습니다.', level: 'error' });
140
- return;
141
- }
142
- const checklist = response.data.checklist;
143
- const allAttachments = [];
144
- // 모든 체크리스트 아이템의 첨부파일을 수집
145
- (_a = checklist.checklistItems) === null || _a === void 0 ? void 0 : _a.forEach((item) => {
146
- var _a;
147
- (_a = item.checklistItemAttachments) === null || _a === void 0 ? void 0 : _a.forEach((attachment) => {
148
- // 이미지 파일만 필터링
149
- if (this._isImageFile(attachment.fullpath)) {
150
- allAttachments.push(Object.assign(Object.assign({}, attachment), { checklistItem: {
151
- id: item.id,
152
- name: item.name
153
- } }));
154
- }
155
- });
156
- });
157
- // 시공자와 감리자로 분류 (이메일 도메인이나 역할로 구분)
158
- this.constructorPhotos = allAttachments.filter(attachment => { var _a; return this._isConstructor(((_a = attachment.creator) === null || _a === void 0 ? void 0 : _a.email) || ''); });
159
- this.supervisorPhotos = allAttachments.filter(attachment => { var _a; return this._isSupervisor(((_a = attachment.creator) === null || _a === void 0 ? void 0 : _a.email) || ''); });
160
- }
161
- catch (error) {
162
- console.error('사진 목록 로딩 중 오류 발생:', error);
163
- notify({ message: '사진 목록을 불러오는데 실패했습니다.', level: 'error' });
164
- }
165
- }
166
- _isImageFile(filepath) {
167
- if (!filepath)
168
- return false;
169
- const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
170
- const extension = filepath.toLowerCase().split('.').pop();
171
- return imageExtensions.includes(extension || '');
172
- }
173
- _isConstructor(email) {
174
- // 시공자 이메일 패턴을 확인 (예: 회사 도메인이나 역할로 구분)
175
- // 이 로직은 실제 시스템의 사용자 역할 구분 방식에 따라 수정해야 합니다
176
- return email.includes('constructor') || email.includes('builder') ||
177
- email.includes('시공') || this._checkUserRole(email, 'constructor');
178
- }
179
- _isSupervisor(email) {
180
- // 감리자 이메일 패턴을 확인
181
- // 이 로직은 실제 시스템의 사용자 역할 구분 방식에 따라 수정해야 합니다
182
- return email.includes('supervisor') || email.includes('monitor') ||
183
- email.includes('감리') || this._checkUserRole(email, 'supervisor');
184
- }
185
- _checkUserRole(email, role) {
186
- // 실제 사용자 역할 확인 로직을 구현
187
- // 예: 사용자 정보에서 역할을 확인하거나, 이메일 도메인으로 구분
188
- // 현재는 기본적으로 시공자로 분류
189
- return role === 'constructor';
190
- }
191
- _setActiveTab(tab) {
192
- this.activeTab = tab;
193
- }
194
- _onTabChange(e) {
195
- // md-tabs의 change 이벤트 처리 (필요한 경우)
196
- }
197
- _openPhotoPreview(photos, startIndex) {
198
- openPopup(html `
199
- <image-preview-popup
200
- .images=${photos}
201
- .currentIndex=${startIndex}
202
- .title=${'사진 미리보기'}
203
- ></image-preview-popup>
204
- `, {
205
- backdrop: true,
206
- size: 'large',
207
- title: '사진 미리보기'
208
- });
209
- }
210
- _onImageError(e, photo) {
211
- const target = e.target;
212
- target.style.display = 'none';
213
- // 오류 발생 시 기본 아이콘 표시
214
- const container = target.parentElement;
215
- container.innerHTML += `
216
- <div style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background-color: #f5f5f5;">
217
- <md-icon style="--md-icon-size: 48px; color: #ccc;">broken_image</md-icon>
218
- </div>
219
- `;
220
- }
221
- _formatDate(date) {
222
- const _date = new Date(date);
223
- if (isNaN(_date.getTime())) {
224
- return '날짜 없음';
225
- }
226
- const year = _date.getFullYear();
227
- const month = String(_date.getMonth() + 1).padStart(2, '0');
228
- const day = String(_date.getDate()).padStart(2, '0');
229
- const hours = String(_date.getHours()).padStart(2, '0');
230
- const minutes = String(_date.getMinutes()).padStart(2, '0');
231
- return `${year}.${month}.${day} ${hours}:${minutes}`;
232
- }
233
- _close() {
234
- history.back();
235
- }
236
- };
237
- PhotoAlbumPopup.styles = [
238
- ButtonContainerStyles,
239
- ScrollbarStyles,
240
- css `
241
- :host {
242
- display: flex;
243
- flex-direction: column;
244
- background-color: #fff;
245
- width: 100%;
246
- max-height: 80vh;
247
- }
248
-
249
- div[body] {
250
- flex: 1;
251
- overflow-y: auto;
252
- padding: 20px;
253
- }
254
-
255
- .tabs-container {
256
- margin-bottom: 20px;
257
- border-bottom: 2px solid #ddd;
258
- }
259
-
260
- md-tabs {
261
- --md-primary-tab-container-color: transparent;
262
- --md-primary-tab-active-indicator-color: #2196f3;
263
- --md-primary-tab-label-text-color: #666;
264
- --md-primary-tab-active-label-text-color: #2196f3;
265
- }
266
-
267
- .photo-grid {
268
- display: grid;
269
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
270
- gap: 15px;
271
- margin-bottom: 20px;
272
- }
273
-
274
- .photo-item {
275
- position: relative;
276
- aspect-ratio: 1;
277
- border-radius: 8px;
278
- overflow: hidden;
279
- cursor: pointer;
280
- transition: all 0.2s ease;
281
- border: 2px solid #ddd;
282
- }
283
-
284
- .photo-item:hover {
285
- transform: translateY(-2px);
286
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
287
- border-color: #2196f3;
288
- }
289
-
290
- .photo-item img {
291
- width: 100%;
292
- height: 100%;
293
- object-fit: cover;
294
- }
295
-
296
- .photo-overlay {
297
- position: absolute;
298
- bottom: 0;
299
- left: 0;
300
- right: 0;
301
- background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
302
- color: white;
303
- padding: 10px 8px 8px;
304
- font-size: 12px;
305
- line-height: 1.2;
306
- }
307
-
308
- .photo-info {
309
- display: flex;
310
- flex-direction: column;
311
- gap: 2px;
312
- }
313
-
314
- .photo-name {
315
- font-weight: bold;
316
- overflow: hidden;
317
- text-overflow: ellipsis;
318
- white-space: nowrap;
319
- }
320
-
321
- .photo-creator {
322
- font-size: 10px;
323
- opacity: 0.9;
324
- display: flex;
325
- align-items: center;
326
- gap: 3px;
327
- }
328
-
329
- .photo-date {
330
- font-size: 10px;
331
- opacity: 0.8;
332
- }
333
-
334
- .empty-state {
335
- text-align: center;
336
- color: #666;
337
- padding: 60px 20px;
338
- }
339
-
340
- .empty-state md-icon {
341
- --md-icon-size: 64px;
342
- color: #ccc;
343
- margin-bottom: 16px;
344
- }
345
-
346
- .tab-content {
347
- min-height: 300px;
348
- }
349
-
350
- .photo-count {
351
- color: #666;
352
- font-size: 14px;
353
- margin-bottom: 15px;
354
- padding: 10px;
355
- background-color: #f5f5f5;
356
- border-radius: 5px;
357
- text-align: center;
358
- }
359
-
360
- h3 {
361
- position: relative;
362
- color: rgb(5, 149, 229);
363
- font-size: 17px;
364
- font-weight: 700;
365
- margin: 0px 0px 20px 0px;
366
- padding-top: 0px;
367
- }
368
-
369
- .button-container {
370
- display: flex;
371
- justify-content: center;
372
- padding: 15px;
373
- border-top: 1px solid #ddd;
374
- background-color: #f9f9f9;
375
- }
376
- `
377
- ];
378
- __decorate([
379
- property({ type: String }),
380
- __metadata("design:type", String)
381
- ], PhotoAlbumPopup.prototype, "checklistId", void 0);
382
- __decorate([
383
- property({ type: String }),
384
- __metadata("design:type", String)
385
- ], PhotoAlbumPopup.prototype, "title", void 0);
386
- __decorate([
387
- state(),
388
- __metadata("design:type", String)
389
- ], PhotoAlbumPopup.prototype, "activeTab", void 0);
390
- __decorate([
391
- state(),
392
- __metadata("design:type", Array)
393
- ], PhotoAlbumPopup.prototype, "constructorPhotos", void 0);
394
- __decorate([
395
- state(),
396
- __metadata("design:type", Array)
397
- ], PhotoAlbumPopup.prototype, "supervisorPhotos", void 0);
398
- __decorate([
399
- state(),
400
- __metadata("design:type", User)
401
- ], PhotoAlbumPopup.prototype, "user", void 0);
402
- PhotoAlbumPopup = __decorate([
403
- customElement('photo-album-popup')
404
- ], PhotoAlbumPopup);
405
- export { PhotoAlbumPopup };
406
- //# sourceMappingURL=photo-album-popup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"photo-album-popup.js","sourceRoot":"","sources":["../../../../client/pages/building-inspection/component/photo-album-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@material/web/icon/icon.js'\nimport '@material/web/tabs/tabs.js'\nimport '@material/web/tabs/primary-tab.js'\n\nimport gql from 'graphql-tag'\nimport { client } from '@operato/graphql'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'\nimport { notify, openPopup } from '@operato/layout'\nimport { store, User } from '@operato/shell'\nimport { connect } from 'pwa-helpers/connect-mixin.js'\nimport './image-preview-popup'\n\nexport enum PhotoTab {\n CONSTRUCTOR = 'constructor',\n SUPERVISOR = 'supervisor'\n}\n\n@customElement('photo-album-popup')\nexport class PhotoAlbumPopup extends connect(store)(LitElement) {\n static styles = [\n ButtonContainerStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n background-color: #fff;\n width: 100%;\n max-height: 80vh;\n }\n\n div[body] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n }\n\n .tabs-container {\n margin-bottom: 20px;\n border-bottom: 2px solid #ddd;\n }\n\n md-tabs {\n --md-primary-tab-container-color: transparent;\n --md-primary-tab-active-indicator-color: #2196f3;\n --md-primary-tab-label-text-color: #666;\n --md-primary-tab-active-label-text-color: #2196f3;\n }\n\n .photo-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 15px;\n margin-bottom: 20px;\n }\n\n .photo-item {\n position: relative;\n aspect-ratio: 1;\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 2px solid #ddd;\n }\n\n .photo-item:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n border-color: #2196f3;\n }\n\n .photo-item img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .photo-overlay {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));\n color: white;\n padding: 10px 8px 8px;\n font-size: 12px;\n line-height: 1.2;\n }\n\n .photo-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .photo-name {\n font-weight: bold;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .photo-creator {\n font-size: 10px;\n opacity: 0.9;\n display: flex;\n align-items: center;\n gap: 3px;\n }\n\n .photo-date {\n font-size: 10px;\n opacity: 0.8;\n }\n\n .empty-state {\n text-align: center;\n color: #666;\n padding: 60px 20px;\n }\n\n .empty-state md-icon {\n --md-icon-size: 64px;\n color: #ccc;\n margin-bottom: 16px;\n }\n\n .tab-content {\n min-height: 300px;\n }\n\n .photo-count {\n color: #666;\n font-size: 14px;\n margin-bottom: 15px;\n padding: 10px;\n background-color: #f5f5f5;\n border-radius: 5px;\n text-align: center;\n }\n\n h3 {\n position: relative;\n color: rgb(5, 149, 229);\n font-size: 17px;\n font-weight: 700;\n margin: 0px 0px 20px 0px;\n padding-top: 0px;\n }\n\n .button-container {\n display: flex;\n justify-content: center;\n padding: 15px;\n border-top: 1px solid #ddd;\n background-color: #f9f9f9;\n }\n `\n ]\n\n @property({ type: String }) checklistId: string = ''\n @property({ type: String }) title: string = '사진대지'\n\n @state() activeTab: PhotoTab = PhotoTab.CONSTRUCTOR\n @state() constructorPhotos: any[] = []\n @state() supervisorPhotos: any[] = []\n @state() user: User = {}\n\n render() {\n const currentPhotos = this.activeTab === PhotoTab.CONSTRUCTOR ? this.constructorPhotos : this.supervisorPhotos\n const constructorCount = this.constructorPhotos.length\n const supervisorCount = this.supervisorPhotos.length\n\n return html`\n <h3>${this.title}</h3>\n\n <div body>\n <div class=\"tabs-container\">\n <md-tabs @change=${this._onTabChange}>\n <md-primary-tab \n ?active=${this.activeTab === PhotoTab.CONSTRUCTOR}\n @click=${() => this._setActiveTab(PhotoTab.CONSTRUCTOR)}\n >\n 시공자 (${constructorCount})\n </md-primary-tab>\n <md-primary-tab \n ?active=${this.activeTab === PhotoTab.SUPERVISOR}\n @click=${() => this._setActiveTab(PhotoTab.SUPERVISOR)}\n >\n 감리자 (${supervisorCount})\n </md-primary-tab>\n </md-tabs>\n </div>\n\n <div class=\"tab-content\">\n <div class=\"photo-count\">\n ${this.activeTab === PhotoTab.CONSTRUCTOR ? '시공자' : '감리자'} 사진: ${currentPhotos.length}건\n </div>\n\n ${currentPhotos.length > 0\n ? html`\n <div class=\"photo-grid\">\n ${currentPhotos.map(\n (photo, index) => html`\n <div class=\"photo-item\" @click=${() => this._openPhotoPreview(currentPhotos, index)}>\n <img \n src=\"${photo.fullpath}\" \n alt=\"${photo.name}\"\n @error=${(e: Event) => this._onImageError(e, photo)}\n />\n <div class=\"photo-overlay\">\n <div class=\"photo-info\">\n <div class=\"photo-name\">${photo.checklistItem?.name || photo.name || ''}</div>\n <div class=\"photo-creator\">\n <md-icon style=\"--md-icon-size: 10px;\">account_circle</md-icon>\n ${photo.creator?.name || ''}\n </div>\n <div class=\"photo-date\">${this._formatDate(photo.createdAt)}</div>\n </div>\n </div>\n </div>\n `\n )}\n </div>\n `\n : html`\n <div class=\"empty-state\">\n <md-icon>photo_library</md-icon>\n <div>${this.activeTab === PhotoTab.CONSTRUCTOR ? '시공자' : '감리자'}가 업로드한 사진이 없습니다.</div>\n </div>\n `}\n </div>\n </div>\n\n <div class=\"button-container\">\n <md-elevated-button @click=${this._close}>\n <md-icon slot=\"icon\">close</md-icon>닫기\n </md-elevated-button>\n </div>\n `\n }\n\n async firstUpdated() {\n this.user = (store.getState() as any).auth?.user\n await this._loadPhotos()\n }\n\n private async _loadPhotos() {\n try {\n const response = await client.query({\n query: gql`\n query ChecklistPhotos($checklistId: String!) {\n checklist(id: $checklistId) {\n id\n checklistItems {\n id\n name\n checklistItemAttachments {\n id\n name\n fullpath\n creator {\n id\n name\n email\n }\n createdAt\n }\n }\n }\n }\n `,\n variables: {\n checklistId: this.checklistId\n }\n })\n\n if (response.errors) {\n notify({ message: '사진 목록을 불러오는데 실패했습니다.', level: 'error' })\n return\n }\n\n const checklist = response.data.checklist\n const allAttachments: any[] = []\n\n // 모든 체크리스트 아이템의 첨부파일을 수집\n checklist.checklistItems?.forEach((item: any) => {\n item.checklistItemAttachments?.forEach((attachment: any) => {\n // 이미지 파일만 필터링\n if (this._isImageFile(attachment.fullpath)) {\n allAttachments.push({\n ...attachment,\n checklistItem: {\n id: item.id,\n name: item.name\n }\n })\n }\n })\n })\n\n // 시공자와 감리자로 분류 (이메일 도메인이나 역할로 구분)\n this.constructorPhotos = allAttachments.filter(attachment => \n this._isConstructor(attachment.creator?.email || '')\n )\n \n this.supervisorPhotos = allAttachments.filter(attachment => \n this._isSupervisor(attachment.creator?.email || '')\n )\n\n } catch (error) {\n console.error('사진 목록 로딩 중 오류 발생:', error)\n notify({ message: '사진 목록을 불러오는데 실패했습니다.', level: 'error' })\n }\n }\n\n private _isImageFile(filepath: string): boolean {\n if (!filepath) return false\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']\n const extension = filepath.toLowerCase().split('.').pop()\n return imageExtensions.includes(extension || '')\n }\n\n private _isConstructor(email: string): boolean {\n // 시공자 이메일 패턴을 확인 (예: 회사 도메인이나 역할로 구분)\n // 이 로직은 실제 시스템의 사용자 역할 구분 방식에 따라 수정해야 합니다\n return email.includes('constructor') || email.includes('builder') || \n email.includes('시공') || this._checkUserRole(email, 'constructor')\n }\n\n private _isSupervisor(email: string): boolean {\n // 감리자 이메일 패턴을 확인\n // 이 로직은 실제 시스템의 사용자 역할 구분 방식에 따라 수정해야 합니다\n return email.includes('supervisor') || email.includes('monitor') || \n email.includes('감리') || this._checkUserRole(email, 'supervisor')\n }\n\n private _checkUserRole(email: string, role: string): boolean {\n // 실제 사용자 역할 확인 로직을 구현\n // 예: 사용자 정보에서 역할을 확인하거나, 이메일 도메인으로 구분\n // 현재는 기본적으로 시공자로 분류\n return role === 'constructor'\n }\n\n private _setActiveTab(tab: PhotoTab) {\n this.activeTab = tab\n }\n\n private _onTabChange(e: Event) {\n // md-tabs의 change 이벤트 처리 (필요한 경우)\n }\n\n private _openPhotoPreview(photos: any[], startIndex: number) {\n openPopup(\n html`\n <image-preview-popup\n .images=${photos}\n .currentIndex=${startIndex}\n .title=${'사진 미리보기'}\n ></image-preview-popup>\n `,\n {\n backdrop: true,\n size: 'large',\n title: '사진 미리보기'\n }\n )\n }\n\n private _onImageError(e: Event, photo: any) {\n const target = e.target as HTMLImageElement\n target.style.display = 'none'\n \n // 오류 발생 시 기본 아이콘 표시\n const container = target.parentElement!\n container.innerHTML += `\n <div style=\"display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background-color: #f5f5f5;\">\n <md-icon style=\"--md-icon-size: 48px; color: #ccc;\">broken_image</md-icon>\n </div>\n `\n }\n\n private _formatDate(date: string | Date): string {\n const _date = new Date(date)\n \n if (isNaN(_date.getTime())) {\n return '날짜 없음'\n }\n\n const year = _date.getFullYear()\n const month = String(_date.getMonth() + 1).padStart(2, '0')\n const day = String(_date.getDate()).padStart(2, '0')\n const hours = String(_date.getHours()).padStart(2, '0')\n const minutes = String(_date.getMinutes()).padStart(2, '0')\n\n return `${year}.${month}.${day} ${hours}:${minutes}`\n }\n\n private _close() {\n history.back()\n }\n}"]}