Improve guest upload flow
This commit is contained in:
+91
-5
@@ -22,21 +22,107 @@
|
||||
<form class="upload-panel" method="post" action="/r/{{slug}}" enctype="multipart/form-data">
|
||||
<p class="upload-panel__today">오늘의 순간</p>
|
||||
|
||||
<label class="upload-button file-picker" aria-label="업로드">
|
||||
<span>사진 올리기</span>
|
||||
<label class="select-button file-picker">
|
||||
<span>사진 선택하기</span>
|
||||
<input type="file" name="files" accept="{{accept}}" multiple required>
|
||||
</label>
|
||||
|
||||
<button class="submit-fallback" type="submit" aria-label="업로드">사진 올리기</button>
|
||||
<div class="file-summary" hidden>
|
||||
<p class="file-summary__title">선택한 파일</p>
|
||||
<ul class="file-list"></ul>
|
||||
</div>
|
||||
|
||||
<button class="upload-button" type="submit" aria-label="업로드">
|
||||
<span>업로드하기</span>
|
||||
</button>
|
||||
|
||||
<p class="upload-status" aria-live="polite"></p>
|
||||
</form>
|
||||
|
||||
<section class="thank-you" hidden>
|
||||
<p class="thank-you__eyebrow">THANK YOU</p>
|
||||
<h2>감사합니다</h2>
|
||||
<p>소중한 오늘을 함께 남겨주셔서 고마워요.</p>
|
||||
<a class="upload-again" href="/r/{{slug}}">사진 더 올리기</a>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
document.querySelectorAll(".upload-panel").forEach((form) => {
|
||||
const input = form.querySelector('input[type="file"][name="files"]');
|
||||
const submit = form.querySelector('button[type="submit"]');
|
||||
const submit = form.querySelector('button[type="submit"][aria-label="업로드"]');
|
||||
const summary = form.querySelector(".file-summary");
|
||||
const list = form.querySelector(".file-list");
|
||||
const status = form.querySelector(".upload-status");
|
||||
const thanks = document.querySelector(".thank-you");
|
||||
submit.disabled = true;
|
||||
|
||||
const formatBytes = (bytes) => {
|
||||
if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
||||
if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
|
||||
return `${bytes} B`;
|
||||
};
|
||||
|
||||
const setStatus = (message, type = "") => {
|
||||
status.textContent = message;
|
||||
status.dataset.type = type;
|
||||
};
|
||||
|
||||
input?.addEventListener("change", () => {
|
||||
if (input.files && input.files.length > 0) submit?.click();
|
||||
const files = Array.from(input.files || []);
|
||||
list.replaceChildren();
|
||||
|
||||
if (files.length === 0) {
|
||||
summary.hidden = true;
|
||||
submit.disabled = true;
|
||||
setStatus("");
|
||||
return;
|
||||
}
|
||||
|
||||
files.forEach((file) => {
|
||||
const item = document.createElement("li");
|
||||
const name = document.createElement("span");
|
||||
const size = document.createElement("span");
|
||||
name.textContent = file.name;
|
||||
size.textContent = formatBytes(file.size);
|
||||
item.append(name, size);
|
||||
list.append(item);
|
||||
});
|
||||
|
||||
summary.hidden = false;
|
||||
submit.disabled = false;
|
||||
setStatus(`${files.length}개 파일을 선택했어요.`);
|
||||
});
|
||||
|
||||
form.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
if (!input.files || input.files.length === 0) {
|
||||
setStatus("먼저 사진을 선택해 주세요.", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
submit.disabled = true;
|
||||
form.dataset.uploading = "true";
|
||||
setStatus("업로드 중이에요. 화면을 닫지 말아 주세요.");
|
||||
|
||||
try {
|
||||
const response = await fetch(form.action, {
|
||||
method: "POST",
|
||||
body: new FormData(form),
|
||||
headers: { "Accept": "application/json" }
|
||||
});
|
||||
const result = await response.json().catch(() => ({}));
|
||||
if (!response.ok || !result.ok) throw new Error(result.message || "업로드 중 오류가 났어요.");
|
||||
|
||||
form.hidden = true;
|
||||
thanks.hidden = false;
|
||||
thanks.querySelector("p:last-of-type").textContent =
|
||||
`${result.count || input.files.length}개 파일을 잘 받았어요. 소중한 오늘을 함께 남겨주셔서 고마워요.`;
|
||||
} catch (error) {
|
||||
submit.disabled = false;
|
||||
form.dataset.uploading = "false";
|
||||
setStatus(error.message || "업로드 중 오류가 났어요. 다시 시도해 주세요.", "error");
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user