mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Refactor component tree builder state
This commit is contained in:
@@ -1,94 +1,33 @@
|
||||
import { useState } from 'react'
|
||||
import { ComponentNode } from '@/types/project'
|
||||
import { AIService } from '@/lib/ai-service'
|
||||
import { toast } from 'sonner'
|
||||
import componentTreeBuilderData from '@/data/component-tree-builder.json'
|
||||
import { ComponentInspector } from '@/components/component-tree-builder/ComponentInspector'
|
||||
import { ComponentTreeToolbar } from '@/components/component-tree-builder/ComponentTreeToolbar'
|
||||
import { ComponentTreeView } from '@/components/component-tree-builder/ComponentTreeView'
|
||||
import {
|
||||
addChildNode,
|
||||
createComponentNode,
|
||||
deleteNodeFromTree,
|
||||
findNodeById,
|
||||
updateNodeInTree,
|
||||
} from '@/components/component-tree-builder/tree-utils'
|
||||
import { useComponentTreeBuilder } from '@/hooks/use-component-tree-builder'
|
||||
|
||||
interface ComponentTreeBuilderProps {
|
||||
components: ComponentNode[]
|
||||
onComponentsChange: (components: ComponentNode[]) => void
|
||||
}
|
||||
|
||||
const { muiComponents, prompts } = componentTreeBuilderData
|
||||
const { muiComponents } = componentTreeBuilderData
|
||||
|
||||
export function ComponentTreeBuilder({
|
||||
components,
|
||||
onComponentsChange,
|
||||
}: ComponentTreeBuilderProps) {
|
||||
const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null)
|
||||
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())
|
||||
|
||||
const selectedNode = selectedNodeId
|
||||
? findNodeById(components, selectedNodeId)
|
||||
: null
|
||||
|
||||
const addRootComponent = () => {
|
||||
const newNode = createComponentNode({
|
||||
name: `Component${components.length + 1}`,
|
||||
})
|
||||
onComponentsChange([...components, newNode])
|
||||
setSelectedNodeId(newNode.id)
|
||||
}
|
||||
|
||||
const addChildComponent = (parentId: string) => {
|
||||
const newNode = createComponentNode()
|
||||
onComponentsChange(addChildNode(components, parentId, newNode))
|
||||
setExpandedNodes(new Set([...expandedNodes, parentId]))
|
||||
setSelectedNodeId(newNode.id)
|
||||
}
|
||||
|
||||
const deleteNode = (nodeId: string) => {
|
||||
onComponentsChange(deleteNodeFromTree(components, nodeId))
|
||||
if (selectedNodeId === nodeId) {
|
||||
setSelectedNodeId(null)
|
||||
}
|
||||
}
|
||||
|
||||
const updateNode = (nodeId: string, updates: Partial<ComponentNode>) => {
|
||||
onComponentsChange(updateNodeInTree(components, nodeId, updates))
|
||||
}
|
||||
|
||||
const toggleExpand = (nodeId: string) => {
|
||||
const newExpanded = new Set(expandedNodes)
|
||||
if (newExpanded.has(nodeId)) {
|
||||
newExpanded.delete(nodeId)
|
||||
} else {
|
||||
newExpanded.add(nodeId)
|
||||
}
|
||||
setExpandedNodes(newExpanded)
|
||||
}
|
||||
|
||||
const generateComponentWithAI = async () => {
|
||||
const description = prompt(prompts.generateComponentDescription)
|
||||
if (!description) return
|
||||
|
||||
try {
|
||||
toast.info('Generating component with AI...')
|
||||
const component = await AIService.generateComponent(description)
|
||||
|
||||
if (component) {
|
||||
onComponentsChange([...components, component])
|
||||
setSelectedNodeId(component.id)
|
||||
setExpandedNodes(new Set([...Array.from(expandedNodes), component.id]))
|
||||
toast.success(`Component "${component.name}" created successfully!`)
|
||||
} else {
|
||||
toast.error('AI generation failed. Please try again.')
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Failed to generate component')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
const {
|
||||
selectedNode,
|
||||
selectedNodeId,
|
||||
expandedNodes,
|
||||
selectNode,
|
||||
addRootComponent,
|
||||
addChildComponent,
|
||||
deleteNode,
|
||||
updateNode,
|
||||
toggleExpand,
|
||||
generateComponentWithAI,
|
||||
} = useComponentTreeBuilder({ components, onComponentsChange })
|
||||
|
||||
return (
|
||||
<div className="h-full flex gap-4 p-6">
|
||||
@@ -101,7 +40,7 @@ export function ComponentTreeBuilder({
|
||||
nodes={components}
|
||||
selectedNodeId={selectedNodeId}
|
||||
expandedNodes={expandedNodes}
|
||||
onSelectNode={setSelectedNodeId}
|
||||
onSelectNode={selectNode}
|
||||
onToggleExpand={toggleExpand}
|
||||
/>
|
||||
</div>
|
||||
|
||||
118
src/hooks/use-component-tree-builder.ts
Normal file
118
src/hooks/use-component-tree-builder.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { ComponentNode } from '@/types/project'
|
||||
import { AIService } from '@/lib/ai-service'
|
||||
import { toast } from 'sonner'
|
||||
import componentTreeBuilderData from '@/data/component-tree-builder.json'
|
||||
import {
|
||||
addChildNode,
|
||||
createComponentNode,
|
||||
deleteNodeFromTree,
|
||||
findNodeById,
|
||||
updateNodeInTree,
|
||||
} from '@/components/component-tree-builder/tree-utils'
|
||||
|
||||
type ComponentTreeBuilderOptions = {
|
||||
components: ComponentNode[]
|
||||
onComponentsChange: (components: ComponentNode[]) => void
|
||||
}
|
||||
|
||||
const { prompts } = componentTreeBuilderData
|
||||
|
||||
export function useComponentTreeBuilder({
|
||||
components,
|
||||
onComponentsChange,
|
||||
}: ComponentTreeBuilderOptions) {
|
||||
const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null)
|
||||
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())
|
||||
|
||||
const selectedNode = useMemo(
|
||||
() => (selectedNodeId ? findNodeById(components, selectedNodeId) : null),
|
||||
[components, selectedNodeId]
|
||||
)
|
||||
|
||||
const selectNode = useCallback((nodeId: string | null) => {
|
||||
setSelectedNodeId(nodeId)
|
||||
}, [])
|
||||
|
||||
const addRootComponent = useCallback(() => {
|
||||
const newNode = createComponentNode({
|
||||
name: `Component${components.length + 1}`,
|
||||
})
|
||||
onComponentsChange([...components, newNode])
|
||||
setSelectedNodeId(newNode.id)
|
||||
}, [components, onComponentsChange])
|
||||
|
||||
const addChildComponent = useCallback(
|
||||
(parentId: string) => {
|
||||
const newNode = createComponentNode()
|
||||
onComponentsChange(addChildNode(components, parentId, newNode))
|
||||
setExpandedNodes(prevExpanded => new Set([...prevExpanded, parentId]))
|
||||
setSelectedNodeId(newNode.id)
|
||||
},
|
||||
[components, onComponentsChange]
|
||||
)
|
||||
|
||||
const deleteNode = useCallback(
|
||||
(nodeId: string) => {
|
||||
onComponentsChange(deleteNodeFromTree(components, nodeId))
|
||||
if (selectedNodeId === nodeId) {
|
||||
setSelectedNodeId(null)
|
||||
}
|
||||
},
|
||||
[components, onComponentsChange, selectedNodeId]
|
||||
)
|
||||
|
||||
const updateNode = useCallback(
|
||||
(nodeId: string, updates: Partial<ComponentNode>) => {
|
||||
onComponentsChange(updateNodeInTree(components, nodeId, updates))
|
||||
},
|
||||
[components, onComponentsChange]
|
||||
)
|
||||
|
||||
const toggleExpand = useCallback((nodeId: string) => {
|
||||
setExpandedNodes(prevExpanded => {
|
||||
const newExpanded = new Set(prevExpanded)
|
||||
if (newExpanded.has(nodeId)) {
|
||||
newExpanded.delete(nodeId)
|
||||
} else {
|
||||
newExpanded.add(nodeId)
|
||||
}
|
||||
return newExpanded
|
||||
})
|
||||
}, [])
|
||||
|
||||
const generateComponentWithAI = useCallback(async () => {
|
||||
const description = prompt(prompts.generateComponentDescription)
|
||||
if (!description) return
|
||||
|
||||
try {
|
||||
toast.info('Generating component with AI...')
|
||||
const component = await AIService.generateComponent(description)
|
||||
|
||||
if (component) {
|
||||
onComponentsChange([...components, component])
|
||||
setSelectedNodeId(component.id)
|
||||
setExpandedNodes(prevExpanded => new Set([...prevExpanded, component.id]))
|
||||
toast.success(`Component "${component.name}" created successfully!`)
|
||||
} else {
|
||||
toast.error('AI generation failed. Please try again.')
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Failed to generate component')
|
||||
console.error(error)
|
||||
}
|
||||
}, [components, onComponentsChange])
|
||||
|
||||
return {
|
||||
selectedNode,
|
||||
selectedNodeId,
|
||||
expandedNodes,
|
||||
selectNode,
|
||||
addRootComponent,
|
||||
addChildComponent,
|
||||
deleteNode,
|
||||
updateNode,
|
||||
toggleExpand,
|
||||
generateComponentWithAI,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user