185 lines
6.0 KiB
TypeScript
185 lines
6.0 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { useSocket } from '@/components/providers/socket-provider'
|
|
import type { Design } from '@/lib/types/planner.types'
|
|
import { EnhancedPlannerCanvas } from './enhanced-planner-canvas'
|
|
import { PlannerToolbar } from './planner-toolbar'
|
|
import { PlannerSidebar } from './planner-sidebar'
|
|
import { AdvancedObjectInspector } from './advanced-object-inspector'
|
|
import { AdvancedToolsPanel } from './advanced-tools-panel'
|
|
import { PerformanceMonitorUI } from './performance-monitor-ui'
|
|
import { GLBOnboarding } from './glb-onboarding'
|
|
import { usePlannerStore } from '@/lib/store/planner-store'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Layers, Eye, Activity, Zap, Sparkles } from 'lucide-react'
|
|
|
|
interface PlannerEditor3DProps {
|
|
design: Design
|
|
userId: string
|
|
userName: string
|
|
}
|
|
|
|
export function PlannerEditor3D({ design, userId, userName }: PlannerEditor3DProps) {
|
|
const { socket, isConnected } = useSocket()
|
|
const [isInitialized, setIsInitialized] = useState(false)
|
|
const [showLeftPanel, setShowLeftPanel] = useState(true)
|
|
const [showRightPanel, setShowRightPanel] = useState(true)
|
|
const [showPerformance, setShowPerformance] = useState(false)
|
|
const [advancedMode, setAdvancedMode] = useState(true)
|
|
|
|
const {
|
|
selectedObjectId,
|
|
placedObjects,
|
|
renderSettings,
|
|
updateRenderSettings
|
|
} = usePlannerStore()
|
|
|
|
// Initialize planner store with design data
|
|
useEffect(() => {
|
|
if (!isInitialized && design) {
|
|
const store = usePlannerStore.getState()
|
|
|
|
// Clear existing objects first
|
|
store.placedObjects.forEach(obj => store.removeObject(obj.id))
|
|
|
|
// Load design data into store
|
|
if (design.placedObjects && design.placedObjects.length > 0) {
|
|
design.placedObjects.forEach(obj => {
|
|
store.addObject(obj)
|
|
})
|
|
}
|
|
|
|
// Load settings
|
|
if (design.snapSettings) {
|
|
store.updateSnapSettings(design.snapSettings)
|
|
}
|
|
|
|
if (design.renderSettings) {
|
|
store.updateRenderSettings(design.renderSettings)
|
|
}
|
|
|
|
setIsInitialized(true)
|
|
}
|
|
}, [design, isInitialized])
|
|
|
|
return (
|
|
<div className="h-screen flex flex-col bg-background">
|
|
{/* Collaboration Status */}
|
|
{socket && !isConnected && (
|
|
<div className="absolute top-4 right-4 z-50 bg-yellow-100 border border-yellow-400 text-yellow-800 px-4 py-2 rounded-lg text-sm shadow-lg">
|
|
🔄 Reconnecting to collaboration server...
|
|
</div>
|
|
)}
|
|
|
|
{socket && isConnected && (
|
|
<div className="absolute top-4 right-4 z-50 bg-green-100 border border-green-400 text-green-800 px-4 py-2 rounded-lg text-sm shadow-lg">
|
|
✓ Connected - Real-time collaboration active
|
|
</div>
|
|
)}
|
|
|
|
{/* Toolbar */}
|
|
<PlannerToolbar design={design} />
|
|
|
|
{/* Status Bar */}
|
|
<div className="px-4 py-2 border-b bg-muted/30 flex items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
<Badge variant="default" className="gap-1">
|
|
<Zap className="w-3 h-3" />
|
|
Advanced Mode
|
|
</Badge>
|
|
|
|
<Badge variant="outline" className="gap-1">
|
|
<Layers className="w-3 h-3" />
|
|
{placedObjects.length} Objects
|
|
</Badge>
|
|
|
|
<Badge variant="outline" className="gap-1">
|
|
<Activity className="w-3 h-3" />
|
|
{renderSettings?.quality?.toUpperCase()}
|
|
</Badge>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => setShowPerformance(!showPerformance)}
|
|
>
|
|
<Activity className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Main Content */}
|
|
<div className="flex-1 flex overflow-hidden relative">
|
|
{/* Left Panel */}
|
|
{showLeftPanel && (
|
|
advancedMode ? (
|
|
<AdvancedToolsPanel />
|
|
) : (
|
|
<PlannerSidebar designId={design.id} />
|
|
)
|
|
)}
|
|
|
|
{/* 3D Canvas */}
|
|
<div className="flex-1 relative">
|
|
<EnhancedPlannerCanvas
|
|
design={design}
|
|
enablePhysics={advancedMode}
|
|
enableWebXR={true}
|
|
enablePerformanceMonitor={showPerformance}
|
|
qualityPreset={renderSettings?.quality}
|
|
/>
|
|
|
|
{/* Toggle Buttons */}
|
|
<div className="absolute top-4 left-4 z-40 flex flex-col gap-2">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => setShowLeftPanel(!showLeftPanel)}
|
|
className="bg-background/90 backdrop-blur-sm"
|
|
>
|
|
<Layers className="w-4 h-4" />
|
|
</Button>
|
|
|
|
<Button
|
|
variant={advancedMode ? 'default' : 'outline'}
|
|
size="sm"
|
|
onClick={() => setAdvancedMode(!advancedMode)}
|
|
className="gap-2 bg-background/90 backdrop-blur-sm"
|
|
>
|
|
<Sparkles className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="absolute top-4 right-4 z-40">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => setShowRightPanel(!showRightPanel)}
|
|
className="bg-background/90 backdrop-blur-sm"
|
|
>
|
|
<Eye className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Performance Monitor */}
|
|
{showPerformance && <PerformanceMonitorUI visible={true} />}
|
|
</div>
|
|
|
|
{/* Right Panel - Object Inspector */}
|
|
{showRightPanel && (
|
|
<div className="w-80 border-l bg-card">
|
|
<AdvancedObjectInspector objectId={selectedObjectId} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* GLB Onboarding */}
|
|
<GLBOnboarding />
|
|
</div>
|
|
)
|
|
}
|