Files
ai-dev-portal/public/js/reactions.js
2620227 2b74b59f81 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>
2026-06-29 17:53:46 +09:00

36 lines
1.3 KiB
JavaScript

// ❤️ 좋아요 / ⭐ 즐겨찾기 — 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("처리에 실패했습니다. 다시 시도해 주세요."));
});
}