diff --git a/app/public/scripts/fetch-prompts.js b/app/public/scripts/fetch-prompts.js new file mode 100644 index 0000000..72573da --- /dev/null +++ b/app/public/scripts/fetch-prompts.js @@ -0,0 +1,108 @@ +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 => + `${tag}` + ).join(''); + + return ` +
+
+

${prompt.title}

+ ${prompt.type} +
+

${prompt.notes ?? ''}

+
${tagSpans}
+
+ `; +} + +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 = ` + + ${tag} + `; + 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); diff --git a/app/src/pages/index.astro b/app/src/pages/index.astro index a5604eb..e35f08e 100644 --- a/app/src/pages/index.astro +++ b/app/src/pages/index.astro @@ -1,35 +1,37 @@ --- +// index.astro import MainLayout from '../layouts/MainLayout.astro'; import SearchBar from '../components/SearchBar.astro'; -import FilteredPromptList from '../components/FilteredPromptList.astro'; -import { supabase } from '../lib/supabase'; -const { data: prompts, error } = await supabase - .from('prompts') - .select('*') - .order('title', { ascending: true }); - -const allTags = Array.from( - new Set( - prompts?.flatMap((p) => p.tags ?? []) - ) -).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); +const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL; +const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY; --- + +

Prompt Catalog

Save and explore AI prompts

- + -
+
- {error - ?

Supabase error: {error.message}

- : } + +
+

+ Filters ↓ +
+ +
Loading prompts…
@@ -37,4 +39,6 @@ const allTags = Array.from( + +
diff --git a/app/src/scripts/fetch-prompts.js b/app/src/scripts/fetch-prompts.js deleted file mode 100644 index 6e780d0..0000000 --- a/app/src/scripts/fetch-prompts.js +++ /dev/null @@ -1,18 +0,0 @@ -// app/src/scripts/fetch-prompts.js -import { createClient } from '@supabase/supabase-js'; - -const supabase = createClient(import.meta.env.PUBLIC_SUPABASE_URL, import.meta.env.PUBLIC_SUPABASE_ANON_KEY); - -async function loadPrompts() { - const { data, error } = await supabase.from('prompts').select('*'); - if (error) { - console.error(error); - return; - } - - // Now render them in the DOM - const container = document.getElementById('prompt-list'); - container.innerHTML = data.map(prompt => `
  • ${prompt.title}
  • `).join(''); -} - -document.addEventListener('DOMContentLoaded', loadPrompts);