[split-required] Split remaining 500-680 LOC files (final batch)
website (17 pages + 3 components): - multiplayer/wizard, middleware/wizard+test-wizard, communication - builds/wizard, staff-search, voice, sbom/wizard - foerderantrag, mail/tasks, tools/communication, sbom - compliance/evidence, uni-crawler, brandbook (already done) - CollectionsTab, IngestionTab, RiskHeatmap backend-lehrer (5 files): - letters_api (641 → 2), certificates_api (636 → 2) - alerts_agent/db/models (636 → 3) - llm_gateway/communication_service (614 → 2) - game/database already done in prior batch klausur-service (2 files): - hybrid_vocab_extractor (664 → 2) - klausur-service/frontend: api.ts (620 → 3), EHUploadWizard (591 → 2) voice-service (3 files): - bqas/rag_judge (618 → 3), runner (529 → 2) - enhanced_task_orchestrator (519 → 2) studio-v2 (6 files): - korrektur/[klausurId] (578 → 4), fairness (569 → 2) - AlertsWizard (552 → 2), OnboardingWizard (513 → 2) - korrektur/api.ts (506 → 3), geo-lernwelt (501 → 2) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
113
studio-v2/app/geo-lernwelt/GeoSettings.tsx
Normal file
113
studio-v2/app/geo-lernwelt/GeoSettings.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
'use client'
|
||||
|
||||
import { AOITheme, AOIQuality, Difficulty, GeoJSONPolygon, AOIResponse } from './types'
|
||||
|
||||
const THEME_CONFIG: Record<AOITheme, { icon: string; color: string; label: string }> = {
|
||||
topographie: { icon: '🏔️', color: 'bg-amber-500', label: 'Topographie' },
|
||||
landnutzung: { icon: '🏘️', color: 'bg-green-500', label: 'Landnutzung' },
|
||||
orientierung: { icon: '🧭', color: 'bg-blue-500', label: 'Orientierung' },
|
||||
geologie: { icon: '🪨', color: 'bg-stone-500', label: 'Geologie' },
|
||||
hydrologie: { icon: '💧', color: 'bg-cyan-500', label: 'Hydrologie' },
|
||||
vegetation: { icon: '🌲', color: 'bg-emerald-500', label: 'Vegetation' },
|
||||
}
|
||||
|
||||
interface GeoSettingsProps {
|
||||
selectedTheme: AOITheme
|
||||
onThemeChange: (theme: AOITheme) => void
|
||||
quality: AOIQuality
|
||||
onQualityChange: (quality: AOIQuality) => void
|
||||
difficulty: Difficulty
|
||||
onDifficultyChange: (difficulty: Difficulty) => void
|
||||
drawnPolygon: GeoJSONPolygon | null
|
||||
currentAOI: AOIResponse | null
|
||||
isLoading: boolean
|
||||
onCreateAOI: () => void
|
||||
}
|
||||
|
||||
export function GeoSettings({
|
||||
selectedTheme, onThemeChange, quality, onQualityChange,
|
||||
difficulty, onDifficultyChange, drawnPolygon, currentAOI,
|
||||
isLoading, onCreateAOI,
|
||||
}: GeoSettingsProps) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* Theme Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Lernthema</h3>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{(Object.keys(THEME_CONFIG) as AOITheme[]).map((theme) => {
|
||||
const config = THEME_CONFIG[theme]
|
||||
return (
|
||||
<button key={theme} onClick={() => onThemeChange(theme)}
|
||||
className={`p-3 rounded-xl text-left transition-all ${selectedTheme === theme ? 'bg-white/15 border border-white/30' : 'bg-white/5 border border-transparent hover:bg-white/10'}`}>
|
||||
<span className="text-2xl">{config.icon}</span>
|
||||
<div className="text-sm text-white mt-1">{config.label}</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quality Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Qualitaet</h3>
|
||||
<div className="flex gap-2">
|
||||
{(['low', 'medium', 'high'] as AOIQuality[]).map((q) => (
|
||||
<button key={q} onClick={() => onQualityChange(q)}
|
||||
className={`flex-1 py-2 rounded-lg text-sm transition-all ${quality === q ? 'bg-white/15 text-white border border-white/30' : 'bg-white/5 text-white/60 hover:bg-white/10'}`}>
|
||||
{q === 'low' ? 'Schnell' : q === 'medium' ? 'Standard' : 'Hoch'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Difficulty Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Schwierigkeitsgrad</h3>
|
||||
<div className="flex gap-2">
|
||||
{(['leicht', 'mittel', 'schwer'] as Difficulty[]).map((d) => (
|
||||
<button key={d} onClick={() => onDifficultyChange(d)}
|
||||
className={`flex-1 py-2 rounded-lg text-sm capitalize transition-all ${difficulty === d ? 'bg-white/15 text-white border border-white/30' : 'bg-white/5 text-white/60 hover:bg-white/10'}`}>
|
||||
{d}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Area Info */}
|
||||
{drawnPolygon && (
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-2">Ausgewaehltes Gebiet</h3>
|
||||
<div className="text-sm text-white/60">
|
||||
<p>Polygon gezeichnet ✓</p>
|
||||
<p className="text-white/40 text-xs mt-1">Klicke "Lernwelt erstellen" um fortzufahren</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Create Button */}
|
||||
<button onClick={onCreateAOI} disabled={!drawnPolygon || isLoading}
|
||||
className={`w-full py-4 rounded-xl font-medium text-lg transition-all ${drawnPolygon && !isLoading ? 'bg-gradient-to-r from-blue-500 to-purple-500 text-white hover:from-blue-600 hover:to-purple-600' : 'bg-white/10 text-white/40 cursor-not-allowed'}`}>
|
||||
{isLoading ? (<span className="flex items-center justify-center gap-2"><span className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />Wird erstellt...</span>) : '🚀 Lernwelt erstellen'}
|
||||
</button>
|
||||
|
||||
{/* AOI Status */}
|
||||
{currentAOI && (
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-2">Status</h3>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={`w-2 h-2 rounded-full ${currentAOI.status === 'completed' ? 'bg-green-500' : currentAOI.status === 'failed' ? 'bg-red-500' : 'bg-yellow-500 animate-pulse'}`} />
|
||||
<span className="text-sm text-white/80 capitalize">
|
||||
{currentAOI.status === 'queued' ? 'In Warteschlange...' : currentAOI.status === 'processing' ? 'Wird verarbeitet...' : currentAOI.status === 'completed' ? 'Fertig!' : 'Fehlgeschlagen'}
|
||||
</span>
|
||||
</div>
|
||||
{currentAOI.area_km2 > 0 && (<p className="text-xs text-white/50">Flaeche: {currentAOI.area_km2.toFixed(2)} km²</p>)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { THEME_CONFIG }
|
||||
@@ -39,15 +39,7 @@ function MapLoadingPlaceholder() {
|
||||
)
|
||||
}
|
||||
|
||||
// Theme icons and colors
|
||||
const THEME_CONFIG: Record<AOITheme, { icon: string; color: string; label: string }> = {
|
||||
topographie: { icon: '🏔️', color: 'bg-amber-500', label: 'Topographie' },
|
||||
landnutzung: { icon: '🏘️', color: 'bg-green-500', label: 'Landnutzung' },
|
||||
orientierung: { icon: '🧭', color: 'bg-blue-500', label: 'Orientierung' },
|
||||
geologie: { icon: '🪨', color: 'bg-stone-500', label: 'Geologie' },
|
||||
hydrologie: { icon: '💧', color: 'bg-cyan-500', label: 'Hydrologie' },
|
||||
vegetation: { icon: '🌲', color: 'bg-emerald-500', label: 'Vegetation' },
|
||||
}
|
||||
import { GeoSettings } from './GeoSettings'
|
||||
|
||||
export default function GeoLernweltPage() {
|
||||
// State
|
||||
@@ -296,138 +288,18 @@ export default function GeoLernweltPage() {
|
||||
</div>
|
||||
|
||||
{/* Settings Panel (1/3) */}
|
||||
<div className="space-y-4">
|
||||
{/* Theme Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Lernthema</h3>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{(Object.keys(THEME_CONFIG) as AOITheme[]).map((theme) => {
|
||||
const config = THEME_CONFIG[theme]
|
||||
return (
|
||||
<button
|
||||
key={theme}
|
||||
onClick={() => setSelectedTheme(theme)}
|
||||
className={`p-3 rounded-xl text-left transition-all ${
|
||||
selectedTheme === theme
|
||||
? 'bg-white/15 border border-white/30'
|
||||
: 'bg-white/5 border border-transparent hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
<span className="text-2xl">{config.icon}</span>
|
||||
<div className="text-sm text-white mt-1">{config.label}</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quality Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Qualitaet</h3>
|
||||
<div className="flex gap-2">
|
||||
{(['low', 'medium', 'high'] as AOIQuality[]).map((q) => (
|
||||
<button
|
||||
key={q}
|
||||
onClick={() => setQuality(q)}
|
||||
className={`flex-1 py-2 rounded-lg text-sm transition-all ${
|
||||
quality === q
|
||||
? 'bg-white/15 text-white border border-white/30'
|
||||
: 'bg-white/5 text-white/60 hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
{q === 'low' ? 'Schnell' : q === 'medium' ? 'Standard' : 'Hoch'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Difficulty Selection */}
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-3">Schwierigkeitsgrad</h3>
|
||||
<div className="flex gap-2">
|
||||
{(['leicht', 'mittel', 'schwer'] as Difficulty[]).map((d) => (
|
||||
<button
|
||||
key={d}
|
||||
onClick={() => setDifficulty(d)}
|
||||
className={`flex-1 py-2 rounded-lg text-sm capitalize transition-all ${
|
||||
difficulty === d
|
||||
? 'bg-white/15 text-white border border-white/30'
|
||||
: 'bg-white/5 text-white/60 hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
{d}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Area Info */}
|
||||
{drawnPolygon && (
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-2">Ausgewaehltes Gebiet</h3>
|
||||
<div className="text-sm text-white/60">
|
||||
<p>Polygon gezeichnet ✓</p>
|
||||
<p className="text-white/40 text-xs mt-1">
|
||||
Klicke "Lernwelt erstellen" um fortzufahren
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Create Button */}
|
||||
<button
|
||||
onClick={handleCreateAOI}
|
||||
disabled={!drawnPolygon || isLoading}
|
||||
className={`w-full py-4 rounded-xl font-medium text-lg transition-all ${
|
||||
drawnPolygon && !isLoading
|
||||
? 'bg-gradient-to-r from-blue-500 to-purple-500 text-white hover:from-blue-600 hover:to-purple-600'
|
||||
: 'bg-white/10 text-white/40 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
{isLoading ? (
|
||||
<span className="flex items-center justify-center gap-2">
|
||||
<span className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||
Wird erstellt...
|
||||
</span>
|
||||
) : (
|
||||
'🚀 Lernwelt erstellen'
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* AOI Status */}
|
||||
{currentAOI && (
|
||||
<div className="bg-white/5 backdrop-blur-lg rounded-2xl border border-white/10 p-4">
|
||||
<h3 className="text-white font-medium mb-2">Status</h3>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${
|
||||
currentAOI.status === 'completed'
|
||||
? 'bg-green-500'
|
||||
: currentAOI.status === 'failed'
|
||||
? 'bg-red-500'
|
||||
: 'bg-yellow-500 animate-pulse'
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm text-white/80 capitalize">
|
||||
{currentAOI.status === 'queued'
|
||||
? 'In Warteschlange...'
|
||||
: currentAOI.status === 'processing'
|
||||
? 'Wird verarbeitet...'
|
||||
: currentAOI.status === 'completed'
|
||||
? 'Fertig!'
|
||||
: 'Fehlgeschlagen'}
|
||||
</span>
|
||||
</div>
|
||||
{currentAOI.area_km2 > 0 && (
|
||||
<p className="text-xs text-white/50">
|
||||
Flaeche: {currentAOI.area_km2.toFixed(2)} km²
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<GeoSettings
|
||||
selectedTheme={selectedTheme}
|
||||
onThemeChange={setSelectedTheme}
|
||||
quality={quality}
|
||||
onQualityChange={setQuality}
|
||||
difficulty={difficulty}
|
||||
onDifficultyChange={setDifficulty}
|
||||
drawnPolygon={drawnPolygon}
|
||||
currentAOI={currentAOI}
|
||||
isLoading={isLoading}
|
||||
onCreateAOI={handleCreateAOI}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
/* Unity 3D Viewer Tab */
|
||||
|
||||
Reference in New Issue
Block a user