관리자 기능과 계정 즐겨찾기 개선
This commit is contained in:
@@ -165,6 +165,23 @@ const UaDeckApi = (() => {
|
||||
|
||||
getPresets: () => request('/decks/presets'),
|
||||
|
||||
getFavorites: () => request('/decks/favorites'),
|
||||
|
||||
/** @param {string[]} shareCodes */
|
||||
syncFavorites: (shareCodes) =>
|
||||
request('/decks/favorites', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ shareCodes }),
|
||||
}),
|
||||
|
||||
/** @param {string} shareCode */
|
||||
addFavorite: (shareCode) =>
|
||||
request(`/decks/favorites/${shareCode}`, { method: 'PUT' }),
|
||||
|
||||
/** @param {string} shareCode */
|
||||
removeFavorite: (shareCode) =>
|
||||
request(`/decks/favorites/${shareCode}`, { method: 'DELETE' }),
|
||||
|
||||
/** 관리자: 회원 목록 */
|
||||
adminGetUsers: (q = '', page = 1) =>
|
||||
request(`/admin/users?q=${encodeURIComponent(q)}&page=${page}`),
|
||||
@@ -185,6 +202,11 @@ const UaDeckApi = (() => {
|
||||
|
||||
adminGetDecks: () => request('/admin/decks'),
|
||||
|
||||
adminGetOrphanPreviews: () => request('/admin/previews/orphans'),
|
||||
|
||||
adminDeleteOrphanPreviews: () =>
|
||||
request('/admin/previews/orphans', { method: 'DELETE' }),
|
||||
|
||||
/** @param {object} body */
|
||||
adminCreatePreset: (body) =>
|
||||
request('/admin/decks/preset', { method: 'POST', body: JSON.stringify(body) }),
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
/**
|
||||
* 덱 즐겨찾기 (localStorage, share_code 기준)
|
||||
* 덱 즐겨찾기
|
||||
* 로그인 사용자는 계정 DB, 비로그인 사용자는 localStorage를 사용한다.
|
||||
*/
|
||||
(function initDeckFavorites() {
|
||||
const STORAGE_KEY = 'uadeck.deckFavorites';
|
||||
/** @type {Set<string>} */
|
||||
let favorites = new Set();
|
||||
/** @type {Promise<void>|null} */
|
||||
let initPromise = null;
|
||||
|
||||
/**
|
||||
* 브라우저 즐겨찾기 읽기
|
||||
* @returns {Set<string>}
|
||||
*/
|
||||
function readSet() {
|
||||
function readLocalSet() {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
const list = raw ? JSON.parse(raw) : [];
|
||||
@@ -18,43 +24,87 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 브라우저 즐겨찾기 저장
|
||||
* @param {Set<string>} set
|
||||
*/
|
||||
function writeSet(set) {
|
||||
function writeLocalSet(set) {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify([...set]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 즐겨찾기 초기화 및 기존 브라우저 데이터 이전
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function init() {
|
||||
if (initPromise) return initPromise;
|
||||
initPromise = (async () => {
|
||||
const localFavorites = readLocalSet();
|
||||
if (!UaDeckApi.getToken()) {
|
||||
favorites = localFavorites;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = localFavorites.size
|
||||
? await UaDeckApi.syncFavorites([...localFavorites])
|
||||
: await UaDeckApi.getFavorites();
|
||||
favorites = new Set(data.favorites || []);
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
} catch (err) {
|
||||
favorites = localFavorites;
|
||||
console.warn('[favorites] 계정 즐겨찾기 동기화 실패', err);
|
||||
}
|
||||
})();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} shareCode
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isFavorite(shareCode) {
|
||||
if (!shareCode) return false;
|
||||
return readSet().has(shareCode);
|
||||
return Boolean(shareCode) && favorites.has(shareCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 즐겨찾기 상태 변경
|
||||
* @param {string} shareCode
|
||||
* @returns {boolean} 토글 후 즐겨찾기 여부
|
||||
* @returns {Promise<boolean>} 변경 후 즐겨찾기 여부
|
||||
*/
|
||||
function toggle(shareCode) {
|
||||
async function toggle(shareCode) {
|
||||
if (!shareCode) return false;
|
||||
const set = readSet();
|
||||
if (set.has(shareCode)) {
|
||||
set.delete(shareCode);
|
||||
} else {
|
||||
set.add(shareCode);
|
||||
await init();
|
||||
const next = !favorites.has(shareCode);
|
||||
|
||||
if (UaDeckApi.getToken()) {
|
||||
if (next) {
|
||||
await UaDeckApi.addFavorite(shareCode);
|
||||
} else {
|
||||
await UaDeckApi.removeFavorite(shareCode);
|
||||
}
|
||||
}
|
||||
writeSet(set);
|
||||
return set.has(shareCode);
|
||||
|
||||
if (next) favorites.add(shareCode);
|
||||
else favorites.delete(shareCode);
|
||||
if (!UaDeckApi.getToken()) writeLocalSet(favorites);
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* 삭제된 덱을 현재 화면 상태에서도 제거
|
||||
* @param {string} shareCode
|
||||
*/
|
||||
function forget(shareCode) {
|
||||
favorites.delete(shareCode);
|
||||
if (!UaDeckApi.getToken()) writeLocalSet(favorites);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getAll() {
|
||||
return [...readSet()];
|
||||
return [...favorites];
|
||||
}
|
||||
|
||||
window.UaDeckFavorites = { isFavorite, toggle, getAll };
|
||||
window.UaDeckFavorites = { init, isFavorite, toggle, forget, getAll };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user