Files
jsahn 4e943700fc feat: add common utilities and feedback handling scripts
- Introduced common.js for shared functions including API calls, error reporting, and UI helpers.
- Implemented feedback.js for the feedback reporting page, including form handling and displaying feedback status.
- Added layout.js for managing galaxy and section layouts in the visualization.
- Created login.js for user authentication with session management.
- Developed search.js for term searching based on user input and synonyms.
- Implemented signup.js for user registration with validation and immediate login.
2026-10-06 23:14:45 +09:00

39 lines
2.5 KiB
JavaScript

// 회원 가입: 수업에서 받은 가입 코드가 있어야 함. 가입하면 바로 이용.
import { api, toast } from "./common.js";
const main = document.getElementById("main");
const next = new URLSearchParams(location.search).get("next") || "";
const safe = (u) => (u && u.startsWith("/") && !u.startsWith("//") ? u : "");
main.innerHTML = `<h1>회원 가입</h1>
<p class="acc-note">수업에서 교수자에게 받은 <b>가입 코드</b>가 있어야 가입할 수 있습니다. 가입하면 바로 사례와 문제를 볼 수 있어요.</p>
<form class="card" id="f">
<label class="field"><span>가입 코드</span><input class="input" name="code" required maxlength="40" autocomplete="off" placeholder="예: K7P-2QX" style="text-transform:uppercase"></label>
<label class="field"><span>아이디 (영문·숫자 3~30자)</span><input class="input" name="username" autocomplete="username" required minlength="3" maxlength="30" pattern="[A-Za-z0-9_.\\-]{3,30}"></label>
<label class="field"><span>비밀번호 (6자 이상)</span><input class="input" name="password" type="password" autocomplete="new-password" required minlength="6"></label>
<label class="field"><span>비밀번호 확인</span><input class="input" name="password2" type="password" autocomplete="new-password" required minlength="6"></label>
<label class="field"><span>이름</span><input class="input" name="name" required maxlength="40"></label>
<label class="field"><span>학번 (선택)</span><input class="input" name="student_no" maxlength="30"></label>
<input class="hp" name="website" tabindex="-1" autocomplete="off" aria-hidden="true">
<button class="btn primary" type="submit">가입하기</button>
</form>
<p class="auth-alt">이미 회원인가요? <a href="/login${next ? "?next=" + encodeURIComponent(next) : ""}">로그인</a></p>`;
document.getElementById("f").addEventListener("submit", async (e) => {
e.preventDefault();
const v = Object.fromEntries(new FormData(e.target).entries());
if (v.password !== v.password2) return toast("비밀번호 확인이 일치하지 않습니다.", true);
delete v.password2;
const btn = e.target.querySelector("button");
btn.disabled = true;
try {
await api("/api/members/signup", { method: "POST", body: v });
await api("/api/members/login", { method: "POST", body: { username: v.username, password: v.password } });
toast("가입했습니다!");
location.href = safe(next) || "/";
} catch (err) {
toast(err.message, true);
btn.disabled = false;
}
});