diff --git a/src/components/SlugInput.astro b/src/components/SlugInput.astro index 72ab64e..3ce3081 100644 --- a/src/components/SlugInput.astro +++ b/src/components/SlugInput.astro @@ -1,4 +1,5 @@ --- +import { getFeedMapping } from '../lib/db'; interface Props { currentSlugs?: string[]; } @@ -42,6 +43,24 @@ const languages = [ +
+ + +
+ @@ -95,6 +114,8 @@ const languages = [ const slugList = document.getElementById('slug-list'); const generateRSSLink = document.getElementById('generate-rss'); const langSelect = document.getElementById('lang-select') as HTMLSelectElement; + const feedIdInput = document.getElementById('feed-id-input') as HTMLInputElement; + const importFeedButton = document.getElementById('import-feed'); // Load saved slugs from localStorage let slugs = new Set(JSON.parse(localStorage.getItem('comic-slugs') || '[]')); @@ -410,6 +431,62 @@ const languages = [ } } + // Import feed functionality + importFeedButton?.addEventListener('click', async () => { + const feedId = feedIdInput.value.trim(); + if (!feedId) return; + + try { + importFeedButton.disabled = true; + importFeedButton.innerHTML = ` + + + + Importing... + `; + + const response = await fetch(`/api/feed/${feedId}`); + if (!response.ok) throw new Error('Failed to fetch feed'); + + const { slugs: feedSlugs, lang } = await response.json(); + + // Update language if provided + if (lang && langSelect) { + langSelect.value = lang; + } + + // Add new slugs to existing collection + feedSlugs.forEach((slug: string) => slugs.add(slug)); + + // Update UI + updateSlugs(); + feedIdInput.value = ''; + + // Show success message + const successDiv = document.createElement('div'); + successDiv.className = 'text-sm text-green-500 mt-1'; + successDiv.textContent = 'Feed imported successfully!'; + feedIdInput.parentNode?.appendChild(successDiv); + setTimeout(() => successDiv.remove(), 3000); + + } catch (error) { + console.error('Failed to import feed:', error); + const errorDiv = document.createElement('div'); + errorDiv.className = 'text-sm text-red-500 mt-1'; + errorDiv.textContent = 'Failed to import feed. Please check the feed ID and try again.'; + feedIdInput.parentNode?.appendChild(errorDiv); + setTimeout(() => errorDiv.remove(), 3000); + } finally { + importFeedButton.disabled = false; + importFeedButton.innerHTML = ` + + + + Import Feed + `; + } + }); + // Initial render renderSlugs(); updateRSSLink(); @@ -423,4 +500,4 @@ const languages = [ searchResults?.classList.add('hidden'); } }); - \ No newline at end of file + \ No newline at end of file diff --git a/src/pages/api/feed/[feedId].ts b/src/pages/api/feed/[feedId].ts new file mode 100644 index 0000000..2fe7c8f --- /dev/null +++ b/src/pages/api/feed/[feedId].ts @@ -0,0 +1,28 @@ +import type { APIRoute } from "astro"; +import { getFeedMapping } from '../../../lib/db'; + +export const GET: APIRoute = async ({ params }) => { + const { feedId } = params; + + if (!feedId) { + return new Response("Feed ID not provided", { status: 400 }); + } + + try { + const mapping = await getFeedMapping(feedId); + + if (!mapping) { + return new Response("Feed not found", { status: 404 }); + } + + return new Response(JSON.stringify(mapping), { + status: 200, + headers: { + 'Content-Type': 'application/json' + } + }); + } catch (error) { + console.error('Error fetching feed:', error); + return new Response("Internal server error", { status: 500 }); + } +}; \ No newline at end of file