diff --git a/frontend/src/components/tools/shared/FileStatusIndicator.tsx b/frontend/src/components/tools/shared/FileStatusIndicator.tsx index 2790680d1..e6f0b2e2f 100644 --- a/frontend/src/components/tools/shared/FileStatusIndicator.tsx +++ b/frontend/src/components/tools/shared/FileStatusIndicator.tsx @@ -1,25 +1,17 @@ import React from 'react'; -import { Text, Box, Flex, ActionIcon, Tooltip } from '@mantine/core'; -import PushPinIcon from '@mui/icons-material/PushPin'; -import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; -import { useFileContext } from '../../../contexts/FileContext'; +import { Text } from '@mantine/core'; export interface FileStatusIndicatorProps { selectedFiles?: File[]; - isCompleted?: boolean; placeholder?: string; - showFileName?: boolean; - showPinControls?: boolean; } const FileStatusIndicator = ({ selectedFiles = [], - isCompleted = false, - placeholder = "Select a PDF file in the main view to get started", - showFileName = true, - showPinControls = true + placeholder = "Select a PDF file in the main view to get started" }: FileStatusIndicatorProps) => { - const { pinFile, unpinFile, isFilePinned } = useFileContext(); + + // Only show content when no files are selected if (selectedFiles.length === 0) { return ( @@ -28,19 +20,8 @@ const FileStatusIndicator = ({ ); } - if (isCompleted) { - return ( - - ✓ Selected: {showFileName ? selectedFiles[0]?.name : `${selectedFiles.length} file${selectedFiles.length > 1 ? 's' : ''}`} - - ); - } - - return ( - - Selected: {showFileName ? selectedFiles[0]?.name : `${selectedFiles.length} file${selectedFiles.length > 1 ? 's' : ''}`} - - ); + // Return nothing when files are selected + return null; } export default FileStatusIndicator; \ No newline at end of file diff --git a/frontend/src/components/tools/shared/SuggestedToolsSection.tsx b/frontend/src/components/tools/shared/SuggestedToolsSection.tsx new file mode 100644 index 000000000..10977ed23 --- /dev/null +++ b/frontend/src/components/tools/shared/SuggestedToolsSection.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Stack, Text, Divider, SimpleGrid, Card, Group } from '@mantine/core'; +import { useTranslation } from 'react-i18next'; +import { useSuggestedTools } from '../../../hooks/useSuggestedTools'; +export interface SuggestedToolsSectionProps {} + +export function SuggestedToolsSection(): React.ReactElement { + const { t } = useTranslation(); + const suggestedTools = useSuggestedTools(); + + return ( + + + + + {t('editYourNewFiles', 'Edit your new File(s)')} + + + + {suggestedTools.map((tool) => { + const IconComponent = tool.icon; + return ( + + + + + {tool.title} + + + + ); + })} + + + ); +} \ No newline at end of file diff --git a/frontend/src/components/tools/shared/createReviewToolStep.tsx b/frontend/src/components/tools/shared/createReviewToolStep.tsx index faea34023..a35652781 100644 --- a/frontend/src/components/tools/shared/createReviewToolStep.tsx +++ b/frontend/src/components/tools/shared/createReviewToolStep.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import DownloadIcon from '@mui/icons-material/Download'; import ErrorNotification from './ErrorNotification'; import ReviewPanel from './ReviewPanel'; +import { SuggestedToolsSection } from './SuggestedToolsSection'; import { ToolOperationHook } from '../../../hooks/tools/shared/useToolOperation'; export interface ReviewToolStepProps { @@ -31,10 +32,6 @@ export function createReviewToolStep( _noPadding: true }, ( - {operation.status && ( - {operation.status} - )} - ( {t("download", "Download")} )} + + )); } diff --git a/frontend/src/components/tools/shared/createToolFlow.tsx b/frontend/src/components/tools/shared/createToolFlow.tsx index 27496b441..d15a339c9 100644 --- a/frontend/src/components/tools/shared/createToolFlow.tsx +++ b/frontend/src/components/tools/shared/createToolFlow.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Stack } from '@mantine/core'; import { createToolSteps, ToolStepProvider } from './ToolStep'; import OperationButton from './OperationButton'; import { ToolOperationHook } from '../../../hooks/tools/shared/useToolOperation'; @@ -58,44 +59,46 @@ export function createToolFlow(config: ToolFlowConfig) { const steps = createToolSteps(); return ( - - {/* Files Step */} - {steps.createFilesStep({ - selectedFiles: config.files.selectedFiles, - isCollapsed: config.files.isCollapsed, - placeholder: config.files.placeholder, - onCollapsedClick: config.files.onCollapsedClick - })} + + + {/* Files Step */} + {steps.createFilesStep({ + selectedFiles: config.files.selectedFiles, + isCollapsed: config.files.isCollapsed, + placeholder: config.files.placeholder, + onCollapsedClick: config.files.onCollapsedClick + })} - {/* Middle Steps */} - {config.steps.map((stepConfig, index) => - steps.create(stepConfig.title, { - isVisible: stepConfig.isVisible, - isCollapsed: stepConfig.isCollapsed, - onCollapsedClick: stepConfig.onCollapsedClick, - tooltip: stepConfig.tooltip - }, stepConfig.content) - )} + {/* Middle Steps */} + {config.steps.map((stepConfig, index) => + steps.create(stepConfig.title, { + isVisible: stepConfig.isVisible, + isCollapsed: stepConfig.isCollapsed, + onCollapsedClick: stepConfig.onCollapsedClick, + tooltip: stepConfig.tooltip + }, stepConfig.content) + )} - {/* Execute Button */} - {config.executeButton && config.executeButton.isVisible !== false && ( - - )} + {/* Execute Button */} + {config.executeButton && config.executeButton.isVisible !== false && ( + + )} - {/* Review Step */} - {steps.createReviewStep({ - isVisible: config.review.isVisible, - operation: config.review.operation, - title: config.review.title, - onFileClick: config.review.onFileClick - })} - + {/* Review Step */} + {steps.createReviewStep({ + isVisible: config.review.isVisible, + operation: config.review.operation, + title: config.review.title, + onFileClick: config.review.onFileClick + })} + + ); } diff --git a/frontend/src/hooks/useSuggestedTools.ts b/frontend/src/hooks/useSuggestedTools.ts new file mode 100644 index 000000000..ae6d77035 --- /dev/null +++ b/frontend/src/hooks/useSuggestedTools.ts @@ -0,0 +1,59 @@ +import { useMemo } from 'react'; +import { useToolWorkflow } from '../contexts/ToolWorkflowContext'; + +// Material UI Icons +import CompressIcon from '@mui/icons-material/Compress'; +import SwapHorizIcon from '@mui/icons-material/SwapHoriz'; +import CleaningServicesIcon from '@mui/icons-material/CleaningServices'; +import CropIcon from '@mui/icons-material/Crop'; +import TextFieldsIcon from '@mui/icons-material/TextFields'; + +export interface SuggestedTool { + name: string; + title: string; + icon: React.ComponentType; + navigate: () => void; +} + +const ALL_SUGGESTED_TOOLS: Omit[] = [ + { + name: 'compress', + title: 'Compress', + icon: CompressIcon + }, + { + name: 'convert', + title: 'Convert', + icon: SwapHorizIcon + }, + { + name: 'sanitize', + title: 'Sanitize', + icon: CleaningServicesIcon + }, + { + name: 'split', + title: 'Split', + icon: CropIcon + }, + { + name: 'ocr', + title: 'OCR', + icon: TextFieldsIcon + } +]; + +export function useSuggestedTools(): SuggestedTool[] { + const { handleToolSelect, selectedToolKey } = useToolWorkflow(); + + return useMemo(() => { + // Filter out the current tool + const filteredTools = ALL_SUGGESTED_TOOLS.filter(tool => tool.name !== selectedToolKey); + + // Add navigation function to each tool + return filteredTools.map(tool => ({ + ...tool, + navigate: () => handleToolSelect(tool.name) + })); + }, [selectedToolKey, handleToolSelect]); +} \ No newline at end of file diff --git a/frontend/src/tools/Compress.tsx b/frontend/src/tools/Compress.tsx index 893f7485d..c4ddbf74c 100644 --- a/frontend/src/tools/Compress.tsx +++ b/frontend/src/tools/Compress.tsx @@ -1,5 +1,4 @@ import React, { useEffect } from "react"; -import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useFileContext } from "../contexts/FileContext"; @@ -63,9 +62,7 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const hasResults = compressOperation.files.length > 0 || compressOperation.downloadUrl !== null; const settingsCollapsed = !hasFiles || hasResults; - return ( - - {createToolFlow({ + return createToolFlow({ files: { selectedFiles, isCollapsed: hasFiles && !hasResults, @@ -96,9 +93,7 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { title: t("compress.title", "Compression Results"), onFileClick: handleThumbnailClick } - })} - - ); + }); } diff --git a/frontend/src/tools/Convert.tsx b/frontend/src/tools/Convert.tsx index 2b9c9fe8d..b173bcca2 100644 --- a/frontend/src/tools/Convert.tsx +++ b/frontend/src/tools/Convert.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useRef } from "react"; -import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useFileContext } from "../contexts/FileContext"; @@ -100,9 +99,7 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { setCurrentMode('convert'); }; - return ( - - {createToolFlow({ + return createToolFlow({ files: { selectedFiles, isCollapsed: filesCollapsed, @@ -137,9 +134,7 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { onFileClick: handleThumbnailClick, testId: "conversion-results" } - })} - - ); + }); }; export default Convert; diff --git a/frontend/src/tools/OCR.tsx b/frontend/src/tools/OCR.tsx index 7fc2cd457..9910b14eb 100644 --- a/frontend/src/tools/OCR.tsx +++ b/frontend/src/tools/OCR.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from "react"; -import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useFileContext } from "../contexts/FileContext"; @@ -80,15 +79,12 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { }; - const filesCollapsed = expandedStep !== 'files'; const settingsCollapsed = expandedStep !== 'settings'; - return ( - - {createToolFlow({ + return createToolFlow({ files: { selectedFiles, - isCollapsed: hasFiles && !hasResults && filesCollapsed, + isCollapsed: hasFiles || hasResults, }, steps: [ { @@ -137,9 +133,7 @@ const OCR = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { title: t("ocr.results.title", "OCR Results"), onFileClick: handleThumbnailClick } - })} - - ); + }); } export default OCR; diff --git a/frontend/src/tools/Sanitize.tsx b/frontend/src/tools/Sanitize.tsx index 6e2e34559..a98025f35 100644 --- a/frontend/src/tools/Sanitize.tsx +++ b/frontend/src/tools/Sanitize.tsx @@ -1,5 +1,4 @@ import { useEffect } from "react"; -import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useToolFileSelection } from "../contexts/FileSelectionContext"; @@ -64,9 +63,7 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const filesCollapsed = hasFiles || hasResults; const settingsCollapsed = !hasFiles || hasResults; - return ( - - {createToolFlow({ + return createToolFlow({ files: { selectedFiles, isCollapsed: filesCollapsed, @@ -97,9 +94,7 @@ const Sanitize = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { title: t("sanitize.sanitizationResults", "Sanitization Results"), onFileClick: handleThumbnailClick } - })} - - ); + }); } export default Sanitize; diff --git a/frontend/src/tools/Split.tsx b/frontend/src/tools/Split.tsx index 2b4ff1fe9..d1de9290a 100644 --- a/frontend/src/tools/Split.tsx +++ b/frontend/src/tools/Split.tsx @@ -1,5 +1,4 @@ import React, { useEffect } from "react"; -import { Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useFileContext } from "../contexts/FileContext"; @@ -63,9 +62,7 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const filesCollapsed = hasFiles; const settingsCollapsed = !hasFiles || hasResults; - return ( - - {createToolFlow({ + return createToolFlow({ files: { selectedFiles, isCollapsed: filesCollapsed, @@ -96,9 +93,7 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { title: "Split Results", onFileClick: handleThumbnailClick } - })} - - ); + }); } export default Split;