Erster Commit

This commit is contained in:
2026-04-23 22:10:45 +02:00
commit 5d47482d2a
30 changed files with 6340 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import ObjectsList from '../components/ObjectsList'
import DetailsPanel from '../components/DetailsPanel'
import SentencesList from '../components/SentencesList'
import { getImages, getObjects, generateDetails, generateSentence, getSentences } from '../api'
import type { ObjectMeta, Sentence } from '../types'
export default function GenerateIt() {
const navigate = useNavigate()
const [imageList, setImageList] = useState<string[]>([])
const [currentIndex, setCurrentIndex] = useState(-1)
const [objects, setObjects] = useState<ObjectMeta[]>([])
const [selectedObj, setSelectedObj] = useState<ObjectMeta | null>(null)
const [sentences, setSentences] = useState<Sentence[]>([])
const [isGeneratingDetails, setIsGeneratingDetails] = useState(false)
const [isGeneratingSentence, setIsGeneratingSentence] = useState(false)
const currentFilename =
currentIndex >= 0 && currentIndex < imageList.length ? imageList[currentIndex] : null
useEffect(() => {
getImages('generate')
.then(imgs => {
setImageList(imgs)
setCurrentIndex(imgs.length - 1)
})
.catch(console.error)
}, [])
useEffect(() => {
if (!currentFilename) {
setObjects([])
setSelectedObj(null)
setSentences([])
return
}
getObjects(currentFilename)
.then(objs => {
setObjects(objs)
if (objs.length > 0) {
setSelectedObj(objs[0])
loadSentences(objs[0].id)
} else {
setSelectedObj(null)
setSentences([])
}
})
.catch(console.error)
}, [currentFilename])
const loadSentences = async (objId: string) => {
try {
const s = await getSentences(objId)
setSentences(s)
} catch (e) {
console.error(e)
}
}
const handleGenerateDetails = async () => {
const target = selectedObj ?? objects[0]
if (!target) return
setIsGeneratingDetails(true)
try {
const data = await generateDetails(target.id)
const updated = { ...target, ...data }
setSelectedObj(updated)
setObjects(prev => prev.map(o => o.id === target.id ? updated : o))
} catch (e) {
alert(e instanceof Error ? e.message : 'Fehler bei KI-Details')
} finally {
setIsGeneratingDetails(false)
}
}
const handleGenerateSentence = async () => {
const target = selectedObj ?? objects[0]
if (!target) return
setIsGeneratingSentence(true)
try {
const data = await generateSentence(target.id)
setSentences(prev => [...prev, data.sentence])
setSelectedObj(prev => prev ? { ...prev, latest_sentence: data.sentence } : prev)
} catch (e) {
alert(e instanceof Error ? e.message : 'Fehler bei KI-Sentence')
} finally {
setIsGeneratingSentence(false)
}
}
return (
<div className="container">
<h1>GenerateIt</h1>
<div className="panel image-nav">
<div className="image-nav-left">
<button
onClick={() => setCurrentIndex(i => i - 1)}
disabled={currentIndex <= 0}
>
</button>
<span>Bild: <code>{currentFilename || ''}</code></span>
<button
onClick={() => setCurrentIndex(i => i + 1)}
disabled={currentIndex >= imageList.length - 1}
>
</button>
<button
onClick={handleGenerateDetails}
disabled={isGeneratingDetails || !selectedObj}
>
{isGeneratingDetails ? '⏳ KI-Details...' : '✨ KI-Details'}
</button>
<button
onClick={handleGenerateSentence}
disabled={isGeneratingSentence || !selectedObj}
>
{isGeneratingSentence ? '⏳ KI-Sentence...' : '💬 KI-Sentence'}
</button>
</div>
<div className="page-switch">
<select value="/generate" onChange={e => navigate(e.target.value)}>
<option value="/draw">DrawIt</option>
<option value="/generate">GenerateIt</option>
</select>
</div>
</div>
<div className="main-layout">
<div className="objects-pane sidebar-section">
<h2>Objekte zu diesem Bild</h2>
<ObjectsList
objects={objects}
selectedObjectId={selectedObj?.id ?? null}
onSelect={id => {
const obj = objects.find(o => o.id === id)
if (obj) {
setSelectedObj(obj)
loadSentences(obj.id)
}
}}
onObjectsChange={setObjects}
isGeneratePage={true}
onShowDetails={obj => setSelectedObj(obj)}
onLoadSentences={loadSentences}
/>
</div>
<div className="right-pane">
<DetailsPanel obj={selectedObj} objects={objects} sentences={sentences} />
</div>
<div className="sentences-pane">
<div className="sidebar-section">
<h2>Alle Sätze</h2>
<SentencesList sentences={sentences} />
</div>
</div>
</div>
</div>
)
}