diff --git a/src/lib/components/HoverStockChart.svelte b/src/lib/components/HoverStockChart.svelte new file mode 100644 index 00000000..35cac216 --- /dev/null +++ b/src/lib/components/HoverStockChart.svelte @@ -0,0 +1,221 @@ + + +
+ +
+ + {symbol?.length !== 0 ? symbol : "-"} + +
+ +
+
+ + + + +
+
+
+
+
diff --git a/src/routes/api/hover-stock-chart/+server.ts b/src/routes/api/hover-stock-chart/+server.ts new file mode 100644 index 00000000..4269f2ab --- /dev/null +++ b/src/routes/api/hover-stock-chart/+server.ts @@ -0,0 +1,20 @@ +import type { RequestHandler } from "./$types"; + +export const POST: RequestHandler = async ({ request, locals }) => { + const data = await request.json(); + const { apiURL, apiKey } = locals; + + const postData = { ticker: data?.ticker }; + const response = await fetch(apiURL + "/hover-stock-chart", { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-API-KEY": apiKey, + }, + body: JSON.stringify(postData), + }); + + const output = await response.json(); + + return new Response(JSON.stringify(output)); +}; diff --git a/src/routes/etf/[tickerID]/holdings/+page.server.ts b/src/routes/etf/[tickerID]/holdings/+page.server.ts index 4993e205..2bb33d4c 100644 --- a/src/routes/etf/[tickerID]/holdings/+page.server.ts +++ b/src/routes/etf/[tickerID]/holdings/+page.server.ts @@ -1,6 +1,6 @@ export const load = async ({ locals, params }) => { + const { apiKey, apiURL } = locals; const getETFHoldings = async () => { - const { apiKey, apiURL } = locals; const postData = { ticker: params.tickerID, }; diff --git a/src/routes/etf/[tickerID]/holdings/+page.svelte b/src/routes/etf/[tickerID]/holdings/+page.svelte index 02e2c0a7..a0f257ff 100644 --- a/src/routes/etf/[tickerID]/holdings/+page.svelte +++ b/src/routes/etf/[tickerID]/holdings/+page.svelte @@ -5,15 +5,20 @@ displayCompanyName, } from "$lib/store"; import { Button } from "$lib/components/shadcn/button/index.js"; - import { screenWidth } from "$lib/store"; + import { screenWidth, getCache, setCache } from "$lib/store"; import { abbreviateNumber, formatString } from "$lib/utils"; import { onMount } from "svelte"; import { goto } from "$app/navigation"; import TableHeader from "$lib/components/Table/TableHeader.svelte"; + import HoverStockChart from "$lib/components/HoverStockChart.svelte"; export let data; let rawData = data?.getETFHoldings; let holdings = rawData?.slice(0, 50); + let stockChartData = {}; + let change = 0; + let changesPercentage = 0; + let priceData = []; async function handleScroll() { const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height @@ -25,6 +30,40 @@ } } + async function getStockData(ticker: string) { + const cachedData = getCache(ticker, "hoverStockChart"); + if (cachedData) { + stockChartData = cachedData; + } else { + const postData = { ticker: ticker }; + const response = await fetch("/api/hover-stock-chart", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(postData), + }); + + stockChartData = (await response.json()) ?? {}; + + setCache(ticker, stockChartData, "hoverStockChart"); + } + + changesPercentage = stockChartData?.changesPercentage; + change = stockChartData?.change; + + priceData = stockChartData?.history; + + priceData = priceData + ?.map((item) => ({ + time: Date.parse(item.time), // Assuming 'time' is the correct property to parse + value: item?.close ?? null, + })) + .filter( + (item) => item?.value !== 0 && item?.value != null, // Simplified condition + ); + } + onMount(() => { window.addEventListener("scroll", handleScroll); return () => { @@ -254,16 +293,14 @@ - {item?.asset?.length !== 0 ? item?.asset : "-"} + getStockData(item?.asset)} + {stockChartData} + symbol={item?.asset} + {change} + {changesPercentage} + {priceData} + />