Home Page (/)
The Home page is just a large version of the logo with a prompt below it to enter a stock ticker to access an analysis for that stock. It then displays a large version of the SearchBar
component.
SearchBar
The search bar will be the main input component for the user. I’ll include it on the HomePage as well as the Header.
It should send new requests to the /stock-analysis
endpoint every time the user types into the search bar. It should then show the results of the query below the search bar. The user should then be able to click the suggestions generated. When clicked the search bar has to send a request with the ticker to /check-analysis
. It should then show a modal with text and two buttons. The text should always be the message key from the API response. The buttons should differ based on the existing_analysis
key. If it’s true the message key will look something like this:
“There is an existing analysis for ‘aapl’ created on 2025-04-06 17:51:38.025720. Do you want to access it or create a new analysis?”
There should be an “Access Existing” and “Create New”. “Access Existing” should just navigate to /stock/{ticker}
where {ticker}
is the ticker the user clicked on. Create New
should send a request to /generate-analysis
said ticker.
If existing_analysis
is false the message will look like this:
“goog was not found in the database. Do you want to generate a new analysis for it?
The two buttons should be “Yes”and “No” with yes sending a request to /generate-analysis
and “No” just closing the modal.
Every time the search bar’s content changes it will send an axios request to the /stock-query
endpoint. This happens with a timeout of 300 ms so there’s a buffer between the requests. If the user clicks outside the bar at any time it will catch it using an event listener and hide the results.
Then comes the clicking of the search results. When clicked the component will send a request to /check-analysis
as described. It will then look for the date in the message using regex and and format it appropriately if found. Then it will open the modal. Also since SearchBar
re-renders a lot (every time the user changes the content) the handleResultClick
is going to be created from scratch every time. To prevent that (so the performance doesn’t suffer) I wrapped handleResultClick
in a useCallback
function. useMemo
doesn’t cut it here because if the individual results were optimized components, receiving a new function instance on every render would cause them to re-render unnecessarily.
Modal
Modal
is it’s own component. It’s props include the basic setter functions again so it can return null when it’s not open and render when it is. They also include functions to run when the modal buttons are clicked. This way all functionality from the Modal
component is set and controlled by the SearchBar
component. Additionally the entire modal component is wrapped in a div with stopPropagation()
so it doesn’t pass on any of the click
events upwards.
handleAccessExisting
navigates the user to /stock/{ticker}
handleGenerateAnalysis
starts the analysis process. It send’s a request to /generate-analysis
as specified above. Then it navigates to the AnalysisLoadingPage. Specifically: /loading-analysis/{data.task_id}/{currentTicker}