import React, { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { MultipleImageSelector } from './multiple-image-selector'; interface DashboardData { rootPath: string; isWritable: boolean; lastGenerated: string | null; llmsTxtExists: boolean; llmsTxtUrl: string; llmsTxtSize?: string; postsCount: number; markdownCount: number; settings: { post_types: string[]; full_content: boolean; days_to_include: number; delete_on_uninstall: boolean; llm_response_images?: Array<{ id: number; position: 'before' | 'after'; }>; // Keep old fields for backward compatibility llm_response_image_id?: number; llm_response_image_position?: 'before' | 'after'; }; postTypes: Array<{ name: string; label: string; }>; isPremium: boolean; imageData?: { id: number; url: string; preview_url: string; width?: number; height?: number; } | null; pluginVersion: string; wordpressVersion: string; } interface DashboardProps { data: DashboardData; onGenerateNow: () => Promise<{ success: boolean; message: string; timestamp?: string }>; onImagesChange: (images: Array<{ id: number; position: 'before' | 'after' }>) => void; onSettingsChange: (settings: any) => void; } export function Dashboard({ data, onGenerateNow, onImagesChange, onSettingsChange }: DashboardProps) { const [isGenerating, setIsGenerating] = useState(false); const [generateMessage, setGenerateMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const [currentImages, setCurrentImages] = useState(data.settings.llm_response_images || []); const [formState, setFormState] = useState({ post_types: data.settings.post_types, full_content: data.settings.full_content, days_to_include: data.settings.days_to_include, delete_on_uninstall: data.settings.delete_on_uninstall, }); const handleGenerateNow = async () => { setIsGenerating(true); setGenerateMessage(null); try { const result = await onGenerateNow(); setGenerateMessage({ type: result.success ? 'success' : 'error', text: result.message }); // Clear message after 5 seconds setTimeout(() => setGenerateMessage(null), 5000); } catch (error) { setGenerateMessage({ type: 'error', text: 'An error occurred while generating files.' }); } finally { setIsGenerating(false); } }; const handleImagesChange = (images: Array<{ id: number; position: 'before' | 'after' }>) => { setCurrentImages(images); onImagesChange(images); }; const handlePostTypeChange = (postType: string, checked: boolean) => { const newFormState = { ...formState, post_types: checked ? [...formState.post_types, postType] : formState.post_types.filter(pt => pt !== postType) }; setFormState(newFormState); onSettingsChange(newFormState); }; const handleCheckboxChange = (name: 'full_content' | 'delete_on_uninstall', checked: boolean) => { const newFormState = { ...formState, [name]: checked }; setFormState(newFormState); onSettingsChange(newFormState); }; const handleDaysChange = (value: string) => { const days = parseInt(value, 10); const newFormState = { ...formState, days_to_include: isNaN(days) ? 0 : days }; setFormState(newFormState); onSettingsChange(newFormState); }; return (
{/* Banner */}
LLMagnet AI SEO Optimizer { // Fallback if the image doesn't load const target = e.target as HTMLImageElement; target.onerror = null; target.src = `${(window as any).llmagnetDashboardData?.pluginUrl || ''}src/assets/images/banner_upgrade.png`; console.log('Trying fallback image path:', target.src); }} />
{/* Header */}

LLMagnet Dashboard

Manage your LLMS.txt file and LLM response settings

{/* Status Overview */}

Status Overview

LLMS.txt Status
{data.llmsTxtExists ? 'Active' : 'Not Generated'}
{data.llmsTxtSize && (
{data.llmsTxtSize}
)}
Posts to Export
{data.postsCount}
Content items
Markdown Files
{data.markdownCount}
Generated files
LLM Images
0 ? 'text-green-600' : 'text-gray-400'}`}> {currentImages.length}
Configured
Directory Status
{data.isWritable ? 'Writable' : 'Not Writable'}
Root directory
{data.lastGenerated && (
Last Generated: {data.lastGenerated}
)}
{/* Generate Section */}
{data.llmsTxtExists && ( View LLMS.txt → )} {generateMessage && (
{generateMessage.text}
)}
{/* Warning for non-writable directory */} {!data.isWritable && (

Warning: Root directory is not writable. Please check file permissions before generating files.

)} {/* Content Settings & LLM Image Settings */}
{/* Content Settings */}

Content Settings

Configure which content should be included in the llms.txt file and associated Markdown exports.

Content Types to Include

{data.postTypes.map((postType) => (
{postType.label}
))}

Content Export

Include full content {!formState.full_content && '(excerpt only)'}

Time Period

handleDaysChange(e.target.value)} className="text-center font-semibold border-gray-300/50 focus:border-purple-400 focus:ring-purple-400/20 rounded-xl" />
{formState.days_to_include > 0 ? `days of content` : 'all content'}

Cleanup on Uninstall

Delete files when plugin is uninstalled
{/* LLM Response Images Section */}

LLM Response Images

Select multiple images to display with responses from all Large Language Models. These images will be included in the llms.txt file and will work with ChatGPT, Claude, Gemini, GPT-4, and other LLMs.

{/* System Information */}

System Information

{data.wordpressVersion}
{data.pluginVersion}
{data.rootPath}
); }