diff --git a/frontend/src/components/tools/shared/ToolStep.tsx b/frontend/src/components/tools/shared/ToolStep.tsx index 2bbd508c4..bda493e88 100644 --- a/frontend/src/components/tools/shared/ToolStep.tsx +++ b/frontend/src/components/tools/shared/ToolStep.tsx @@ -9,6 +9,7 @@ import { createReviewToolStep, ReviewToolStepProps } from './ReviewToolStep'; interface ToolStepContextType { visibleStepCount: number; + forceStepNumbers?: boolean; } const ToolStepContext = createContext(null); @@ -82,10 +83,11 @@ const ToolStep = ({ const parent = useContext(ToolStepContext); - // Auto-detect if we should show numbers based on sibling count + // Auto-detect if we should show numbers based on sibling count or force option const shouldShowNumber = useMemo(() => { - if (showNumber !== undefined) return showNumber; - return parent ? parent.visibleStepCount >= 3 : false; + if (showNumber !== undefined) return showNumber; // Individual step override + if (parent?.forceStepNumbers) return true; // Flow-level force + return parent ? parent.visibleStepCount >= 3 : false; // Auto-detect }, [showNumber, parent]); const stepNumber = _stepNumber; @@ -196,7 +198,7 @@ export function createToolSteps() { } // Context provider wrapper for tools using the factory -export function ToolStepProvider({ children }: { children: React.ReactNode }) { +export function ToolStepProvider({ children, forceStepNumbers }: { children: React.ReactNode; forceStepNumbers?: boolean }) { // Count visible steps from children that are ToolStep elements const visibleStepCount = useMemo(() => { let count = 0; @@ -212,8 +214,9 @@ export function ToolStepProvider({ children }: { children: React.ReactNode }) { }, [children]); const contextValue = useMemo(() => ({ - visibleStepCount - }), [visibleStepCount]); + visibleStepCount, + forceStepNumbers + }), [visibleStepCount, forceStepNumbers]); return ( diff --git a/frontend/src/components/tools/shared/createToolFlow.tsx b/frontend/src/components/tools/shared/createToolFlow.tsx index 76f53cfe2..3cb46ed60 100644 --- a/frontend/src/components/tools/shared/createToolFlow.tsx +++ b/frontend/src/components/tools/shared/createToolFlow.tsx @@ -49,6 +49,7 @@ export interface ToolFlowConfig { steps: MiddleStepConfig[]; executeButton?: ExecuteButtonConfig; review: ReviewStepConfig; + forceStepNumbers?: boolean; } /** @@ -60,7 +61,7 @@ export function createToolFlow(config: ToolFlowConfig) { return ( - + {/* Files Step */} {steps.createFilesStep({ selectedFiles: config.files.selectedFiles, diff --git a/frontend/src/tools/AddWatermark.tsx b/frontend/src/tools/AddWatermark.tsx index 57cff6f59..ad0b55a37 100644 --- a/frontend/src/tools/AddWatermark.tsx +++ b/frontend/src/tools/AddWatermark.tsx @@ -14,8 +14,15 @@ import WatermarkFormatting from "../components/tools/addWatermark/WatermarkForma import { useAddWatermarkParameters } from "../hooks/tools/addWatermark/useAddWatermarkParameters"; import { useAddWatermarkOperation } from "../hooks/tools/addWatermark/useAddWatermarkOperation"; -import { useWatermarkTypeTips, useWatermarkWordingTips, useWatermarkTextStyleTips, useWatermarkFileTips, useWatermarkFormattingTips } from "../components/tooltips/useWatermarkTips"; +import { + useWatermarkTypeTips, + useWatermarkWordingTips, + useWatermarkTextStyleTips, + useWatermarkFileTips, + useWatermarkFormattingTips, +} from "../components/tooltips/useWatermarkTips"; import { BaseToolProps } from "../types/tool"; +import { isVisible } from "@testing-library/user-event/dist/utils"; const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); @@ -24,7 +31,7 @@ const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => const [collapsedType, setCollapsedType] = useState(false); const [collapsedStyle, setCollapsedStyle] = useState(true); - const [collapsedAdvanced, setCollapsedAdvanced] = useState(true); + const [collapsedFormatting, setCollapsedFormatting] = useState(true); const watermarkParams = useAddWatermarkParameters(); const watermarkOperation = useAddWatermarkOperation(); @@ -80,36 +87,28 @@ const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => // Step completion logic const typeStepCompleted = hasFiles && !!watermarkParams.parameters.watermarkType; - const textWordingCompleted = typeStepCompleted && - watermarkParams.parameters.watermarkType === 'text' && - watermarkParams.parameters.watermarkText.trim().length > 0; - const imageFileCompleted = typeStepCompleted && - watermarkParams.parameters.watermarkType === 'image' && - watermarkParams.parameters.watermarkImage !== undefined; // Dynamic step structure based on watermark type const getSteps = () => { const steps = []; - // Step 1: Watermark Type (always visible after files) - if (hasFiles) { - steps.push({ - title: t("watermark.steps.type", "Watermark Type"), - isCollapsed: hasResults ? true : collapsedType, - onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedType(!collapsedType), - tooltip: watermarkTypeTips, - content: ( - watermarkParams.updateParameter('watermarkType', type)} - disabled={endpointLoading} - /> - ), - }); - } + steps.push({ + title: t("watermark.steps.type", "Watermark Type"), + isCollapsed: hasResults ? true : collapsedType, + isVisible: hasFiles || hasResults, + onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedType(!collapsedType), + tooltip: watermarkTypeTips, + content: ( + watermarkParams.updateParameter("watermarkType", type)} + disabled={endpointLoading} + /> + ), + }); // Text watermark path - if (watermarkParams.parameters.watermarkType === 'text') { + if (watermarkParams.parameters.watermarkType === "text") { // Step 2: Wording steps.push({ title: t("watermark.steps.wording", "Wording"), @@ -142,8 +141,8 @@ const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => // Step 4: Formatting steps.push({ title: t("watermark.steps.formatting", "Formatting"), - isCollapsed: hasResults ? true : collapsedAdvanced, - onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedAdvanced(!collapsedAdvanced), + isCollapsed: hasResults ? true : collapsedFormatting, + onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedFormatting(!collapsedFormatting), tooltip: watermarkFormattingTips, content: ( } // Image watermark path - if (watermarkParams.parameters.watermarkType === 'image') { + if (watermarkParams.parameters.watermarkType === "image") { // Step 2: Watermark File steps.push({ title: t("watermark.steps.file", "Watermark File"), @@ -174,8 +173,8 @@ const AddWatermark = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => // Step 3: Formatting steps.push({ title: t("watermark.steps.formatting", "Formatting"), - isCollapsed: hasResults ? true : collapsedAdvanced, - onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedAdvanced(!collapsedAdvanced), + isCollapsed: hasResults ? true : collapsedFormatting, + onCollapsedClick: hasResults ? handleSettingsReset : () => setCollapsedFormatting(!collapsedFormatting), tooltip: watermarkFormattingTips, content: ( title: t("watermark.results.title", "Watermark Results"), onFileClick: handleThumbnailClick, }, + forceStepNumbers: true, }); -} +}; export default AddWatermark;