import React, { useState, useEffect } from 'react'; import ReactDOM from 'react-dom/client'; import { GoogleGenAI, Type } from "@google/genai"; // --- Types --- type SchemaType = 'Article' | 'Product' | 'Organization' | 'LocalBusiness' | 'FAQPage' | 'Recipe'; interface SchemaField { name: string; label: string; type: 'text' | 'textarea' | 'number' | 'url' | 'date'; placeholder?: string; required?: boolean; } interface SchemaDefinition { type: SchemaType; label: string; icon: string; description: string; fields: SchemaField[]; } // --- Constants --- const SCHEMA_DEFINITIONS: SchemaDefinition[] = [ { type: 'Article', label: 'Article', icon: '📰', description: 'News, blog posts, or research articles.', fields: [ { name: 'headline', label: 'Headline', type: 'text', required: true }, { name: 'author', label: 'Author Name', type: 'text', required: true }, { name: 'datePublished', label: 'Date Published', type: 'date', required: true }, { name: 'image', label: 'Image URL', type: 'url' }, ] }, { type: 'Product', label: 'Product', icon: '📦', description: 'Products with prices and reviews.', fields: [ { name: 'name', label: 'Product Name', type: 'text', required: true }, { name: 'description', label: 'Description', type: 'textarea' }, { name: 'brand', label: 'Brand', type: 'text' }, { name: 'price', label: 'Price', type: 'number' }, { name: 'currency', label: 'Currency (e.g. USD)', type: 'text' }, ] }, { type: 'FAQPage', label: 'FAQ Page', icon: '❓', description: 'Helpful for search result rich snippets.', fields: [ { name: 'questions', label: 'Q&A Content', type: 'textarea', placeholder: 'Q: Is it organic? A: Yes.', required: true } ] }, { type: 'LocalBusiness', label: 'Local Business', icon: '🏠', description: 'Physical locations and contact info.', fields: [ { name: 'name', label: 'Business Name', type: 'text', required: true }, { name: 'address', label: 'Street Address', type: 'text' }, { name: 'phone', label: 'Phone', type: 'text' }, ] }, { type: 'Recipe', label: 'Recipe', icon: '🍳', description: 'Cooking steps and ingredients.', fields: [ { name: 'name', label: 'Recipe Name', type: 'text', required: true }, { name: 'prepTime', label: 'Prep Time (e.g. PT20M)', type: 'text' }, { name: 'ingredients', label: 'Ingredients List', type: 'textarea' } ] } ]; // --- Application Logic --- const App = () => { const [apiKeySet, setApiKeySet] = useState(false); const [selectedType, setSelectedType] = useState(null); const [formData, setFormData] = useState>({}); const [generatedCode, setGeneratedCode] = useState(''); const [explanation, setExplanation] = useState(''); const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState<'form' | 'ai' | 'url'>('form'); const [aiPrompt, setAiPrompt] = useState(''); const [urlInput, setUrlInput] = useState(''); useEffect(() => { const checkExistingKey = async () => { const aistudio = (window as any).aistudio; if (aistudio && await aistudio.hasSelectedApiKey()) { setApiKeySet(true); } else if (typeof process !== 'undefined' && process.env?.API_KEY) { setApiKeySet(true); } }; checkExistingKey(); }, []); const handleOpenKeySelector = async () => { const aistudio = (window as any).aistudio; if (aistudio) { await aistudio.openSelectKey(); setApiKeySet(true); } else { alert("API key selector is not available. Please ensure window.aistudio is present."); } }; const handleGenerate = async (mode: 'form' | 'ai' | 'url') => { setIsLoading(true); try { // Create fresh instance to use latest session key const ai = new GoogleGenAI({ apiKey: process.env.API_KEY }); let resText = ''; let insights = ''; // Standardizing on 'gemini-3-flash-preview' for best reliability across tiers const MODEL_NAME = 'gemini-3-flash-preview'; if (mode === 'form' && selectedType) { const response = await ai.models.generateContent({ model: MODEL_NAME, contents: `Create valid JSON-LD schema for ${selectedType} using this data: ${JSON.stringify(formData)}. Return ONLY the JSON-LD code block inside