refactor(js): app.js 를 브라우저 네이티브 ESM 모듈로 분할
public/js/{util,ui,reactions,modals,comments,feed,main}.js 로 분리하고
dashboard/project 에서 <script type="module" src="/public/js/main.js"> 로 로드.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
35
public/js/reactions.js
Normal file
35
public/js/reactions.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// ❤️ 좋아요 / ⭐ 즐겨찾기 — fetch 로 토글하고 카운트를 즉시 반영(점진적 향상).
|
||||
import { $, $$, toast, burstSparkle } from "./util.js";
|
||||
|
||||
let starTaps = [];
|
||||
|
||||
function syncReaction(id, kind, on, count) {
|
||||
$$('[data-react][data-id="' + id + '"][data-kind="' + kind + '"]').forEach((b) => {
|
||||
b.classList.toggle("on", !!on);
|
||||
const c = $(".count", b);
|
||||
if (c) c.textContent = count;
|
||||
});
|
||||
}
|
||||
|
||||
export function initReactions() {
|
||||
document.addEventListener("click", (e) => {
|
||||
const btn = e.target.closest("[data-react]");
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const id = btn.getAttribute("data-id");
|
||||
const kind = btn.getAttribute("data-kind"); // heart | star
|
||||
if (kind === "star") {
|
||||
starTaps = starTaps.filter((t) => Date.now() - t < 1400);
|
||||
starTaps.push(Date.now());
|
||||
if (starTaps.length >= 4) burstSparkle(e.clientX, e.clientY);
|
||||
}
|
||||
fetch("/projects/" + id + "/" + kind, {
|
||||
method: "POST",
|
||||
headers: { "X-Requested-With": "fetch", "Accept": "application/json" },
|
||||
})
|
||||
.then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
|
||||
.then((data) => syncReaction(id, kind, data.on, data.count))
|
||||
.catch(() => toast("처리에 실패했습니다. 다시 시도해 주세요."));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user