From 68714fad3c7a2300779a9bf92edc814e4c15608c Mon Sep 17 00:00:00 2001 From: chihlasm Date: Fri, 6 Mar 2026 23:43:10 -0500 Subject: [PATCH] feat: integrate AI panel, context menu, and ghost steps in procedural editor Co-Authored-By: Claude Opus 4.6 --- .../components/procedural-editor/StepList.tsx | 118 +++++++++++------- frontend/src/pages/ProceduralEditorPage.tsx | 78 +++++++++++- 2 files changed, 149 insertions(+), 47 deletions(-) diff --git a/frontend/src/components/procedural-editor/StepList.tsx b/frontend/src/components/procedural-editor/StepList.tsx index a9cb93f1..f0e1d0ba 100644 --- a/frontend/src/components/procedural-editor/StepList.tsx +++ b/frontend/src/components/procedural-editor/StepList.tsx @@ -39,7 +39,11 @@ function SortableStepWrapper({ ) } -export function StepList() { +interface StepListProps { + onStepContextMenu?: (e: React.MouseEvent, stepId: string) => void +} + +export function StepList({ onStepContextMenu }: StepListProps) { const { steps, intakeForm, @@ -208,6 +212,7 @@ export function StepList() { const contentType = step.content_type || 'action' const config = contentTypeConfig[contentType] const Icon = config.icon + const isGhost = !!(step as unknown as Record)._suggestion if (isExpanded) { return ( @@ -232,53 +237,80 @@ export function StepList() { {({ dragHandleProps }) => (
onStepContextMenu?.(e, step.id)} > - +
+ - - {stepNumber} - - - - - - - setExpandedStepId(step.id)} - > - {step.title || 'Untitled step'} - - - {step.estimated_minutes && ( - - ~{step.estimated_minutes}m + + {stepNumber} + + + + + + setExpandedStepId(step.id)} + > + {step.title || 'Untitled step'} + + + {step.estimated_minutes && ( + + ~{step.estimated_minutes}m + + )} + + + + +
+ + {isGhost && ( +
+ + +
)} - - - -
)} diff --git a/frontend/src/pages/ProceduralEditorPage.tsx b/frontend/src/pages/ProceduralEditorPage.tsx index a9a74560..b807e08d 100644 --- a/frontend/src/pages/ProceduralEditorPage.tsx +++ b/frontend/src/pages/ProceduralEditorPage.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, useCallback } from 'react' import { useParams, useNavigate, useSearchParams } from 'react-router-dom' -import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar } from 'lucide-react' +import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar, Sparkles, Layers } from 'lucide-react' import { treesApi } from '@/api/trees' import { useProceduralEditorStore } from '@/store/proceduralEditorStore' import { CollapsibleEditorSection } from '@/components/procedural-editor/CollapsibleEditorSection' @@ -10,6 +10,10 @@ import { getScheduleSummary } from '@/components/procedural-editor/scheduleUtils import { StepList } from '@/components/procedural-editor/StepList' import { TagInput } from '@/components/common/TagInput' import { Spinner } from '@/components/common/Spinner' +import { EditorAIPanel } from '@/components/editor-ai/EditorAIPanel' +import { ContextMenu } from '@/components/common/ContextMenu' +import { useEditorAI } from '@/hooks/useEditorAI' +import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' import type { TreeType, MaintenanceSchedule, TargetList } from '@/types' @@ -44,6 +48,13 @@ export function ProceduralEditorPage() { getTreeForSave, } = useProceduralEditorStore() + const steps = useProceduralEditorStore(s => s.steps) + + const editorAI = useEditorAI({ + flowType: 'procedural', + treeId: id, + }) + const isMaintenance = treeType === 'maintenance' const flowLabel = isMaintenance ? 'Maintenance Flow' : 'Procedure' @@ -175,6 +186,19 @@ export function ProceduralEditorPage() { {isDirty && ( Unsaved changes )} +