Files
PromptBase/app/public/scripts/fetch-prompts.js

109 lines
3.8 KiB
JavaScript

import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
const env = document.getElementById('supabase-env');
const supabaseUrl = env.dataset.url;
const supabaseKey = env.dataset.key;
const supabase = createClient(supabaseUrl, supabaseKey);
const promptContainer = document.getElementById('prompt-container');
const errorBox = document.getElementById('prompt-error');
function renderPromptCard(prompt) {
const tagSpans = (prompt.tags ?? []).map(tag =>
`<span class="text-sm bg-gray-200 text-gray-800 px-2 py-1 pt-0 rounded">${tag}</span>`
).join('');
return `
<div class="prompt-card border border-gray-400 rounded p-4 bg-gray-700 text-gray-200 shadow-sm flex flex-col gap-2 min-h-[12rem]"
data-type="${prompt.type}" data-tags="${(prompt.tags ?? []).join(',')}">
<div class="flex items-center justify-between">
<h3 class="text-xl font-semibold">${prompt.title}</h3>
<span class="text-sm font-medium px-2 py-1 rounded ${
prompt.type === 'System'
? 'bg-blue-100 text-blue-700'
: 'bg-green-100 text-green-700'
}">${prompt.type}</span>
</div>
<p class="text-md">${prompt.notes ?? ''}</p>
<div class="flex flex-wrap gap-2 mt-2">${tagSpans}</div>
</div>
`;
}
function updateFiltersFromTags(prompts) {
const tagSet = new Set(prompts.flatMap(p => p.tags ?? []));
const tagContainer = document.querySelector('#filters fieldset > div');
if (!tagContainer) return;
tagContainer.innerHTML = '';
tagSet.forEach(tag => {
const label = document.createElement('label');
label.className = "relative inline-flex items-center cursor-pointer";
label.innerHTML = `
<input type="checkbox" name="tag" value="${tag}" class="sr-only peer">
<span class="px-3 py-1 pt-0 rounded-full border border-gray-300 peer-checked:bg-blue-600 peer-checked:text-white hover:bg-blue-600 hover:text-white transition-colors duration-300 text-sm">${tag}</span>
`;
tagContainer.appendChild(label);
});
}
function filterCards() {
const form = document.getElementById('filter-form');
const cards = document.querySelectorAll('.prompt-card');
const params = new URLSearchParams(new FormData(form));
const type = params.get('type');
const query = params.get('q')?.toLowerCase() || '';
const tagParams = params.getAll('tag');
let visibleCount = 0;
cards.forEach(card => {
const cardType = card.dataset.type;
const cardTags = card.dataset.tags.split(',');
const cardText = card.innerText.toLowerCase();
const matchesType = !type || type === cardType;
const matchesTags = tagParams.length === 0 || tagParams.some(t => cardTags.includes(t));
const matchesSearch = !query || cardText.includes(query);
const show = matchesType && matchesTags && matchesSearch;
card.style.display = show ? 'block' : 'none';
if (show) visibleCount++;
});
const countLabel = document.getElementById('prompt-count');
if (countLabel) {
countLabel.textContent = visibleCount === 1
? '1 prompt shown'
: `${visibleCount} prompts shown`;
}
}
async function loadPrompts() {
const { data: prompts, error } = await supabase.from('prompts').select('*').order('title');
if (error) {
promptContainer.innerHTML = '';
errorBox.textContent = error.message;
errorBox.classList.remove('hidden');
return;
}
promptContainer.innerHTML = prompts.map(renderPromptCard).join('');
updateFiltersFromTags(prompts);
filterCards(); // initial run
const form = document.getElementById('filter-form');
form?.addEventListener('input', filterCards);
const clearBtn = document.getElementById('clear-filters');
clearBtn?.addEventListener('click', () => {
form.reset();
filterCards();
});
}
document.addEventListener('DOMContentLoaded', loadPrompts);