|
import React, { useState, useCallback } from 'react'; |
|
import { Zap } from 'lucide-react'; |
|
|
|
|
|
import Header from './Header'; |
|
import SetupScreen from './SetupScreen'; |
|
import InputScreen from './InputScreen'; |
|
import GeneratingScreen from './GeneratingScreen'; |
|
import PreviewScreen from './PreviewScreen'; |
|
|
|
|
|
import { callAnthropicAPI } from '../services/anthropic'; |
|
import { callHuggingFaceAPI } from '../services/huggingface'; |
|
import { getPrompts } from '../services/prompts'; |
|
|
|
const WorkshopGenerator = () => { |
|
const [currentStep, setCurrentStep] = useState('setup'); |
|
const [apiKey, setApiKey] = useState({ anthropic: '', huggingface: '' }); |
|
const [apiProvider, setApiProvider] = useState('anthropic'); |
|
const [workshopData, setWorkshopData] = useState({ |
|
topic: '', |
|
audience: '', |
|
duration: '90', |
|
difficulty: 'intermediate' |
|
}); |
|
const [generatedContent, setGeneratedContent] = useState(null); |
|
const [isGenerating, setIsGenerating] = useState(false); |
|
const [activeAgent, setActiveAgent] = useState(''); |
|
const [error, setError] = useState(''); |
|
|
|
const getApiCallFunction = useCallback(() => { |
|
if (apiProvider === 'huggingface') { |
|
return (prompt, maxTokens) => callHuggingFaceAPI(prompt, apiKey.huggingface, maxTokens); |
|
} |
|
|
|
return (prompt, maxTokens) => callAnthropicAPI(prompt, apiKey.anthropic, maxTokens); |
|
}, [apiProvider, apiKey]); |
|
|
|
const generateWorkshop = async () => { |
|
setIsGenerating(true); |
|
setCurrentStep('generating'); |
|
setError(''); |
|
const callAPI = getApiCallFunction(); |
|
const prompts = getPrompts(workshopData); |
|
|
|
try { |
|
const runAgent = async (agentName, prompt, maxTokens) => { |
|
setActiveAgent(agentName); |
|
const response = await callAPI(prompt, maxTokens); |
|
const cleanResponse = response.replace(/```json\n?/, "").replace(/```\n?/, "").trim(); |
|
try { |
|
return JSON.parse(cleanResponse); |
|
} catch (parseError) { |
|
console.error(`Error parsing JSON from ${agentName}:`, parseError, "Raw response:", response); |
|
throw new Error(`Agent "${agentName}" returned invalid data. Please try again.`); |
|
} |
|
}; |
|
|
|
|
|
const topicData = await runAgent('topic', prompts.topic, 1500); |
|
const contentData = await runAgent('content', prompts.content(JSON.stringify(topicData)), 3000); |
|
const slideData = await runAgent('slide', prompts.slide(JSON.stringify(contentData)), 4000); |
|
const codeData = await runAgent('code', prompts.code(JSON.stringify(topicData)), 3000); |
|
|
|
|
|
setGeneratedContent({ |
|
topic: topicData, |
|
content: contentData, |
|
slides: slideData, |
|
code: codeData, |
|
metadata: { |
|
title: topicData.title || workshopData.topic, |
|
modules: topicData.modules?.length || 0, |
|
slideCount: slideData.slide_count || slideData.slides?.length || 0, |
|
exercises: codeData.exercises?.length || 0, |
|
generatedAt: new Date().toISOString(), |
|
provider: apiProvider |
|
} |
|
}); |
|
|
|
setCurrentStep('preview'); |
|
} catch (err) { |
|
console.error("Workshop generation error:", err); |
|
setError(err.message); |
|
setCurrentStep('input'); |
|
} finally { |
|
setIsGenerating(false); |
|
setActiveAgent(''); |
|
} |
|
}; |
|
|
|
const resetGenerator = () => { |
|
setCurrentStep('input'); |
|
setGeneratedContent(null); |
|
setWorkshopData({ topic: '', audience: '', duration: '90', difficulty: 'intermediate' }); |
|
setError(''); |
|
}; |
|
|
|
const renderStep = () => { |
|
switch (currentStep) { |
|
case 'setup': |
|
return <SetupScreen |
|
apiKey={apiKey} |
|
setApiKey={setApiKey} |
|
apiProvider={apiProvider} |
|
setApiProvider={setApiProvider} |
|
setCurrentStep={setCurrentStep} |
|
setError={setError} |
|
getApiCallFunction={getApiCallFunction} |
|
/>; |
|
case 'input': |
|
return <InputScreen |
|
workshopData={workshopData} |
|
setWorkshopData={setWorkshopData} |
|
isGenerating={isGenerating} |
|
generateWorkshop={generateWorkshop} |
|
setCurrentStep={setCurrentStep} |
|
/>; |
|
case 'generating': |
|
return <GeneratingScreen activeAgent={activeAgent} />; |
|
case 'preview': |
|
return <PreviewScreen |
|
generatedContent={generatedContent} |
|
workshopData={workshopData} |
|
resetGenerator={resetGenerator} |
|
/>; |
|
default: |
|
return <SetupScreen />; |
|
} |
|
}; |
|
|
|
return ( |
|
<div className="min-h-screen bg-gray-900 text-white font-sans"> |
|
<Header /> |
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> |
|
{error && ( |
|
<div className="max-w-2xl mx-auto mb-6 bg-red-500/20 border border-red-400 rounded-lg p-4 flex items-center space-x-3"> |
|
<AlertCircle className="w-5 h-5 text-red-400" /> |
|
<span className="text-red-200">{error}</span> |
|
</div> |
|
)} |
|
{renderStep()} |
|
</main> |
|
</div> |
|
); |
|
}; |
|
|
|
export default WorkshopGenerator; |