diff --git a/src/App.tsx b/src/App.tsx index ccf07573..d975efa0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ // src/App.tsx import React, { useState, useCallback, useEffect } from 'react'; -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route, useParams, useNavigate } from 'react-router-dom'; import { Toaster } from 'react-hot-toast'; import { FlyerDisplay } from './features/flyer/FlyerDisplay'; import { ExtractedDataTable } from './features/flyer/ExtractedDataTable'; @@ -300,6 +300,21 @@ function App() { } }, [flyers, selectedFlyer, handleFlyerSelect]); + // New effect to handle routing to a specific flyer ID from the URL + useEffect(() => { + const urlParams = new URLSearchParams(window.location.search); + const flyerIdFromUrl = urlParams.get('flyerId'); // Or parse from path if using /flyers/:id + + if (flyerIdFromUrl && flyers.length > 0) { + const flyerId = parseInt(flyerIdFromUrl, 10); + const flyerToSelect = flyers.find(f => f.flyer_id === flyerId); + if (flyerToSelect && flyerToSelect.flyer_id !== selectedFlyer?.flyer_id) { + handleFlyerSelect(flyerToSelect); + } + } + }, [flyers, handleFlyerSelect, selectedFlyer]); + + useEffect(() => { const findActiveDeals = async () => { if (flyers.length === 0 || localWatchedItems.length === 0) { @@ -626,6 +641,7 @@ function App() { )} + } /> {/* This banner will only appear for users who have interacted with the app but are not logged in. */} @@ -746,4 +762,30 @@ function App() { ); } +/** + * A wrapper component to handle the logic for the /flyers/:flyerId route. + * It extracts the flyerId from the URL and triggers the selection in the parent App component. + */ +const HomePage: React.FC = () => { + const { flyerId } = useParams<{ flyerId: string }>(); + const navigate = useNavigate(); + + useEffect(() => { + // This component's purpose is to set the selected flyer based on the URL. + // The actual rendering is handled by the main App component's state. + // After mounting, we can navigate back to the root path, as the selection + // will have been triggered by the main App's useEffect hook that watches the URL. + // This is a common pattern for using URL params to drive state in a parent component. + if (flyerId) { + // The main App component will see this URL and select the flyer. + // We can then navigate to the root to clean up the URL, while the selection remains. + // A small timeout can ensure the parent component has time to react. + setTimeout(() => navigate('/', { replace: true }), 100); + } + }, [flyerId, navigate]); + + // This component doesn't render anything itself; it's just a controller. + return null; +}; + export default App; \ No newline at end of file diff --git a/src/features/flyer/FlyerUploader.tsx b/src/features/flyer/FlyerUploader.tsx index 0a5a192d..0e7c9b56 100644 --- a/src/features/flyer/FlyerUploader.tsx +++ b/src/features/flyer/FlyerUploader.tsx @@ -1,5 +1,6 @@ // src/features/flyer/FlyerUploader.tsx import React, { useState, useEffect, useRef, useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; import { uploadAndProcessFlyer, getJobStatus } from '../../services/aiApiClient'; import { generateFileChecksum } from '../../utils/checksum'; // Assuming you have this utility import { logger } from '../../services/logger.client'; @@ -21,6 +22,7 @@ export const FlyerUploader: React.FC = ({ onProcessingComple const [jobId, setJobId] = useState(null); const [errorMessage, setErrorMessage] = useState(null); const [isDragging, setIsDragging] = useState(false); + const navigate = useNavigate(); // Use a ref to manage the polling timeout to prevent memory leaks const pollingTimeoutRef = useRef(null); @@ -54,9 +56,7 @@ export const FlyerUploader: React.FC = ({ onProcessingComple // Call the callback to refetch the main flyer list onProcessingComplete(); // Redirect to the new flyer's page after a short delay - setTimeout(() => { - window.location.href = `/flyers/${flyerId}`; - }, 2000); + setTimeout(() => navigate(`/flyers/${flyerId}`), 1500); } else { throw new Error('Job completed but did not return a flyer ID.'); } @@ -89,7 +89,7 @@ export const FlyerUploader: React.FC = ({ onProcessingComple clearTimeout(pollingTimeoutRef.current); } }; - }, [processingState, jobId, onProcessingComplete]); + }, [processingState, jobId, onProcessingComplete, navigate]); const processFile = useCallback(async (file: File) => { setProcessingState('uploading'); setErrorMessage(null); setStatusMessage('Calculating file checksum...');