mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 20:23:36 +00:00
fix(kanban): persist image previews when switching tabs in Add Feature modal
Lifts image preview state up to parent components to prevent loss of preview thumbnails when switching between tabs. Added previewMap/onPreviewMapChange props to DescriptionImageDropZone for parent-controlled state management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useRef, useCallback } from "react";
|
||||
import React, { useState, useRef, useCallback, useEffect } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ImageIcon, X, Loader2 } from "lucide-react";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
@@ -14,6 +14,9 @@ export interface FeatureImagePath {
|
||||
mimeType: string;
|
||||
}
|
||||
|
||||
// Map to store preview data by image ID (persisted across component re-mounts)
|
||||
export type ImagePreviewMap = Map<string, string>;
|
||||
|
||||
interface DescriptionImageDropZoneProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
@@ -24,6 +27,9 @@ interface DescriptionImageDropZoneProps {
|
||||
disabled?: boolean;
|
||||
maxFiles?: number;
|
||||
maxFileSize?: number; // in bytes, default 10MB
|
||||
// Optional: pass preview map from parent to persist across tab switches
|
||||
previewMap?: ImagePreviewMap;
|
||||
onPreviewMapChange?: (map: ImagePreviewMap) => void;
|
||||
}
|
||||
|
||||
const ACCEPTED_IMAGE_TYPES = [
|
||||
@@ -45,12 +51,31 @@ export function DescriptionImageDropZone({
|
||||
disabled = false,
|
||||
maxFiles = 5,
|
||||
maxFileSize = DEFAULT_MAX_FILE_SIZE,
|
||||
previewMap,
|
||||
onPreviewMapChange,
|
||||
}: DescriptionImageDropZoneProps) {
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [previewImages, setPreviewImages] = useState<Map<string, string>>(
|
||||
new Map()
|
||||
// Use parent-provided preview map if available, otherwise use local state
|
||||
const [localPreviewImages, setLocalPreviewImages] = useState<Map<string, string>>(
|
||||
() => new Map()
|
||||
);
|
||||
|
||||
// Determine which preview map to use - prefer parent-controlled state
|
||||
const previewImages = previewMap !== undefined ? previewMap : localPreviewImages;
|
||||
const setPreviewImages = useCallback((updater: Map<string, string> | ((prev: Map<string, string>) => Map<string, string>)) => {
|
||||
if (onPreviewMapChange) {
|
||||
const currentMap = previewMap !== undefined ? previewMap : localPreviewImages;
|
||||
const newMap = typeof updater === 'function' ? updater(currentMap) : updater;
|
||||
onPreviewMapChange(newMap);
|
||||
} else {
|
||||
setLocalPreviewImages((prev) => {
|
||||
const newMap = typeof updater === 'function' ? updater(prev) : updater;
|
||||
return newMap;
|
||||
});
|
||||
}
|
||||
}, [onPreviewMapChange, previewMap, localPreviewImages]);
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const currentProject = useAppStore((state) => state.currentProject);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import { FeatureImageUpload } from "@/components/ui/feature-image-upload";
|
||||
import {
|
||||
DescriptionImageDropZone,
|
||||
FeatureImagePath as DescriptionImagePath,
|
||||
ImagePreviewMap,
|
||||
} from "@/components/ui/description-image-dropzone";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -197,6 +198,13 @@ export function BoardView() {
|
||||
const [followUpImagePaths, setFollowUpImagePaths] = useState<
|
||||
DescriptionImagePath[]
|
||||
>([]);
|
||||
// Preview maps to persist image previews across tab switches
|
||||
const [newFeaturePreviewMap, setNewFeaturePreviewMap] = useState<ImagePreviewMap>(
|
||||
() => new Map()
|
||||
);
|
||||
const [followUpPreviewMap, setFollowUpPreviewMap] = useState<ImagePreviewMap>(
|
||||
() => new Map()
|
||||
);
|
||||
|
||||
// Make current project available globally for modal
|
||||
useEffect(() => {
|
||||
@@ -716,6 +724,8 @@ export function BoardView() {
|
||||
model: "opus",
|
||||
thinkingLevel: "none",
|
||||
});
|
||||
// Clear the preview map when the feature is added
|
||||
setNewFeaturePreviewMap(new Map());
|
||||
setShowAddDialog(false);
|
||||
};
|
||||
|
||||
@@ -991,6 +1001,7 @@ export function BoardView() {
|
||||
setFollowUpFeature(null);
|
||||
setFollowUpPrompt("");
|
||||
setFollowUpImagePaths([]);
|
||||
setFollowUpPreviewMap(new Map());
|
||||
|
||||
// Show success toast immediately
|
||||
toast.success("Follow-up started", {
|
||||
@@ -1485,7 +1496,13 @@ export function BoardView() {
|
||||
</div>
|
||||
|
||||
{/* Add Feature Dialog */}
|
||||
<Dialog open={showAddDialog} onOpenChange={setShowAddDialog}>
|
||||
<Dialog open={showAddDialog} onOpenChange={(open) => {
|
||||
setShowAddDialog(open);
|
||||
// Clear preview map when dialog closes
|
||||
if (!open) {
|
||||
setNewFeaturePreviewMap(new Map());
|
||||
}
|
||||
}}>
|
||||
<DialogContent
|
||||
compact={!isMaximized}
|
||||
data-testid="add-feature-dialog"
|
||||
@@ -1536,6 +1553,8 @@ export function BoardView() {
|
||||
setNewFeature({ ...newFeature, imagePaths: images })
|
||||
}
|
||||
placeholder="Describe the feature..."
|
||||
previewMap={newFeaturePreviewMap}
|
||||
onPreviewMapChange={setNewFeaturePreviewMap}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -2077,6 +2096,7 @@ export function BoardView() {
|
||||
setFollowUpFeature(null);
|
||||
setFollowUpPrompt("");
|
||||
setFollowUpImagePaths([]);
|
||||
setFollowUpPreviewMap(new Map());
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -2115,6 +2135,8 @@ export function BoardView() {
|
||||
images={followUpImagePaths}
|
||||
onImagesChange={setFollowUpImagePaths}
|
||||
placeholder="Describe what needs to be fixed or changed..."
|
||||
previewMap={followUpPreviewMap}
|
||||
onPreviewMapChange={setFollowUpPreviewMap}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
@@ -2130,6 +2152,7 @@ export function BoardView() {
|
||||
setFollowUpFeature(null);
|
||||
setFollowUpPrompt("");
|
||||
setFollowUpImagePaths([]);
|
||||
setFollowUpPreviewMap(new Map());
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
|
||||
Reference in New Issue
Block a user