import * as React from 'react'; import { AIGCSettings, AIGCArticle } from '../types'; import { Icon } from './ui/Icon'; import { generateArticle } from '../services/geminiService'; import { format, parseISO } from 'date-fns'; import { useTranslation } from '../hooks/useI18n'; // --- Helper Components --- const ArticlePreview: React.FC<{ article: AIGCArticle; onEdit: () => void }> = ({ article, onEdit }) => { const { t } = useTranslation(); return (

{article.title}

{article.title}

{article.summary}

Published: {format(parseISO(article.publicationDate), 'MMMM d, yyyy')}


); }; const EditorToolbar: React.FC<{ onExecCommand: (command: string, value?: string) => void }> = ({ onExecCommand }) => { const inputClasses = "bg-gray-200 dark:bg-gray-600 border-gray-300 dark:border-gray-500 rounded p-1 text-xs focus:outline-none focus:ring-1 focus:ring-brand-primary text-gray-900 dark:text-white"; const buttonClasses = "p-2 rounded hover:bg-gray-200 dark:hover:bg-gray-600"; return (
{/* Style */}
{/* Align */}
{/* Font */} onExecCommand('foreColor', e.target.value)} defaultValue="#E5E7EB" className={`${inputClasses} h-8 w-8 p-0 align-middle`} />
{/* Insert */}
); }; const ArticleEditor: React.FC<{ initialData: Partial; onSave: (data: Omit) => void; onCancel: () => void; isNew: boolean; }> = ({ initialData, onSave, onCancel, isNew }) => { const { t } = useTranslation(); const [data, setData] = React.useState(initialData); const contentEditableRef = React.useRef(null); const inputClasses = "w-full bg-gray-100 dark:bg-gray-700 p-2 rounded-md border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-1 focus:ring-brand-primary"; const labelClasses = "block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-1"; const [generationMode, setGenerationMode] = React.useState<'ai' | 'url'>('ai'); const [generationInput, setGenerationInput] = React.useState(''); const [isGenerating, setIsGenerating] = React.useState(false); const [showGenerator, setShowGenerator] = React.useState(false); const handleSave = () => { if (!data.title?.trim()) { alert(t('aigc.news.title_req')); return; } onSave({ title: data.title, summary: data.summary || '', content: data.content || '', sourceType: data.sourceType || 'text', sourceUrl: data.sourceUrl }); }; const handleExecCommand = (command: string, value?: string) => { document.execCommand(command, false, value); contentEditableRef.current?.focus(); }; const handleContentChange = (e: React.FormEvent) => { setData(d => ({ ...d, content: e.currentTarget.innerHTML })); }; const handleGenerate = async () => { setIsGenerating(true); try { const prompt = generationMode === 'url' ? `Parse and summarize this article: ${generationInput}` : generationInput; if (!generationInput.trim()) { alert(`Please enter a ${generationMode === 'url' ? 'URL' : 'topic'}.`); return; } const result = await generateArticle(prompt); setData(d => ({ ...d, ...result, sourceType: generationMode === 'url' ? 'url' : 'generated', sourceUrl: generationMode === 'url' ? generationInput : undefined, })); // Keep the generator open for potential re-generation } catch (error) { console.error("Failed to generate article:", error); alert("Sorry, we couldn't generate the article at this time."); } finally { setIsGenerating(false); } }; return (

{isNew ? t('aigc.news.create') : t('aigc.news.edit')}

{showGenerator && (
{(['ai', 'url'] as const).map(m => ( ))}
setGenerationInput(e.target.value)} onKeyPress={e => e.key === 'Enter' && handleGenerate()} placeholder={generationMode === 'ai' ? t('aigc.news.enter_topic') : t('aigc.news.enter_url')} className={inputClasses} />
)}
setData(d => ({...d, title: e.target.value}))} className={inputClasses} />
); }; // --- Main Component --- interface NewsCreatorProps { aigcSettings: AIGCSettings; onUpdateAIGCSettings: (newSettings: AIGCSettings) => void; } const NewsCreator: React.FC = ({ aigcSettings, onUpdateAIGCSettings }) => { const { t } = useTranslation(); const [selectedArticleId, setSelectedArticleId] = React.useState(null); const [isEditing, setIsEditing] = React.useState(false); const articles = aigcSettings.articles || []; const selectedArticle = React.useMemo(() => articles.find(a => a.id === selectedArticleId), [articles, selectedArticleId]); const handleSaveArticle = (data: Omit) => { let updatedArticles; if (selectedArticleId && !selectedArticleId.startsWith('new-')) { // Editing existing article updatedArticles = articles.map(a => a.id === selectedArticleId ? { ...a, ...data, publicationDate: new Date().toISOString() } : a); } else { // Creating new article const newArticle: AIGCArticle = { id: `article-${Date.now()}`, publicationDate: new Date().toISOString(), ...data }; if (selectedArticleId?.startsWith('new-')) { updatedArticles = articles.map(a => a.id === selectedArticleId ? newArticle : a); } else { updatedArticles = [newArticle, ...articles]; } setSelectedArticleId(newArticle.id); } onUpdateAIGCSettings({ ...aigcSettings, articles: updatedArticles }); setIsEditing(false); }; const handleDeleteArticle = (id: string) => { if (!window.confirm(t('aigc.news.delete_confirm'))) return; const updatedArticles = articles.filter(a => a.id !== id); onUpdateAIGCSettings({ ...aigcSettings, articles: updatedArticles }); if (selectedArticleId === id) { setSelectedArticleId(null); setIsEditing(false); } }; const handleCreateNewArticle = () => { if (selectedArticleId?.startsWith('new-')) return; // Don't create another if one is in progress const tempId = `new-${Date.now()}`; const tempArticle: AIGCArticle = { id: tempId, publicationDate: new Date().toISOString(), title: '', summary: '', content: '', sourceType: 'text', }; onUpdateAIGCSettings({ ...aigcSettings, articles: [tempArticle, ...articles] }); setSelectedArticleId(tempId); setIsEditing(true); }; const handleCancelEdit = () => { if (selectedArticleId && selectedArticleId.startsWith('new-')) { const updatedArticles = articles.filter(a => a.id !== selectedArticleId); onUpdateAIGCSettings({ ...aigcSettings, articles: updatedArticles }); const firstRealArticle = updatedArticles.find(a => !a.id.startsWith('new-')); setSelectedArticleId(firstRealArticle ? firstRealArticle.id : null); } setIsEditing(false); }; return (
{selectedArticle ? ( isEditing ? ( ) : ( setIsEditing(true)} /> ) ) : (

{t('aigc.news.empty_title')}

{t('aigc.news.empty_desc')}

)}
); }; export default NewsCreator;