The application displays the Open, High, Low, Close and Volume values along with a line and bar graph visualization for a given stock symbol/ticker on a given date handling appropriate edge cases.
The application was designed based on following edge cases and constraints that I came up with.
- date range in picker to be restricted to last two years excluding current day as we only get the last 2 year's end of the day data for free version.
- if user chooses saturdays and sundays display error and disable submit button as market is closed.
- when some error occurs during fetch the user should know what happened in layman terms and should know whether to wait or proceed again, so display appropriate messages when error response from backend is recieved.
- ondatachange clear screen of any error/previous output.
- empty fields shouldn't be submitted make both input fields required.
- Have necessary try and catch blocks when waiting for a response.
- convert stock symbol input to upper case before sending axios request as Polygon API recognizes only the uppercase form.
- check if server response is ok.
- if server response is ok then filter only the required fields from json object(Object destructuring is used) then send it to the frontend.
- if server response is not ok get the status code, store the message/error and send it as response to the frontend.
- Check if the stock symbol exists and then send request saving number of api calls(not able to complete because of the 5calls/min restriction - GetAllTIckets.js contains the code)
- Have necessary try and catch blocks when waiting for a response.
For the purpose of separation of concerns I have split the page into several components.
- StockForm - To get the input values.
- StockData - To display OHLCV values.
- *StockChart- To visualize the OHLC, neglecting the volume.
- 403 we don't have access to that date.
- 404 sunday or saturday or data not found due to some other reasons.
- 429 5 calls/minute is utilized i.e., to many requests.
- 200 response is ok.
- In order to improve the UX for a large user, we can have the following,
- load balancer such as Nginx to handle large incoming traffic.
- Design the UI to be responsive for all screen sizes(mobiles,Desktops, etc.,).
- Implement server-side caching to store frequently requested stock data.
- Utilize client-side caching to store data temporarily on the user's device.
- For charts and other data visualizations, we can have lazy loading.
- we can use CDN's to deliver static data fast.
- we can set up analytics and monitoring tools to track user behavior, identify bottlenecks, and gain insights to further improve the application's performance.
- we can add dark mode.
- To Improve utility we can add new features such as,
- historical comparison with other stocks based on which the user can invest or sell.
- Price alerts where user can set a buy/sell price for a stock and recieve alerts when it drops below it.
- adding stock screener where user can filter based on yield or market cap
- add social sharing using which people can share interesting insights.
- create a user watchlist where users can watch they performance of favourite stocks like a feed without needing to search and understand.
Learning and understanding React states,Hooks,events, event listners, event listner attributes, event handlers and functions used in this project.
- searchResults is initially set to an empty array([]) using useState Hook.
- setSearchResults- is a function provided by useState Hook to update the searchResults value.
- findIndex is inbuilt method provided to arrays by javascript.
- Used to close the drop the dropdown when clicked outside of the container.
- Used to scroll into view the current element selected using arrowKeys.
- To create a state variable and set the initial state.
- To create a reference varibale which doesn't renrender dependent DOM elements and set the initial state.
```
useEffect(()=>{
const handleOutsideClick = (e) => {
if (searchContainerRef.current && !searchContainerRef.current.contains(e.target)) {
setShowDropdown(false);
}
};
document.addEventListener("click", handleOutsideClick);
return () => {
document.removeEventListener("click", handleOutsideClick);
};
},[]);
```
- This gets triggered only once and as soon as the component is mounted, only once because the dependent array is empty.
- The content inside return gets executed when the component unmounts. In our case event listner is removed thereby avoiding memery leaks.
searchContainerRef.currentchecks if searchContainerRef has the node element been set to it.!searchContainerRef.current.contains(e.target)checks if the element clicked is not inside the refered div element.
- To get all relevant names of stocks, the name can be passed and retrieved in 2 ways,
- Query
- frontend:
axios.get(api/fetch/?name=${name}) - backend:
app.get("api/fetch/",(response,request)=>{ name=req.query.name })
- frontend:
- Path:
- frontend: axios.get(api/fetch/${name})
- backend:
app.get("api/fetch/:name",(response,request)=>{ name=req.params.name })
- Query
In web Development an event is any action that happens in the browser or more specifically inside the DOM.
- example: mouse click, mouse hover, keyboard key press etc.
-
what is event listners?
- In vanilla javascript (that is plain JS without any framworks) event listners are methods available for the objects we create for an HTML element.
const btn = document.querySelector("button");Here btn is the object created for the button element and these object contain methods called eventlistners to listen events (eg: mouseclick) which can be accessed as below.
btn.addEventListner("click", ()=>{ console.log("Button cLicked") })There are 2 parameters to the addEventlistner method
- First Parameter: The event(eg:click) itself.
- Second Parameter: The callback function, which will be called when the event occurs.
- In vanilla javascript (that is plain JS without any framworks) event listners are methods available for the objects we create for an HTML element.
-
What is event handlers properties?
- In vanilla javascript event handler properties are properties available for the objects we create for an HTML element.
const btn = document.querySelector("button");btn.onclick = ()=>{ console.log("Button Clicked"); }
- In vanilla javascript event handler properties are properties available for the objects we create for an HTML element.
-
what is event handler HTML attributes?
- An event handler HTMl attribute is also called an inline event handler.
- An event handler HTML attribute are provided by the HTMl itself and it can used as follows
<!--HTML File--> <button onclick="eventHandlerFunc()">Click Me</button><!--JS File--> function eventHandlerFunc(){ console.log("Button Clicked"); } -
What is an event handler?
- An event handler is a function that is called when a event is triggered and captured by either of the three(event listner, event handler property or event handler HTML attribute).
- The above eventHandlerFunc function is an example of event handler.
-
Which one to use method, property or the attribute?
- Usage of event listner is recommended over the other 2 for complex large scale projects.
- Event listner has the ability to call more than one function for any given event whereas event handler property doesn't.
- Event handler HTML attribute is age old offering and it's always good to seperate HTML from JS so avoid using this.
-
Why do we use event attribute in React if it's not best practise?
- React takes care of it and converts this usage into event listerner.
- A we use attribute in JSX which is not just plain HTML.
-
How to differentiate between an HTML event attribute vs react event attribute?
- React event attributes are camel Cased(onClick) whereas HTML's are small case(onclick).
Understanding Object data modelling
- To Connect to mongo db using connection string
mongoose.connect("mongodb://localhost:27017/<DB NAME>", { useNewUrlParser: true, useUnifiedTopology: true, }); - To create a schema for the model
const <SCHEMA NAME> = mongoose.Schema({ key1: ValueDataType, key2: ValueDataType, keyn: ValueDataType }); - To create a model for interacting with the DB
const <MODEL REFERENCE NAME> = mongoose.model("<MODEL NAME>", <SCHEMA NAME>);Note: The "MODEL NAME" mentioned here will be pluralized and if a collection doesn't exist in the same name a new collection will be created on first insert.
- Function to insert documents into the collection
async function saveToDatabase(ObjectName) { try { await <MODEL REFERENCE NAME>.insertMany(ObjectName); console.log("Saved to the database."); } catch (error) { console.error("Error saving to the database:", error.message); throw error; } } - To insert documents,
await saveToDatabase(ObjectName); - To search for documents,
const results = await <MODEL REFERENCE NAME>.find({ <KEY>: <VALUE> }).select("<KEY>");
- To make auto deploy work for new commits install the app to your repository.
- click here to install
- environment variable values must not be in double quotes.
- as this is a free deployment, server automatically spun down after 15 minutes of inactivity, therefore on first new requests to the server after inactivity there is a slight delay in response for both stock data and stock name search dropdownn
The backend (server) is set to auto deploy (CD-continous deployment) when new changes are been commited to main branch. Exluding the changes made to getALLTickets, StoreAllTickets, searchServer.
- The React frontend is production built using
npm run buildand auto deployed using github workflow.
- high number of api calls for search - use debouncing.(SOLVED)
- incorrect search result since response is out of order - display only the last request made using reqid(SOLVED)
- app gets crashed or hanged due to high volume of data(>34000) that is rendered - reduce the amount of data rendered at any point of time using react-virtualized(SOLVED)
- padding causes overflow in the dropdown - use boxsizing property(SOLVED)
- loading is not set to false when data not found -
- Why searchbar inside stock Form? can't we place it inside formcontainer for a common css
- Loading animation doesn't stop on error response. (SOLVED)
- Show waiting time info only while loading (SOLVED)
