Files
storycove/frontend/src/app/import/page.tsx
2025-08-14 19:46:50 +02:00

113 lines
3.6 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import ImportLayout from '../../components/layout/ImportLayout';
import { Input } from '../../components/ui/Input';
import Button from '../../components/ui/Button';
export default function ImportFromUrlPage() {
const [importUrl, setImportUrl] = useState('');
const [scraping, setScraping] = useState(false);
const [errors, setErrors] = useState<Record<string, string>>({});
const router = useRouter();
const handleImportFromUrl = async () => {
if (!importUrl.trim()) {
setErrors({ importUrl: 'URL is required' });
return;
}
setScraping(true);
setErrors({});
try {
const response = await fetch('/scrape/story', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ url: importUrl }),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Failed to scrape story');
}
const scrapedStory = await response.json();
// Redirect to add-story page with pre-filled data
const queryParams = new URLSearchParams({
from: 'url-import',
title: scrapedStory.title || '',
summary: scrapedStory.summary || '',
author: scrapedStory.author || '',
sourceUrl: scrapedStory.sourceUrl || importUrl,
tags: JSON.stringify(scrapedStory.tags || []),
content: scrapedStory.content || ''
});
router.push(`/add-story?${queryParams.toString()}`);
} catch (error: any) {
console.error('Failed to import story:', error);
setErrors({ importUrl: error.message });
} finally {
setScraping(false);
}
};
return (
<ImportLayout
title="Import Story from URL"
description="Import a single story from a website"
>
<div className="space-y-6">
<div className="bg-gray-50 dark:bg-gray-800/50 rounded-lg p-6">
<h3 className="text-lg font-medium theme-header mb-4">Import Story from URL</h3>
<p className="theme-text text-sm mb-4">
Enter a URL from a supported story site to automatically extract the story content, title, author, and other metadata. After importing, you'll be able to review and edit the data before saving.
</p>
<div className="space-y-4">
<Input
label="Story URL"
type="url"
value={importUrl}
onChange={(e) => setImportUrl(e.target.value)}
placeholder="https://example.com/story-url"
error={errors.importUrl}
disabled={scraping}
/>
<div className="flex gap-3">
<Button
type="button"
onClick={handleImportFromUrl}
loading={scraping}
disabled={!importUrl.trim() || scraping}
>
{scraping ? 'Importing...' : 'Import Story'}
</Button>
<Button
type="button"
variant="ghost"
href="/add-story"
disabled={scraping}
>
Enter Manually Instead
</Button>
</div>
<div className="text-xs theme-text">
<p className="font-medium mb-1">Supported Sites:</p>
<p>Archive of Our Own, DeviantArt, FanFiction.Net, Literotica, Royal Road, Wattpad, and more</p>
</div>
</div>
</div>
</div>
</ImportLayout>
);
}