Implement catalog CRUD overhaul, snapshot fallback activation, and billing/UX hardening
This commit is contained in:
@@ -218,6 +218,7 @@
|
||||
const state = { page: 1, limit: 32, total: 0, items: [], categories: {} };
|
||||
const userTier = @json($userTier ?? null);
|
||||
const isPersonal = userTier === 'personal';
|
||||
const isSignedIn = @json(auth()->check());
|
||||
const initialQuery = @json($initialQuery ?? '');
|
||||
const initialCategory = @json($initialCategory ?? '');
|
||||
const initialSubcategory = @json($initialSubcategory ?? '');
|
||||
@@ -456,7 +457,7 @@
|
||||
if (catEl.value) params.set('category', catEl.value);
|
||||
if (subEl.value) params.set('subcategory', subEl.value);
|
||||
|
||||
const endpoint = isPersonal ? '/dashboard/keywords/search' : '/v1/emojis';
|
||||
const endpoint = isSignedIn ? '/dashboard/keywords/search' : '/v1/emojis';
|
||||
const res = await fetch(endpoint + '?' + params.toString());
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
@@ -492,15 +493,10 @@
|
||||
</a>
|
||||
<div class="emoji-card-bar absolute bottom-0 left-0 right-0 border-t border-white/10 bg-black/20 px-2 py-1.5 flex items-start gap-1">
|
||||
<span class="emoji-name-clamp text-[10px] text-gray-300 text-left flex-1">${esc(item.name)}</span>
|
||||
${isPrivate ? `<span class="px-1.5 py-0.5 rounded bg-brand-ocean/20 text-[9px] text-brand-oceanSoft" title="${esc(item.matched_keyword || '')}">Your: ${esc(item.matched_keyword || '')}</span>` : ''}
|
||||
${isPrivate ? `<button type="button" class="edit-btn shrink-0 rounded bg-white/10 px-1.5 text-[9px] text-gray-200 hover:bg-brand-ocean/30">Edit</button>` : ''}
|
||||
${isPrivate ? `<button type="button" class="delete-btn shrink-0 rounded bg-white/10 px-1.5 text-[9px] text-gray-200 hover:bg-red-500/30">Del</button>` : ''}
|
||||
<button type="button" class="copy-btn shrink-0 w-6 h-6 rounded bg-white/10 hover:bg-brand-ocean/30 text-[11px] text-gray-200 hover:text-white transition-colors" title="Copy emoji">⧉</button>
|
||||
</div>
|
||||
`;
|
||||
const copyBtn = card.querySelector('.copy-btn');
|
||||
const editBtn = card.querySelector('.edit-btn');
|
||||
const deleteBtn = card.querySelector('.delete-btn');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
@@ -511,36 +507,6 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
if (editBtn && isPrivate) {
|
||||
editBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
openKeywordEdit(item);
|
||||
});
|
||||
}
|
||||
if (deleteBtn && isPrivate) {
|
||||
deleteBtn.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
if (!item.matched_keyword_id) return;
|
||||
const ok = await window.dewemojiConfirm('Delete this keyword?', {
|
||||
title: 'Delete keyword',
|
||||
okText: 'Delete',
|
||||
});
|
||||
if (!ok) return;
|
||||
const res = await fetch(`/dashboard/keywords/${item.matched_keyword_id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
...(csrf ? { 'X-CSRF-TOKEN': csrf } : {}),
|
||||
},
|
||||
});
|
||||
const data = await res.json().catch(() => null);
|
||||
if (!res.ok || !data?.ok) {
|
||||
showToast('Could not delete keyword');
|
||||
return;
|
||||
}
|
||||
fetchEmojis(true);
|
||||
});
|
||||
}
|
||||
card.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
navigator.clipboard.writeText(item.emoji).then(() => {
|
||||
|
||||
Reference in New Issue
Block a user