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 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-19 03:22:13 -05:00
parent a60103e337
commit 77ed045204

View File

@@ -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<MaintenanceSchedule | null>(null)
const [scheduleTargetList, setScheduleTargetList] = useState<TargetList | null>(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() {
>
<IntakeFormBuilder />
</CollapsibleEditorSection>
{isMaintenance && (
<CollapsibleEditorSection
title="Schedule"
icon={<Calendar className="h-4 w-4" />}
summary={scheduleSummary}
expanded={expandedSection === 'schedule'}
onToggle={() => toggleSection('schedule')}
>
<MaintenanceScheduleSection
treeId={treeId}
onScheduleLoaded={handleScheduleLoaded}
/>
</CollapsibleEditorSection>
)}
</div>
{/* Step List — flex-1, scrolls independently */}