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

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 (70) hide show
  1. package/dist-client/graphql/building-inspection.js +28 -0
  2. package/dist-client/graphql/building-inspection.js.map +1 -1
  3. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.d.ts +9 -0
  4. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js +114 -4
  5. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js.map +1 -1
  6. package/dist-client/pages/building-inspection/building-inspection-list.d.ts +6 -0
  7. package/dist-client/pages/building-inspection/building-inspection-list.js +47 -8
  8. package/dist-client/pages/building-inspection/building-inspection-list.js.map +1 -1
  9. package/dist-client/pages/building-inspection/component/image-preview-popup.d.ts +15 -0
  10. package/dist-client/pages/building-inspection/component/image-preview-popup.js +351 -0
  11. package/dist-client/pages/building-inspection/component/image-preview-popup.js.map +1 -0
  12. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.d.ts +20 -0
  13. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js +436 -0
  14. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js.map +1 -0
  15. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.d.ts +27 -0
  16. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js +453 -0
  17. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js.map +1 -0
  18. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.d.ts +21 -0
  19. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.js +327 -0
  20. package/dist-client/pages/building-inspection/component/inspection-document/name-list-upload-popup.js.map +1 -0
  21. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.d.ts +27 -0
  22. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js +401 -0
  23. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js.map +1 -0
  24. package/dist-client/pages/building-inspection/component/photo-album-popup.d.ts +41 -0
  25. package/dist-client/pages/building-inspection/component/photo-album-popup.js +406 -0
  26. package/dist-client/pages/building-inspection/component/photo-album-popup.js.map +1 -0
  27. package/dist-client/pages/building-inspection/inspection-create-popup.js +17 -5
  28. package/dist-client/pages/building-inspection/inspection-create-popup.js.map +1 -1
  29. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.d.ts +1 -0
  30. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.js +47 -3
  31. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.js.map +1 -1
  32. package/dist-client/pages/building-inspection-grid/component/grid-inspection-create-popup.js +8 -2
  33. package/dist-client/pages/building-inspection-grid/component/grid-inspection-create-popup.js.map +1 -1
  34. package/dist-client/pages/checklist/attachment-list-popup.d.ts +1 -0
  35. package/dist-client/pages/checklist/attachment-list-popup.js +244 -68
  36. package/dist-client/pages/checklist/attachment-list-popup.js.map +1 -1
  37. package/dist-client/pages/checklist/checklist-view.d.ts +5 -0
  38. package/dist-client/pages/checklist/checklist-view.js +64 -14
  39. package/dist-client/pages/checklist/checklist-view.js.map +1 -1
  40. package/dist-client/pages/checklist/file-preview-popup.js +0 -1
  41. package/dist-client/pages/checklist/file-preview-popup.js.map +1 -1
  42. package/dist-client/pages/checklist/inspection-tab-popup.js +3 -1
  43. package/dist-client/pages/checklist/inspection-tab-popup.js.map +1 -1
  44. package/dist-client/pages/checklist-template/checklist-template-list.js +1 -1
  45. package/dist-client/pages/checklist-template/checklist-template-list.js.map +1 -1
  46. package/dist-client/route.d.ts +1 -1
  47. package/dist-client/tsconfig.tsbuildinfo +1 -1
  48. package/dist-server/service/building-inspection/building-inspection-history.d.ts +1 -0
  49. package/dist-server/service/building-inspection/building-inspection-history.js +5 -0
  50. package/dist-server/service/building-inspection/building-inspection-history.js.map +1 -1
  51. package/dist-server/service/building-inspection/building-inspection-mutation.js +48 -21
  52. package/dist-server/service/building-inspection/building-inspection-mutation.js.map +1 -1
  53. package/dist-server/service/building-inspection/building-inspection-type.d.ts +6 -0
  54. package/dist-server/service/building-inspection/building-inspection-type.js +21 -0
  55. package/dist-server/service/building-inspection/building-inspection-type.js.map +1 -1
  56. package/dist-server/service/building-inspection/building-inspection.js +1 -1
  57. package/dist-server/service/building-inspection/building-inspection.js.map +1 -1
  58. package/dist-server/service/building-inspection/index.d.ts +1 -1
  59. package/dist-server/service/checklist/checklist-query.d.ts +6 -0
  60. package/dist-server/service/checklist/checklist-query.js +63 -0
  61. package/dist-server/service/checklist/checklist-query.js.map +1 -1
  62. package/dist-server/service/checklist/checklist.d.ts +20 -0
  63. package/dist-server/service/checklist/checklist.js +62 -1
  64. package/dist-server/service/checklist/checklist.js.map +1 -1
  65. package/dist-server/service/checklist-item/checklist-item-query.d.ts +1 -1
  66. package/dist-server/service/checklist-item/checklist-item-query.js +5 -3
  67. package/dist-server/service/checklist-item/checklist-item-query.js.map +1 -1
  68. package/dist-server/service/index.d.ts +1 -1
  69. package/dist-server/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +2 -2
