import { type BuildingNode, LevelNode, useScene, type ZoneNode, } from "@pascal-app/core"; import { useViewer } from "@pascal-app/viewer"; import { Building2, ChevronDown, Hexagon, Layers, Plus, Trash2, } from "lucide-react"; import { cn } from "@/lib/utils"; import useEditor from "@/store/use-editor"; import { TreeNode } from "./tree-node"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/primitives/popover"; // Preset colors for zones const PRESET_COLORS = [ "#3b82f6", // blue "#22c55e", // green "#eab308", // yellow "#f97316", // orange "#ef4444", // red "#a855f7", // purple "#ec4899", // pink "#06b6d4", // cyan ]; // ============================================================================ // SITE PHASE VIEW - Simple building buttons // ============================================================================ function SitePhaseView() { const nodes = useScene((state) => state.nodes); const rootNodeIds = useScene((state) => state.rootNodeIds); const selectedBuildingId = useViewer((state) => state.selection.buildingId); const setSelection = useViewer((state) => state.setSelection); const buildings = rootNodeIds .map((id) => nodes[id]) .filter((node): node is BuildingNode => node?.type === "building"); if (buildings.length === 0) { return (
No buildings yet
); } return (
{buildings.map((building) => ( ))}
); } // ============================================================================ // STRUCTURE/FURNISH PHASE VIEW - Building dropdown + Levels + Content // ============================================================================ function BuildingSelector() { const nodes = useScene((state) => state.nodes); const rootNodeIds = useScene((state) => state.rootNodeIds); const selectedBuildingId = useViewer((state) => state.selection.buildingId); const setSelection = useViewer((state) => state.setSelection); const buildings = rootNodeIds .map((id) => nodes[id]) .filter((node): node is BuildingNode => node?.type === "building"); const selectedBuilding = selectedBuildingId ? (nodes[selectedBuildingId] as BuildingNode) : null; if (buildings.length === 0) return null; // If only one building, just show it as a header if (buildings.length === 1) { return (
{buildings[0]?.name || "Building"}
); } return ( {buildings.map((building) => ( ))} ); } function LevelsSection() { const nodes = useScene((state) => state.nodes); const createNode = useScene((state) => state.createNode); const selectedBuildingId = useViewer((state) => state.selection.buildingId); const selectedLevelId = useViewer((state) => state.selection.levelId); const setSelection = useViewer((state) => state.setSelection); const building = selectedBuildingId ? (nodes[selectedBuildingId] as BuildingNode) : null; if (!building) return null; const levels = building.children .map((id) => nodes[id]) .filter((node): node is LevelNode => node?.type === "level"); const handleAddLevel = () => { const newLevel = LevelNode.parse({ level: levels.length, children: [], parentId: building.id, }); createNode(newLevel, building.id); setSelection({ levelId: newLevel.id }); }; return (
{/* Header */}
Levels
{/* Level buttons */}
{levels.map((level) => ( ))} {levels.length === 0 && (
No levels yet
)}
); } function LayerToggle() { const structureLayer = useEditor((state) => state.structureLayer); const setStructureLayer = useEditor((state) => state.setStructureLayer); return (
); } function ZoneItem({ zone }: { zone: ZoneNode }) { const deleteNode = useScene((state) => state.deleteNode); const updateNode = useScene((state) => state.updateNode); const selectedZoneId = useViewer((state) => state.selection.zoneId); const hoveredId = useViewer((state) => state.hoveredId); const setSelection = useViewer((state) => state.setSelection); const setHoveredId = useViewer((state) => state.setHoveredId); const setPhase = useEditor((state) => state.setPhase); const setMode = useEditor((state) => state.setMode); const isSelected = selectedZoneId === zone.id; const isHovered = hoveredId === zone.id; const handleClick = () => { setSelection({ zoneId: zone.id }); setPhase("structure"); setMode("select"); }; const handleDelete = (e: React.MouseEvent) => { e.stopPropagation(); deleteNode(zone.id); if (isSelected) { setSelection({ zoneId: null }); } }; const handleColorChange = (color: string) => { updateNode(zone.id, { color }); }; return (
setHoveredId(zone.id)} onMouseLeave={() => setHoveredId(null)} >
{zone.name} ); } function ContentSection() { const nodes = useScene((state) => state.nodes); const selectedLevelId = useViewer((state) => state.selection.levelId); const structureLayer = useEditor((state) => state.structureLayer); const setPhase = useEditor((state) => state.setPhase); const setMode = useEditor((state) => state.setMode); const setTool = useEditor((state) => state.setTool); const level = selectedLevelId ? (nodes[selectedLevelId] as LevelNode) : null; if (!level) { return (
Select a level to view content
); } if (structureLayer === "zones") { // Show zones for this level const levelZones = Object.values(nodes).filter( (node): node is ZoneNode => node.type === "zone" && node.parentId === selectedLevelId ); const handleAddZone = () => { setPhase("structure"); setMode("build"); setTool("zone"); }; if (levelZones.length === 0) { return (
No zones on this level.{" "}
); } return (
{levelZones.map((zone) => ( ))}
); } // Show elements (walls, items, etc.) for this level if (level.children.length === 0) { return (
No elements on this level
); } return (
{level.children.map((childId) => ( ))}
); } function StructurePhaseView() { const phase = useEditor((state) => state.phase); return (
{/* Only show layer toggle in structure phase, furnish is always elements */} {phase === "structure" && }
); } // ============================================================================ // MAIN SITE PANEL // ============================================================================ export function SitePanel() { const phase = useEditor((state) => state.phase); if (phase === "site") { return ; } return ; }