import React, { useState, useRef } from 'react'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Checkbox } from '@/components/ui/checkbox'; interface ImageData { id: number; url: string; preview_url: string; width?: number; height?: number; } interface ImageSelectorProps { currentImage?: ImageData | null; position: 'before' | 'after'; onImageSelect: (imageData: ImageData | null) => void; onPositionChange: (position: 'before' | 'after') => void; isPremium: boolean; } export function ImageSelector({ currentImage, position, onImageSelect, onPositionChange, isPremium }: ImageSelectorProps) { const [isUploading, setIsUploading] = useState(false); const [uploadError, setUploadError] = useState(null); const fileInputRef = useRef(null); const handleFileSelect = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // Validate file type if (!file.type.startsWith('image/')) { setUploadError('Please select an image file.'); return; } // Validate file size (max 5MB) if (file.size > 5 * 1024 * 1024) { setUploadError('Image size must be less than 5MB.'); return; } setIsUploading(true); setUploadError(null); try { const formData = new FormData(); formData.append('action', 'llmagnet_ai_seo_upload_image'); formData.append('nonce', window.llmagnetLlmsTxtAdmin.nonce); formData.append('image', file); const response = await fetch(window.llmagnetLlmsTxtAdmin.ajaxUrl, { method: 'POST', body: formData, credentials: 'same-origin', }); const result = await response.json(); if (result.success && result.data) { onImageSelect({ id: result.data.attachment_id, url: result.data.url, preview_url: result.data.preview_url, width: result.data.width, height: result.data.height, }); } else { setUploadError(result.data?.message || 'Upload failed. Please try again.'); } } catch (error) { console.error('Upload error:', error); setUploadError('Upload failed. Please check your connection and try again.'); } finally { setIsUploading(false); // Reset file input if (fileInputRef.current) { fileInputRef.current.value = ''; } } }; const openMediaLibrary = () => { if (typeof wp !== 'undefined' && wp.media) { const mediaUploader = wp.media({ title: 'Select LLM Response Image', button: { text: 'Use this image' }, multiple: false, library: { type: 'image' } }); mediaUploader.on('select', () => { const attachment = mediaUploader.state().get('selection').first().toJSON(); onImageSelect({ id: attachment.id, url: attachment.url, preview_url: attachment.sizes?.medium?.url || attachment.url, width: attachment.sizes?.medium?.width || attachment.width, height: attachment.sizes?.medium?.height || attachment.height, }); }); mediaUploader.open(); } else { // Fallback to file input if WordPress media library is not available fileInputRef.current?.click(); } }; const removeImage = () => { onImageSelect(null); }; if (!isPremium) { return (

LLM Response Image (Premium Feature)

Attach an image that will be displayed with responses from all Large Language Models (ChatGPT, Claude, Gemini, GPT-4, etc.) and included in the llms.txt file.

Premium Feature: This feature is available for premium users only. Upgrade to attach images to your LLM responses.
); } return (

LLM Response Image

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

{currentImage ? (
Selected image

Current Image

{currentImage.width && currentImage.height ? `${currentImage.width} × ${currentImage.height}px` : 'Image selected'}

) : (

No image selected

)} {/* Position Setting */}
checked && onPositionChange('before')} />
checked && onPositionChange('after')} />
{/* Hidden file input */} {/* Error display */} {uploadError && (
{uploadError}
)}
); }