@@ -0,0 +1,327 @@
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/button/outlined-button.js';
5
+ import gql from 'graphql-tag';
6
+ import { client } from '@operato/graphql';
7
+ import { css, html, LitElement } from 'lit';
8
+ import { customElement, property, state } from 'lit/decorators.js';
9
+ import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles';
10
+ import { notify } from '@operato/layout';
11
+ let NameListUploadPopup = class NameListUploadPopup extends LitElement {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.checklistId = '';
15
+ this.selectedFile = null;
16
+ }
17
+ render() {
18
+ return html `
19
+ <div body>
20
+ <div
21
+ upload-area
22
+ @click=${this._selectFile}
23
+ @drop=${this._handleDrop}
24
+ @dragover=${this._handleDragOver}
25
+ @dragleave=${this._handleDragLeave}
26
+ >
27
+ ${!this.selectedFile
28
+ ? html `
29
+ <div upload-icon>
30
+ <md-icon>cloud_upload</md-icon>
31
+ </div>
32
+ <div upload-text>
33
+ <h3>실명부 파일 업로드</h3>
34
+ <p>파일을 클릭하거나 드래그하여 업로드하세요</p>
35
+ </div>
36
+ `
37
+ : html `
38
+ <div file-preview>
39
+ <div file-icon>
40
+ <md-icon>description</md-icon>
41
+ </div>
42
+ <div file-info>
43
+ <span>${this.selectedFile.name}</span>
44
+ <small>${this._formatFileSize(this.selectedFile.size)}</small>
45
+ </div>
46
+ <div remove-button @click=${this._removeFile}>
47
+ <md-icon>close</md-icon>
48
+ </div>
49
+ </div>
50
+ `}
51
+ </div>
52
+
53
+ <input type="file" id="file-input" accept=".pdf,.doc,.docx,.jpg,.jpeg,.png" @change=${this._handleFileSelect} />
54
+ </div>
55
+
56
+ <div button-container>
57
+ <md-outlined-button @click=${this._close}>닫기</md-outlined-button>
58
+ </div>
59
+ `;
60
+ }
61
+ _selectFile() {
62
+ var _a;
63
+ if (this.selectedFile)
64
+ return;
65
+ const input = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#file-input');
66
+ input === null || input === void 0 ? void 0 : input.click();
67
+ }
68
+ _handleFileSelect(e) {
69
+ var _a;
70
+ const input = e.target;
71
+ const file = (_a = input.files) === null || _a === void 0 ? void 0 : _a[0];
72
+ if (file) {
73
+ this.selectedFile = file;
74
+ }
75
+ }
76
+ _handleDrop(e) {
77
+ var _a, _b;
78
+ e.preventDefault();
79
+ e.stopPropagation();
80
+ this._removeDragOverClass();
81
+ const file = (_b = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0];
82
+ if (file) {
83
+ this.selectedFile = file;
84
+ }
85
+ }
86
+ _handleDragOver(e) {
87
+ e.preventDefault();
88
+ e.stopPropagation();
89
+ this._addDragOverClass();
90
+ }
91
+ _handleDragLeave(e) {
92
+ e.preventDefault();
93
+ e.stopPropagation();
94
+ this._removeDragOverClass();
95
+ }
96
+ _addDragOverClass() {
97
+ var _a;
98
+ const uploadArea = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('[upload-area]');
99
+ uploadArea === null || uploadArea === void 0 ? void 0 : uploadArea.classList.add('drag-over');
100
+ }
101
+ _removeDragOverClass() {
102
+ var _a;
103
+ const uploadArea = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('[upload-area]');
104
+ uploadArea === null || uploadArea === void 0 ? void 0 : uploadArea.classList.remove('drag-over');
105
+ }
106
+ _removeFile(e) {
107
+ var _a;
108
+ e.stopPropagation();
109
+ this.selectedFile = null;
110
+ // 파일 input 초기화
111
+ const input = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#file-input');
112
+ if (input)
113
+ input.value = '';
114
+ }
115
+ async _uploadFile() {
116
+ var _a;
117
+ if (!this.selectedFile)
118
+ return;
119
+ try {
120
+ const response = await client.mutate({
121
+ mutation: gql `
122
+ mutation CreateAttachments($attachments: [NewAttachment!]!) {
123
+ createAttachments(attachments: $attachments) {
124
+ id
125
+ name
126
+ fullpath
127
+ creator {
128
+ id
129
+ name
130
+ email
131
+ }
132
+ createdAt
133
+ }
134
+ }
135
+ `,
136
+ variables: {
137
+ attachments: [
138
+ {
139
+ file: this.selectedFile,
140
+ refBy: this.checklistId,
141
+ refType: 'Checklist_NameList'
142
+ }
143
+ ]
144
+ },
145
+ context: {
146
+ hasUpload: true
147
+ }
148
+ });
149
+ if (response.errors) {
150
+ throw new Error(((_a = response.errors[0]) === null || _a === void 0 ? void 0 : _a.message) || '업로드에 실패했습니다.');
151
+ }
152
+ const uploadedAttachment = response.data.createAttachments[0];
153
+ // 부모 컴포넌트에 업로드 완료 이벤트 전달
154
+ this.dispatchEvent(new CustomEvent('name-list-uploaded', {
155
+ detail: { attachment: uploadedAttachment },
156
+ bubbles: true
157
+ }));
158
+ notify({ message: '실명부가 성공적으로 업로드되었습니다.', level: 'info' });
159
+ this._close();
160
+ }
161
+ catch (error) {
162
+ console.error('업로드 오류:', error);
163
+ }
164
+ }
165
+ _formatFileSize(bytes) {
166
+ if (bytes === 0)
167
+ return '0 Bytes';
168
+ const k = 1024;
169
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
170
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
171
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
172
+ }
173
+ _close() {
174
+ this.dispatchEvent(new CustomEvent('popup-close', { bubbles: true }));
175
+ history.back();
176
+ }
177
+ };
178
+ NameListUploadPopup.styles = [
179
+ ButtonContainerStyles,
180
+ ScrollbarStyles,
181
+ css `
182
+ :host {
183
+ display: flex;
184
+ flex-direction: column;
185
+ background-color: #fff;
186
+ width: 100%;
187
+ overflow-y: auto;
188
+ }
189
+
190
+ div[body] {
191
+ flex: 1;
192
+ padding: 20px;
193
+ display: flex;
194
+ flex-direction: column;
195
+ gap: 20px;
196
+ }
197
+
198
+ div[upload-area] {
199
+ border: 2px dashed #ddd;
200
+ border-radius: 8px;
201
+ padding: 40px 20px;
202
+ text-align: center;
203
+ background-color: #fafafa;
204
+ transition: all 0.2s ease;
205
+ cursor: pointer;
206
+ }
207
+
208
+ div[upload-area]:hover {
209
+ border-color: #2196f3;
210
+ background-color: #f5f9ff;
211
+ }
212
+
213
+ div[upload-area].drag-over {
214
+ border-color: #2196f3;
215
+ background-color: #e3f2fd;
216
+ }
217
+
218
+ div[upload-icon] {
219
+ margin-bottom: 16px;
220
+ }
221
+
222
+ div[upload-icon] md-icon {
223
+ --md-icon-size: 48px;
224
+ color: #999;
225
+ }
226
+
227
+ div[upload-text] {
228
+ color: #666;
229
+ margin-bottom: 16px;
230
+ }
231
+
232
+ div[upload-text] h3 {
233
+ margin: 0 0 8px 0;
234
+ color: #333;
235
+ font-size: 16px;
236
+ }
237
+
238
+ div[upload-text] p {
239
+ margin: 0;
240
+ font-size: 14px;
241
+ color: #666;
242
+ }
243
+
244
+ div[file-preview] {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 12px;
248
+ padding: 12px;
249
+ background-color: #f7f7f7;
250
+ border-radius: 6px;
251
+ border: 1px solid #ddd;
252
+ }
253
+
254
+ div[file-preview] div[file-icon] {
255
+ display: flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ width: 40px;
259
+ height: 40px;
260
+ border-radius: 8px;
261
+ background-color: #e3f2fd;
262
+ }
263
+
264
+ div[file-preview] div[file-icon] md-icon {
265
+ --md-icon-size: 24px;
266
+ color: #2196f3;
267
+ }
268
+
269
+ div[file-preview] div[file-info] {
270
+ flex: 1;
271
+ }
272
+
273
+ div[file-preview] div[file-info] span {
274
+ display: block;
275
+ font-size: 14px;
276
+ font-weight: 500;
277
+ color: #333;
278
+ }
279
+
280
+ div[file-preview] div[file-info] small {
281
+ font-size: 12px;
282
+ color: #666;
283
+ }
284
+
285
+ div[remove-button] {
286
+ cursor: pointer;
287
+ padding: 4px;
288
+ border-radius: 4px;
289
+ transition: background-color 0.2s;
290
+ }
291
+
292
+ div[remove-button]:hover {
293
+ background-color: rgba(244, 67, 54, 0.1);
294
+ }
295
+
296
+ div[remove-button] md-icon {
297
+ --md-icon-size: 20px;
298
+ color: #f44336;
299
+ }
300
+
301
+ div[button-container] {
302
+ display: flex;
303
+ align-items: center;
304
+ justify-content: flex-end;
305
+ gap: 10px;
306
+ padding: 20px;
307
+ border-top: 1px solid #eee;
308
+ }
309
+
310
+ input[type='file'] {
311
+ display: none;
312
+ }
313
+ `
314
+ ];
315
+ __decorate([
316
+ property({ type: String }),
317
+ __metadata("design:type", String)
318
+ ], NameListUploadPopup.prototype, "checklistId", void 0);
319
+ __decorate([
320
+ state(),
321
+ __metadata("design:type", Object)
322
+ ], NameListUploadPopup.prototype, "selectedFile", void 0);
323
+ NameListUploadPopup = __decorate([
324
+ customElement('name-list-upload-popup')
325
+ ], NameListUploadPopup);
326
+ export { NameListUploadPopup };
327
+ //# sourceMappingURL=name-list-upload-popup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name-list-upload-popup.js","sourceRoot":"","sources":["../../../../../client/pages/building-inspection/component/inspection-document/name-list-upload-popup.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,yCAAyC,CAAA;AAChD,OAAO,yCAAyC,CAAA;AAChD,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAGjC,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,UAAU;IAA5C;;QA2IuB,gBAAW,GAAW,EAAE,CAAA;QAC3C,iBAAY,GAAgB,IAAI,CAAA;IA4K3C,CAAC;IA1KC,MAAM;QACJ,OAAO,IAAI,CAAA;;;;mBAII,IAAI,CAAC,WAAW;kBACjB,IAAI,CAAC,WAAW;sBACZ,IAAI,CAAC,eAAe;uBACnB,IAAI,CAAC,gBAAgB;;YAEhC,CAAC,IAAI,CAAC,YAAY;YAClB,CAAC,CAAC,IAAI,CAAA;;;;;;;;eAQH;YACH,CAAC,CAAC,IAAI,CAAA;;;;;;4BAMU,IAAI,CAAC,YAAY,CAAC,IAAI;6BACrB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;;8CAE3B,IAAI,CAAC,WAAW;;;;eAI/C;;;8FAG+E,IAAI,CAAC,iBAAiB;;;;qCAI/E,IAAI,CAAC,MAAM;;KAE3C,CAAA;IACH,CAAC;IAEO,WAAW;;QACjB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,aAAa,CAAqB,CAAA;QAC/E,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,EAAE,CAAA;IAChB,CAAC;IAEO,iBAAiB,CAAC,CAAQ;;QAChC,MAAM,KAAK,GAAG,CAAC,CAAC,MAA0B,CAAA;QAC1C,MAAM,IAAI,GAAG,MAAA,KAAK,CAAC,KAAK,0CAAG,CAAC,CAAC,CAAA;QAC7B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAC1B,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,CAAY;;QAC9B,CAAC,CAAC,cAAc,EAAE,CAAA;QAClB,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,oBAAoB,EAAE,CAAA;QAE3B,MAAM,IAAI,GAAG,MAAA,MAAA,CAAC,CAAC,YAAY,0CAAE,KAAK,0CAAG,CAAC,CAAC,CAAA;QACvC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAC1B,CAAC;IACH,CAAC;IAEO,eAAe,CAAC,CAAY;QAClC,CAAC,CAAC,cAAc,EAAE,CAAA;QAClB,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,iBAAiB,EAAE,CAAA;IAC1B,CAAC;IAEO,gBAAgB,CAAC,CAAY;QACnC,CAAC,CAAC,cAAc,EAAE,CAAA;QAClB,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,oBAAoB,EAAE,CAAA;IAC7B,CAAC;IAEO,iBAAiB;;QACvB,MAAM,UAAU,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAA;QAClE,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAEO,oBAAoB;;QAC1B,MAAM,UAAU,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAA;QAClE,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC3C,CAAC;IAEO,WAAW,CAAC,CAAQ;;QAC1B,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAExB,eAAe;QACf,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,UAAU,0CAAE,aAAa,CAAC,aAAa,CAAqB,CAAA;QAC/E,IAAI,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,EAAE,CAAA;IAC7B,CAAC;IAEO,KAAK,CAAC,WAAW;;QACvB,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAM;QAE9B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;;;;;;;;SAcZ;gBACD,SAAS,EAAE;oBACT,WAAW,EAAE;wBACX;4BACE,IAAI,EAAE,IAAI,CAAC,YAAY;4BACvB,KAAK,EAAE,IAAI,CAAC,WAAW;4BACvB,OAAO,EAAE,oBAAoB;yBAC9B;qBACF;iBACF;gBACD,OAAO,EAAE;oBACP,SAAS,EAAE,IAAI;iBAChB;aACF,CAAC,CAAA;YAEF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,CAAA,MAAA,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,0CAAE,OAAO,KAAI,cAAc,CAAC,CAAA;YAChE,CAAC;YAED,MAAM,kBAAkB,GAAG,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAA;YAE7D,yBAAyB;YACzB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,oBAAoB,EAAE;gBACpC,MAAM,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE;gBAC1C,OAAO,EAAE,IAAI;aACd,CAAC,CACH,CAAA;YAED,MAAM,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;YAC1D,IAAI,CAAC,MAAM,EAAE,CAAA;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAEO,eAAe,CAAC,KAAa;QACnC,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA;QAEjC,MAAM,CAAC,GAAG,IAAI,CAAA;QACd,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAEnD,OAAO,UAAU,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACzE,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACrE,OAAO,CAAC,IAAI,EAAE,CAAA;IAChB,CAAC;;AAtTM,0BAAM,GAAG;IACd,qBAAqB;IACrB,eAAe;IACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoIF;CACF,AAxIY,CAwIZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wDAAyB;AAC3C;IAAR,KAAK,EAAE;;yDAAiC;AA5I9B,mBAAmB;IAD/B,aAAa,CAAC,wBAAwB,CAAC;GAC3B,mBAAmB,CAwT/B","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/button/outlined-button.js'\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 } from '@operato/layout'\n\n@customElement('name-list-upload-popup')\nexport class NameListUploadPopup extends 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 overflow-y: auto;\n }\n\n div[body] {\n flex: 1;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n }\n\n div[upload-area] {\n border: 2px dashed #ddd;\n border-radius: 8px;\n padding: 40px 20px;\n text-align: center;\n background-color: #fafafa;\n transition: all 0.2s ease;\n cursor: pointer;\n }\n\n div[upload-area]:hover {\n border-color: #2196f3;\n background-color: #f5f9ff;\n }\n\n div[upload-area].drag-over {\n border-color: #2196f3;\n background-color: #e3f2fd;\n }\n\n div[upload-icon] {\n margin-bottom: 16px;\n }\n\n div[upload-icon] md-icon {\n --md-icon-size: 48px;\n color: #999;\n }\n\n div[upload-text] {\n color: #666;\n margin-bottom: 16px;\n }\n\n div[upload-text] h3 {\n margin: 0 0 8px 0;\n color: #333;\n font-size: 16px;\n }\n\n div[upload-text] p {\n margin: 0;\n font-size: 14px;\n color: #666;\n }\n\n div[file-preview] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background-color: #f7f7f7;\n border-radius: 6px;\n border: 1px solid #ddd;\n }\n\n div[file-preview] div[file-icon] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n background-color: #e3f2fd;\n }\n\n div[file-preview] div[file-icon] md-icon {\n --md-icon-size: 24px;\n color: #2196f3;\n }\n\n div[file-preview] div[file-info] {\n flex: 1;\n }\n\n div[file-preview] div[file-info] span {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: #333;\n }\n\n div[file-preview] div[file-info] small {\n font-size: 12px;\n color: #666;\n }\n\n div[remove-button] {\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: background-color 0.2s;\n }\n\n div[remove-button]:hover {\n background-color: rgba(244, 67, 54, 0.1);\n }\n\n div[remove-button] md-icon {\n --md-icon-size: 20px;\n color: #f44336;\n }\n\n div[button-container] {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 20px;\n border-top: 1px solid #eee;\n }\n\n input[type='file'] {\n display: none;\n }\n `\n ]\n\n @property({ type: String }) checklistId: string = ''\n @state() selectedFile: File | null = null\n\n render() {\n return html`\n <div body>\n <div\n upload-area\n @click=${this._selectFile}\n @drop=${this._handleDrop}\n @dragover=${this._handleDragOver}\n @dragleave=${this._handleDragLeave}\n >\n ${!this.selectedFile\n ? html`\n <div upload-icon>\n <md-icon>cloud_upload</md-icon>\n </div>\n <div upload-text>\n <h3>실명부 파일 업로드</h3>\n <p>파일을 클릭하거나 드래그하여 업로드하세요</p>\n </div>\n `\n : html`\n <div file-preview>\n <div file-icon>\n <md-icon>description</md-icon>\n </div>\n <div file-info>\n <span>${this.selectedFile.name}</span>\n <small>${this._formatFileSize(this.selectedFile.size)}</small>\n </div>\n <div remove-button @click=${this._removeFile}>\n <md-icon>close</md-icon>\n </div>\n </div>\n `}\n </div>\n\n <input type=\"file\" id=\"file-input\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" @change=${this._handleFileSelect} />\n </div>\n\n <div button-container>\n <md-outlined-button @click=${this._close}>닫기</md-outlined-button>\n </div>\n `\n }\n\n private _selectFile() {\n if (this.selectedFile) return\n const input = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement\n input?.click()\n }\n\n private _handleFileSelect(e: Event) {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (file) {\n this.selectedFile = file\n }\n }\n\n private _handleDrop(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n this._removeDragOverClass()\n\n const file = e.dataTransfer?.files?.[0]\n if (file) {\n this.selectedFile = file\n }\n }\n\n private _handleDragOver(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n this._addDragOverClass()\n }\n\n private _handleDragLeave(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n this._removeDragOverClass()\n }\n\n private _addDragOverClass() {\n const uploadArea = this.shadowRoot?.querySelector('[upload-area]')\n uploadArea?.classList.add('drag-over')\n }\n\n private _removeDragOverClass() {\n const uploadArea = this.shadowRoot?.querySelector('[upload-area]')\n uploadArea?.classList.remove('drag-over')\n }\n\n private _removeFile(e: Event) {\n e.stopPropagation()\n this.selectedFile = null\n\n // 파일 input 초기화\n const input = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement\n if (input) input.value = ''\n }\n\n private async _uploadFile() {\n if (!this.selectedFile) return\n\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation CreateAttachments($attachments: [NewAttachment!]!) {\n createAttachments(attachments: $attachments) {\n id\n name\n fullpath\n creator {\n id\n name\n email\n }\n createdAt\n }\n }\n `,\n variables: {\n attachments: [\n {\n file: this.selectedFile,\n refBy: this.checklistId,\n refType: 'Checklist_NameList'\n }\n ]\n },\n context: {\n hasUpload: true\n }\n })\n\n if (response.errors) {\n throw new Error(response.errors[0]?.message || '업로드에 실패했습니다.')\n }\n\n const uploadedAttachment = response.data.createAttachments[0]\n\n // 부모 컴포넌트에 업로드 완료 이벤트 전달\n this.dispatchEvent(\n new CustomEvent('name-list-uploaded', {\n detail: { attachment: uploadedAttachment },\n bubbles: true\n })\n )\n\n notify({ message: '실명부가 성공적으로 업로드되었습니다.', level: 'info' })\n this._close()\n } catch (error) {\n console.error('업로드 오류:', error)\n }\n }\n\n private _formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes'\n\n const k = 1024\n const sizes = ['Bytes', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]\n }\n\n private _close() {\n this.dispatchEvent(new CustomEvent('popup-close', { bubbles: true }))\n history.back()\n }\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import '@material/web/button/elevated-button.js';
2
+ import '@material/web/icon/icon.js';
3
+ import '@material/web/tabs/tabs.js';
4
+ import '@material/web/tabs/primary-tab.js';
5
+ import { LitElement } from 'lit';
6
+ import '../image-preview-popup';
7
+ export declare enum PhotoTab {
8
+ CONSTRUCTOR = "constructor",
9
+ SUPERVISOR = "supervisor"
10
+ }
11
+ export declare class PhotoAlbumPopup extends LitElement {
12
+ static styles: import("lit").CSSResult[];
13
+ checklistId: string;
14
+ activeTab: PhotoTab;
15
+ constructorFiles: any[];
16
+ supervisorFiles: any[];
17
+ render(): import("lit-html").TemplateResult<1>;
18
+ firstUpdated(): Promise<void>;
19
+ private _loadPhotos;
20
+ private _isImageFile;
21
+ private _getFileExtension;
22
+ private _setActiveTab;
23
+ private _openFilePreview;
24
+ private _onImageError;
25
+ private _formatDate;
26
+ private _close;
27
+ }