From 77ed04520418be5feba8ba8926804a23f02fb9a7 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Thu, 19 Feb 2026 03:22:13 -0500 Subject: [PATCH] feat: wire maintenance schedule section into procedural editor Add collapsible Schedule section for maintenance flows with accordion integration. Schedule summary shows frequency, time, and target count when collapsed. New maintenance flows default to schedule section expanded. Two-stage save preserved: tree saved first, schedule managed independently. Co-Authored-By: Claude Opus 4.6 --- frontend/src/pages/ProceduralEditorPage.tsx | 31 +++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/ProceduralEditorPage.tsx b/frontend/src/pages/ProceduralEditorPage.tsx index 8e5a2905..f17b4d8e 100644 --- a/frontend/src/pages/ProceduralEditorPage.tsx +++ b/frontend/src/pages/ProceduralEditorPage.tsx @@ -1,14 +1,15 @@ import { useEffect, useState, useCallback } from 'react' import { useParams, useNavigate, useSearchParams } from 'react-router-dom' -import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText } from 'lucide-react' +import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar } from 'lucide-react' import { treesApi } from '@/api/trees' import { useProceduralEditorStore } from '@/store/proceduralEditorStore' import { CollapsibleEditorSection } from '@/components/procedural-editor/CollapsibleEditorSection' import { IntakeFormBuilder } from '@/components/procedural-editor/IntakeFormBuilder' +import { MaintenanceScheduleSection, getScheduleSummary } from '@/components/procedural-editor/MaintenanceScheduleSection' import { StepList } from '@/components/procedural-editor/StepList' import { TagInput } from '@/components/common/TagInput' import { toast } from '@/lib/toast' -import type { TreeType } from '@/types' +import type { TreeType, MaintenanceSchedule, TargetList } from '@/types' type SectionKey = 'details' | 'intake' | 'schedule' @@ -49,10 +50,19 @@ export function ProceduralEditorPage() { isEditMode ? null : 'details' ) + // Schedule state for collapsed summary + const [schedule, setSchedule] = useState(null) + const [scheduleTargetList, setScheduleTargetList] = useState(null) + const toggleSection = useCallback((key: SectionKey) => { setExpandedSection(prev => prev === key ? null : key) }, []) + const handleScheduleLoaded = useCallback((s: MaintenanceSchedule | null, tl: TargetList | null) => { + setSchedule(s) + setScheduleTargetList(tl) + }, []) + // Load tree or init new useEffect(() => { if (isEditMode && id) { @@ -123,6 +133,8 @@ export function ProceduralEditorPage() { isPublic ? 'Public' : 'Private', ].join(' \u00b7 ') + const scheduleSummary = getScheduleSummary(schedule, scheduleTargetList) + const intakeSummary = intakeForm.length === 0 ? 'No fields defined' : `${intakeForm.length} field${intakeForm.length !== 1 ? 's' : ''}: ${intakeForm.map(f => f.label || f.variable_name).slice(0, 4).join(', ')}${intakeForm.length > 4 ? ', \u2026' : ''}` @@ -241,6 +253,21 @@ export function ProceduralEditorPage() { > + + {isMaintenance && ( + } + summary={scheduleSummary} + expanded={expandedSection === 'schedule'} + onToggle={() => toggleSection('schedule')} + > + + + )} {/* Step List — flex-1, scrolls independently */}