/* Local interaction preview: no requests, uploads, or storage. */ (() => { 'use strict'; const form = document.querySelector('.inquiry-form'); if (!form) return; const message = form.elements.message; const counter = form.querySelector('[data-message-count]'); const input = form.elements.attachments; const dropzone = form.querySelector('.inquiry-upload'); const list = form.querySelector('.inquiry-files'); const uploadStatus = form.querySelector('.inquiry-upload-status'); const dialog = document.querySelector('#inquiry-success-dialog'); const submitButton = form.querySelector('.inquiry-submit'); submitButton.disabled = false; const maxFiles = 5; const maxBytes = 20 * 1024 * 1024; let files = []; let dragDepth = 0; function formatSize(size) { return size >= 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(1)} MB` : `${Math.max(1, Math.ceil(size / 1024))} KB`; } function showFiles() { list.replaceChildren(); files.forEach((file, index) => { const item = document.createElement('li'); const name = document.createElement('span'); name.className = 'inquiry-file-name'; name.textContent = file.name; const size = document.createElement('span'); size.className = 'inquiry-file-size'; size.textContent = formatSize(file.size); const remove = document.createElement('button'); remove.type = 'button'; remove.className = 'inquiry-file-remove'; remove.textContent = '×'; remove.setAttribute('aria-label', `${file.name} 삭제`); remove.addEventListener('click', () => { files.splice(index, 1); showFiles(); const next = list.querySelectorAll('button')[Math.min(index, files.length - 1)]; (next || input).focus(); }); item.append(name, size, remove); list.append(item); }); uploadStatus.classList.remove('is-error'); uploadStatus.textContent = files.length ? `${files.length}개 선택 · 총 ${formatSize(files.reduce((sum, file) => sum + file.size, 0))}` : ''; } function addFiles(selection) { const next = [...files]; for (const file of selection) { if (!next.some(existing => existing.name === file.name && existing.size === file.size && existing.lastModified === file.lastModified)) next.push(file); } let error = ''; if (next.length > maxFiles) error = '파일은 최대 5개까지 첨부할 수 있습니다.'; else if (next.reduce((sum, file) => sum + file.size, 0) > maxBytes) error = '첨부파일의 총 용량은 20MB 이하여야 합니다.'; input.value = ''; if (error) { uploadStatus.textContent = error; uploadStatus.classList.add('is-error'); return; } files = next; showFiles(); } input.addEventListener('change', () => addFiles([...input.files])); dropzone.addEventListener('dragenter', event => { event.preventDefault(); dragDepth++; dropzone.classList.add('is-dragging'); }); dropzone.addEventListener('dragover', event => { event.preventDefault(); event.dataTransfer.dropEffect = 'copy'; }); dropzone.addEventListener('dragleave', () => { if (--dragDepth <= 0) dropzone.classList.remove('is-dragging'); }); dropzone.addEventListener('drop', event => { event.preventDefault(); dragDepth = 0; dropzone.classList.remove('is-dragging'); addFiles([...event.dataTransfer.files]); }); // Avoid navigating away if a file is dropped just outside the attachment area. for (const type of ['dragover', 'drop']) { form.addEventListener(type, event => { if ([...event.dataTransfer.types].includes('Files')) event.preventDefault(); }); } form.addEventListener('input', event => { if (event.target.matches('input, textarea')) event.target.setCustomValidity(''); counter.textContent = message.value.length.toLocaleString('ko-KR'); }); dialog.querySelectorAll('[data-close-inquiry]').forEach(button => { button.addEventListener('click', () => dialog.close()); }); let backdropPressed = false; function isBackdrop(event) { const bounds = dialog.getBoundingClientRect(); return event.target === dialog && (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom); } dialog.addEventListener('pointerdown', event => { backdropPressed = isBackdrop(event); }); dialog.addEventListener('click', event => { if (backdropPressed && isBackdrop(event)) dialog.close(); backdropPressed = false; }); dialog.addEventListener('close', () => { document.documentElement.classList.remove('inquiry-success-open'); submitButton.focus({ preventScroll: true }); }); form.addEventListener('submit', event => { event.preventDefault(); for (const field of [form.elements.name, message]) { field.setCustomValidity(field.value.trim() ? '' : '공백을 제외한 내용을 입력해 주세요.'); } if (!form.reportValidity()) return; if (!dialog.open) { dialog.showModal(); document.documentElement.classList.add('inquiry-success-open'); } }); })();