import { type Component, createSignal, Show } from 'solid-js'; import { Download, Upload } from 'lucide-solid'; import { sourcesApi } from '~/api/sources'; import { normalizeUrl } from '~/utils/url'; import { useI18n } from '~/i18n'; import { isApiError } from '~/types'; interface SourceImportProps { themeId: string; onImported: () => void; } /** CSV import/export + bulk text import for sources. */ const SourceImport: Component = (props) => { const { t } = useI18n(); const [bulkText, setBulkText] = createSignal(''); const [importing, setImporting] = createSignal(false); const [importError, setImportError] = createSignal(null); const [csvError, setCsvError] = createSignal(null); let fileInputRef: HTMLInputElement | undefined; // ---- CSV Export ---- const handleExportCsv = async () => { setCsvError(null); try { await sourcesApi.exportCsv(props.themeId); } catch { setCsvError(t('sources.exportError')); } }; // ---- CSV Import ---- const handleImportCsv = async (e: Event) => { const input = e.target as HTMLInputElement; const file = input.files?.[0]; if (!file) return; setImporting(true); setCsvError(null); try { await sourcesApi.importCsv(file, props.themeId); props.onImported(); } catch (err) { if (isApiError(err)) { setCsvError(err.message); } else { setCsvError(t('sources.csvImportError')); } } finally { setImporting(false); input.value = ''; } }; // ---- Bulk Import ---- const handleBulkImport = async (e: SubmitEvent) => { e.preventDefault(); if (!bulkText().trim()) return; setImporting(true); setImportError(null); const lines = bulkText() .split('\n') .map((l) => l.trim()) .filter((l) => l.length > 0); const validSources: { title: string; url: string; theme_id?: string }[] = []; for (const line of lines) { const parts = line.split(';'); if (parts.length >= 2) { const title = parts[0].trim(); const url = normalizeUrl(parts.slice(1).join(';').trim()); if (title && url) { validSources.push({ title, url, theme_id: props.themeId }); } } } if (validSources.length === 0) { setImportError(t('sources.bulkImportError')); setImporting(false); return; } try { await sourcesApi.bulkImport({ sources: validSources, theme_id: props.themeId }); setBulkText(''); props.onImported(); } catch (err) { if (isApiError(err)) { setImportError(err.message); } else { setImportError(t('sources.bulkImportError')); } } finally { setImporting(false); } }; return ( <> {/* CSV Import / Export */}

{t('sources.csvSection')}

{t('sources.csvDescription')}

{(msg) => (

{msg()}

)}
{/* Bulk Import */}

{t('sources.bulkSection')}

{t('sources.bulkDescription')}{' '} {t('sources.bulkFormat')}