"use client"; import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { HotkeyButton } from "@/components/ui/hotkey-button"; import { Label } from "@/components/ui/label"; import { CategoryAutocomplete } from "@/components/ui/category-autocomplete"; import { DescriptionImageDropZone, FeatureImagePath as DescriptionImagePath, ImagePreviewMap, } from "@/components/ui/description-image-dropzone"; import { MessageSquare, Settings2, FlaskConical, Sparkles, ChevronDown, GitBranch } from "lucide-react"; import { toast } from "sonner"; import { getElectronAPI } from "@/lib/electron"; import { modelSupportsThinking } from "@/lib/utils"; import { Feature, AgentModel, ThinkingLevel, AIProfile, useAppStore, } from "@/store/app-store"; import { ModelSelector, ThinkingLevelSelector, ProfileQuickSelect, TestingTabContent, PrioritySelector, } from "../shared"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { DependencyTreeDialog } from "./dependency-tree-dialog"; interface EditFeatureDialogProps { feature: Feature | null; onClose: () => void; onUpdate: ( featureId: string, updates: { category: string; description: string; steps: string[]; skipTests: boolean; model: AgentModel; thinkingLevel: ThinkingLevel; imagePaths: DescriptionImagePath[]; priority: number; } ) => void; categorySuggestions: string[]; isMaximized: boolean; showProfilesOnly: boolean; aiProfiles: AIProfile[]; allFeatures: Feature[]; } export function EditFeatureDialog({ feature, onClose, onUpdate, categorySuggestions, isMaximized, showProfilesOnly, aiProfiles, allFeatures, }: EditFeatureDialogProps) { const [editingFeature, setEditingFeature] = useState(feature); const [editFeaturePreviewMap, setEditFeaturePreviewMap] = useState(() => new Map()); const [showEditAdvancedOptions, setShowEditAdvancedOptions] = useState(false); const [isEnhancing, setIsEnhancing] = useState(false); const [enhancementMode, setEnhancementMode] = useState<'improve' | 'technical' | 'simplify' | 'acceptance'>('improve'); const [showDependencyTree, setShowDependencyTree] = useState(false); // Get enhancement model from store const { enhancementModel } = useAppStore(); useEffect(() => { setEditingFeature(feature); if (!feature) { setEditFeaturePreviewMap(new Map()); setShowEditAdvancedOptions(false); } }, [feature]); const handleUpdate = () => { if (!editingFeature) return; const selectedModel = (editingFeature.model ?? "opus") as AgentModel; const normalizedThinking: ThinkingLevel = modelSupportsThinking(selectedModel) ? (editingFeature.thinkingLevel ?? "none") : "none"; const updates = { category: editingFeature.category, description: editingFeature.description, steps: editingFeature.steps, skipTests: editingFeature.skipTests ?? false, model: selectedModel, thinkingLevel: normalizedThinking, imagePaths: editingFeature.imagePaths ?? [], priority: editingFeature.priority ?? 2, }; onUpdate(editingFeature.id, updates); setEditFeaturePreviewMap(new Map()); setShowEditAdvancedOptions(false); onClose(); }; const handleDialogClose = (open: boolean) => { if (!open) { onClose(); } }; const handleModelSelect = (model: AgentModel) => { if (!editingFeature) return; setEditingFeature({ ...editingFeature, model, thinkingLevel: modelSupportsThinking(model) ? editingFeature.thinkingLevel : "none", }); }; const handleProfileSelect = (model: AgentModel, thinkingLevel: ThinkingLevel) => { if (!editingFeature) return; setEditingFeature({ ...editingFeature, model, thinkingLevel, }); }; const handleEnhanceDescription = async () => { if (!editingFeature?.description.trim() || isEnhancing) return; setIsEnhancing(true); try { const api = getElectronAPI(); const result = await api.enhancePrompt?.enhance( editingFeature.description, enhancementMode, enhancementModel ); if (result?.success && result.enhancedText) { const enhancedText = result.enhancedText; setEditingFeature(prev => prev ? { ...prev, description: enhancedText } : prev); toast.success("Description enhanced!"); } else { toast.error(result?.error || "Failed to enhance description"); } } catch (error) { console.error("Enhancement failed:", error); toast.error("Failed to enhance description"); } finally { setIsEnhancing(false); } }; const editModelAllowsThinking = modelSupportsThinking(editingFeature?.model); if (!editingFeature) { return null; } return ( { const target = e.target as HTMLElement; if (target.closest('[data-testid="category-autocomplete-list"]')) { e.preventDefault(); } }} onInteractOutside={(e) => { const target = e.target as HTMLElement; if (target.closest('[data-testid="category-autocomplete-list"]')) { e.preventDefault(); } }} > Edit Feature Modify the feature details. Prompt Model Testing {/* Prompt Tab */}
setEditingFeature({ ...editingFeature, description: value, }) } images={editingFeature.imagePaths ?? []} onImagesChange={(images) => setEditingFeature({ ...editingFeature, imagePaths: images, }) } placeholder="Describe the feature..." previewMap={editFeaturePreviewMap} onPreviewMapChange={setEditFeaturePreviewMap} data-testid="edit-feature-description" />
setEnhancementMode('improve')}> Improve Clarity setEnhancementMode('technical')}> Add Technical Details setEnhancementMode('simplify')}> Simplify setEnhancementMode('acceptance')}> Add Acceptance Criteria
setEditingFeature({ ...editingFeature, category: value, }) } suggestions={categorySuggestions} placeholder="e.g., Core, UI, API" data-testid="edit-feature-category" />
{/* Priority Selector */} setEditingFeature({ ...editingFeature, priority, }) } testIdPrefix="edit-priority" />
{/* Model Tab */} {/* Show Advanced Options Toggle */} {showProfilesOnly && (

Simple Mode Active

Only showing AI profiles. Advanced model tweaking is hidden.

)} {/* Quick Select Profile Section */} {/* Separator */} {aiProfiles.length > 0 && (!showProfilesOnly || showEditAdvancedOptions) && (
)} {/* Claude Models Section */} {(!showProfilesOnly || showEditAdvancedOptions) && ( <> {editModelAllowsThinking && ( setEditingFeature({ ...editingFeature, thinkingLevel: level, }) } testIdPrefix="edit-thinking-level" /> )} )} {/* Testing Tab */} setEditingFeature({ ...editingFeature, skipTests }) } steps={editingFeature.steps} onStepsChange={(steps) => setEditingFeature({ ...editingFeature, steps }) } testIdPrefix="edit" />
Save Changes
setShowDependencyTree(false)} feature={editingFeature} allFeatures={allFeatures} />
); }