From b5f1fcc6db9b1d64f51815699981fd072609fdc3 Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Fri, 22 Nov 2024 01:33:47 +0100 Subject: [PATCH] update stock layout --- src/lib/store.ts | 3 + .../stocks/[tickerID]/+layout.server.ts | 8 +- src/routes/stocks/[tickerID]/+layout.svelte | 225 +++++++++-------- src/routes/stocks/[tickerID]/+page.svelte | 226 +++--------------- 4 files changed, 154 insertions(+), 308 deletions(-) diff --git a/src/lib/store.ts b/src/lib/store.ts index cf1eae8a..b3a99623 100644 --- a/src/lib/store.ts +++ b/src/lib/store.ts @@ -43,6 +43,9 @@ export const clearCache = () => { clientSideCache.set({}); }; +export const displayLegend = writable(>{}); + + export const showCookieConsent = writable(false); export const shouldUpdatePriceChart = writable(false); export const coolMode = writable(false); diff --git a/src/routes/stocks/[tickerID]/+layout.server.ts b/src/routes/stocks/[tickerID]/+layout.server.ts index eae3a072..b32ca117 100644 --- a/src/routes/stocks/[tickerID]/+layout.server.ts +++ b/src/routes/stocks/[tickerID]/+layout.server.ts @@ -42,7 +42,7 @@ const fetchWatchlist = async (pb, userId) => { return output; }; -export const load = async ({ params, locals }) => { +export const load = async ({ params, locals, setHeaders }) => { const { apiURL, apiKey, pb, user } = locals; const { tickerID } = params; @@ -50,6 +50,7 @@ export const load = async ({ params, locals }) => { "/stockdeck", "/analyst-summary-rating", "/stock-quote", + "/pre-post-quote", "/bull-bear-say", "/wiim", "/one-day-price", @@ -70,6 +71,7 @@ export const load = async ({ params, locals }) => { getStockDeck, getAnalystRating, getStockQuote, + getPrePostQuote, getBullBearSay, getWhyPriceMoved, getOneDayPrice, @@ -80,10 +82,14 @@ export const load = async ({ params, locals }) => { getUserWatchlist, ] = await Promise.all(promises); + setHeaders({ "cache-control": "public, max-age=60" }); + + return { getStockDeck, getAnalystRating, getStockQuote, + getPrePostQuote, getBullBearSay, getWhyPriceMoved, getOneDayPrice, diff --git a/src/routes/stocks/[tickerID]/+layout.svelte b/src/routes/stocks/[tickerID]/+layout.svelte index 2c4d6683..32c3afd0 100644 --- a/src/routes/stocks/[tickerID]/+layout.svelte +++ b/src/routes/stocks/[tickerID]/+layout.svelte @@ -13,7 +13,10 @@ priceIncrease, stockTicker, displayCompanyName, + displayLegend, isOpen, + isBeforeMarketOpen, + isWeekend, shouldUpdatePriceChart, priceChartData, } from "$lib/store"; @@ -23,8 +26,10 @@ import toast from "svelte-french-toast"; import Markethour from "$lib/components/Markethour.svelte"; import AIScore from "$lib/components/AIScore.svelte"; + import { convertTimestamp } from "$lib/utils"; export let data; + let prePostData = data?.getPrePostQuote || {}; $: $realtimePrice = data?.getStockQuote?.price?.toFixed(2); let previousRealtimePrice = null; @@ -277,6 +282,7 @@ function handleTypeOfTrade(state:string) // add a check to see if running on client-side $currentPortfolioPrice = data?.getStockQuote?.price; + prePostData = data?.getPrePostQuote || {}; } } @@ -285,7 +291,7 @@ function handleTypeOfTrade(state:string) item.user === data?.user?.id && item.ticker?.includes($stockTicker), ); - $: charNumber = $screenWidth < 640 ? 15 : 25; + $: charNumber = $screenWidth < 640 ? 25 : 40; $: { if ( @@ -326,7 +332,7 @@ function handleTypeOfTrade(state:string) class="bg-[#09090B] w-full max-w-screen sm:max-w-7xl min-h-screen xl:max-w-screen-2xl overflow-hidden" > -
+
@@ -361,9 +367,7 @@ function handleTypeOfTrade(state:string) ? "hidden" : "flex flex-col items-center ml-6 transition-transform ease-in"} > - + {$stockTicker} @@ -673,29 +677,106 @@ function handleTypeOfTrade(state:string)
-
- - {$stockTicker?.toUpperCase()} - - - {$displayCompanyName?.length > charNumber - ? $displayCompanyName?.slice(0, charNumber) + - "..." - : $displayCompanyName} - -
-
- +
+ + {$displayCompanyName?.length > charNumber + ? $displayCompanyName?.slice(0, charNumber) + + "..." + : $displayCompanyName} + ({$stockTicker?.toUpperCase()}) + +
+ +
+
+ +
+
+
+ {$displayLegend?.close} +
+
+ {$displayLegend?.change}% +
+
+ At close: + {$displayLegend?.date} +
+
+ {#if Object?.keys(prePostData)?.length !== 0} +
+
+ {prePostData?.price?.toFixed(2)} +
+
+ {prePostData?.changesPercentage?.toFixed( + 2, + )}% +
+
+ + After-hours: + {convertTimestamp( + prePostData?.time / 1000, + )} +
+
+ {/if} +
@@ -818,103 +899,11 @@ function handleTypeOfTrade(state:string) {/if} - - {#if PriceAlert} {/if} - - - - - - - diff --git a/src/routes/stocks/[tickerID]/+page.svelte b/src/routes/stocks/[tickerID]/+page.svelte index 4bc230f2..395436b0 100644 --- a/src/routes/stocks/[tickerID]/+page.svelte +++ b/src/routes/stocks/[tickerID]/+page.svelte @@ -6,17 +6,14 @@ setCache, numberOfUnreadNotification, globalForm, - isCrosshairMoveActive, realtimePrice, priceIncrease, wsBidPrice, wsAskPrice, + displayLegend, currentPortfolioPrice, stockTicker, displayCompanyName, - isOpen, - isBeforeMarketOpen, - isWeekend, shouldUpdatePriceChart, priceChartData, } from "$lib/store"; @@ -38,7 +35,6 @@ export let data; export let form; - let prePostData = {}; let stockDeck = {}; $: previousClose = data?.getStockQuote?.previousClose; @@ -60,52 +56,55 @@ $: { if (output !== null) { let change; + let graphChange; let currentDataRow; - let baseClose; + let currentDataRowOneDay; + let baseClose = previousClose; + let graphBaseClose; + + const length = oneDayPrice?.length; + for (let i = length - 1; i >= 0; i--) { + if (!isNaN(oneDayPrice[i]?.close)) { + currentDataRowOneDay = oneDayPrice[i]; + break; + } + } // Determine current data row and base close price based on displayData switch (displayData) { - case "1D": - const length = oneDayPrice?.length; - for (let i = length - 1; i >= 0; i--) { - if (!isNaN(oneDayPrice[i]?.close)) { - currentDataRow = oneDayPrice[i]; - break; - } - } - baseClose = previousClose; - break; - case "1W": currentDataRow = oneWeekPrice?.at(-1); // Latest entry for 1 week - baseClose = oneWeekPrice?.[0]?.close; + graphBaseClose = oneWeekPrice?.at(0)?.close; break; case "1M": currentDataRow = oneMonthPrice?.at(-1); // Latest entry for 1 month - baseClose = oneMonthPrice?.[0]?.close; + graphBaseClose = oneMonthPrice?.at(0)?.close; break; case "6M": currentDataRow = sixMonthPrice?.at(-1); // Latest entry for 6 months - baseClose = sixMonthPrice?.[0]?.close; + graphBaseClose = sixMonthPrice?.at(0)?.close; break; case "1Y": currentDataRow = oneYearPrice?.at(-1); // Latest entry for 1 year - baseClose = oneYearPrice?.[0]?.close; + graphBaseClose = oneYearPrice?.at(0)?.close; break; case "MAX": currentDataRow = maxPrice?.at(-1); // Latest entry for MAX range - baseClose = maxPrice?.[0]?.close; + graphBaseClose = maxPrice?.at(0)?.close; break; } // Calculate percentage change if baseClose and currentDataRow are valid const closeValue = - displayData === "1D" && - !$isCrosshairMoveActive && + $realtimePrice !== null + ? $realtimePrice + : (currentDataRowOneDay?.close ?? currentDataRowOneDay?.value); + + const graphCloseValue = $realtimePrice !== null ? $realtimePrice : (currentDataRow?.close ?? currentDataRow?.value); @@ -114,8 +113,12 @@ change = ((closeValue / baseClose - 1) * 100).toFixed(2); } + if (graphCloseValue && graphBaseClose) { + graphChange = ((graphCloseValue / graphBaseClose - 1) * 100).toFixed(2); + } + // Format date - const date = new Date(currentDataRow?.time * 1000); + const date = new Date(currentDataRowOneDay?.time * 1000); const options = { day: "2-digit", @@ -127,14 +130,7 @@ }; //const formattedDate = (displayData === '1D' || displayData === '1W' || displayData === '1M') ? date.toLocaleString('en-GB', options).replace(/\//g, '.') : date.toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' }).replace(/\//g, '.'); - const formattedDate = - displayData === "1D" || displayData === "1W" || displayData === "1M" - ? date.toLocaleString("en-US", options) - : new Date(currentDataRow?.time)?.toLocaleDateString("en-US", { - day: "2-digit", - month: "short", - year: "numeric", - }); + const formattedDate = date?.toLocaleString("en-US", options); const safeFormattedDate = formattedDate === "Invalid Date" @@ -142,13 +138,13 @@ : formattedDate; // Set display legend - displayLegend = { + $displayLegend = { close: - currentDataRow?.value ?? - currentDataRow?.close ?? - data?.getStockQuote?.price, + currentDataRowOneDay?.close?.toFixed(2) ?? + data?.getStockQuote?.price?.toFixed(2), date: safeFormattedDate, change, + graphChange: displayData === "1D" ? change : graphChange, }; } } @@ -422,33 +418,7 @@ } } - async function getPrePostQuote() { - if (!$isOpen) { - const postData = { ticker: $stockTicker, path: "pre-post-quote" }; - const response = await fetch("/api/ticker-data", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(postData), - }); - - prePostData = await response.json(); - } - } - - let currentDataRow = { value: "-", date: "-" }; - - let lineLegend = null; - let displayLegend = { close: "-", date: "-" }; - - function handleSeriesReference(ref) { - try { - lineLegend = ref; - } catch (error) { - console.log(error); - } - } + $displayLegend = { close: "-", date: "-" }; let displayLastLogicalRangeValue; @@ -747,20 +717,11 @@ oneMonthPrice = []; oneYearPrice = []; maxPrice = []; - prePostData = {}; output = null; stockDeck = data?.getStockDeck; // Essential otherwise chart will not be updated since we wait until #layout.server.ts server response is finished - const asyncFunctions = [getPrePostQuote()]; - - Promise.all(asyncFunctions) - .then((results) => { - initializePrice(); - }) - .catch((error) => { - console.error("An error occurred:", error); - }); + initializePrice(); } } @@ -812,99 +773,6 @@
- - - -
-
-
- {$realtimePrice ?? displayLegend?.close} - - {#if $priceIncrease === true} -
- {:else if $priceIncrease === false} -
- {/if} -
- -
- {displayLegend?.change ?? "-"}% - - {displayLegend?.date} -
-
- -
- {#if Object?.keys(prePostData)?.length !== 0 && prePostData?.price !== 0} -
-
- - {prePostData?.price} - - {#if prePostData?.changesPercentage >= 0} - ({prePostData?.changesPercentage}%) - {:else if prePostData?.changesPercentage < 0} - ({prePostData?.changesPercentage}%) - {/if} -
- {#if $isBeforeMarketOpen && !$isOpen && !$isWeekend} -
- Pre-market: - -
- {:else} -
- After-hours: - -
- {/if} -
- {/if} -
-
- - -
- = 0 - ? "before:content-['+'] text-[#00FC50]" - : "text-[#FF2F1F]"} - > - {displayLegend?.change ?? "-"}% - - -
= 0 + class={$displayLegend?.graphChange >= 0 ? "before:content-['+'] text-[#00FC50]" : "text-[#FF2F1F]"} > - {displayLegend?.change}% + {$displayLegend?.graphChange}%