diff --git a/src/lib/components/AIScore.svelte b/src/lib/components/AIScore.svelte
index d34047d0..e212b044 100644
--- a/src/lib/components/AIScore.svelte
+++ b/src/lib/components/AIScore.svelte
@@ -6,7 +6,7 @@
// Use the correct reactive declaration
$: {
- if ($stockTicker && typeof window !== "undefined") {
+ if ($stockTicker) {
// Correctly check if score is neither undefined nor null
$scoreComponent = score !== undefined && score !== null && score !== 0;
}
diff --git a/src/lib/components/BullBearSay.svelte b/src/lib/components/BullBearSay.svelte
deleted file mode 100644
index 5a6f4b94..00000000
--- a/src/lib/components/BullBearSay.svelte
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-{#if Object?.keys(rawData)?.length !== 0}
-
-
-
-
-
-
-
-
- Bull Case vs Bear Case
-
-
-
-
-
-
-
-
-
- {#each tabs as item, i}
-
handleMode(i)}
- class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
- i
- ? 'z-0'
- : ''} "
- >
- {#if activeIdx === i}
-
- {/if}
-
- {item.title}
-
-
- {/each}
-
-
-
-
-
- New
- Updated {formatDate(rawData?.date)}
-
-
-
-
- {#if activeIdx === 0 && data?.user?.tier === "Pro"}
- {rawData?.bullSays}
- {:else if activeIdx === 1 && data?.user?.tier === "Pro"}
- {rawData?.bearSays}
- {:else if activeIdx === 0 && data?.user?.tier !== "Pro"}
-
- {rawData?.bullSays?.slice(0, 150) + "..."}
-
- Unlock content with
- Pro Subscription
-
-
- {:else if activeIdx === 1 && data?.user?.tier !== "Pro"}
-
- {rawData?.bearSays?.slice(0, 150) + "..."}
-
- Unlock content with
- Pro Subscription
-
-
- {/if}
-
-
-
-
-{/if}
diff --git a/src/lib/components/ClinicalTrial.svelte b/src/lib/components/ClinicalTrial.svelte
deleted file mode 100644
index f77bc159..00000000
--- a/src/lib/components/ClinicalTrial.svelte
+++ /dev/null
@@ -1,366 +0,0 @@
-
-
-
-
-
-
- Clinical Trials
-
-
-
-
- {#if data?.user?.tier === "Pro"}
- {#if isLoaded}
- {#if rawData?.length >= 5}
-
-
- The Biotech company {$displayCompanyName} has conducted a total of
- {abbreviateNumber(rawData?.length)} clinical trials. Out of these,
- {numOfActive === 0 ? "none" : numOfActive} are currently active,
- {numOfCompleted} have been completed, {numOfTerminated} were terminated
- and {numOfResults} trials have produced results.
-
-
-
-
-
-
- {/if}
- {:else}
-
- {/if}
- {:else}
-
-
- Unlock content with
-
Pro Subscription
-
- {/if}
-
-
-
-
-
-
-
-
-
-
-
-
- ✕
-
-
-
- Title: {trialTitle}
-
-
- Brief Summary:
- {trialSummary}
-
-
-
-
-
-
- NCT Number
- {trialId}
-
-
- Start Date
- {trialStart}
-
-
- End Date
- {trialEnd}
-
-
-
- Study Status
- {trialStage}
-
-
- Phase Status
- {trialPhase}
-
-
- Study Results
- {trialResult}
-
-
- Sex
- {formatString(trialSex)}
-
-
- Age
- {formatString(trialAge)?.replace("Older_adult", "Older Adult")}
-
-
- Sponsor
- {trialSponsor}
-
-
- Enrollment
- {trialEnrollment}
-
-
- Study Type
- {trialStudyType}
-
-
- Funder Type
- {trialFunderType}
-
-
- Website
- {trialLink}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/components/CorporateLobbying.svelte b/src/lib/components/CorporateLobbying.svelte
deleted file mode 100644
index 462fe0fa..00000000
--- a/src/lib/components/CorporateLobbying.svelte
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
-
- Corporate Lobbying
-
-
-
-
- {#if isLoaded}
- {#if rawData?.length !== 0}
-
-
-
- Explore {$displayCompanyName}'s lobbying strategy by analyzing
- their annual spending to influence lawmakers towards favorable
- regulation and legislation alignment.
-
-
-
-
-
-
-
-
- The company allocated an average of {abbreviateNumber(
- avgAmount,
- true,
- )} annually towards lobbying efforts, reaching its peak at {abbreviateNumber(
- displayMaxLobbying,
- true,
- )} in {displayYear}.
-
-
- {:else}
-
- No data available
-
-
- {/if}
- {:else}
-
- {/if}
-
-
-
-
diff --git a/src/lib/components/ETFSidecard.svelte b/src/lib/components/ETFSidecard.svelte
index ea0161bf..6c94e96b 100644
--- a/src/lib/components/ETFSidecard.svelte
+++ b/src/lib/components/ETFSidecard.svelte
@@ -6,7 +6,6 @@
abbreviateNumber,
sectorNavigation,
} from "$lib/utils";
- import defaultLogo from "$lib/images/stocks/logo/default_logo.png";
import { goto } from "$app/navigation";
@@ -39,7 +38,7 @@
}
$: {
- if ($etfTicker && typeof window !== "undefined") {
+ if ($etfTicker) {
info = data?.getETFProfile?.at(0);
topHoldingList = data?.getETFHoldings?.holdings || [];
topSectorList = data?.getETFSectorWeighting || [];
@@ -215,21 +214,9 @@
>
-
-
-
-
+
{item?.symbol ?? "-"} {item?.symbol ?? "n/a"}
{#if typeof item?.name !== "undefined"}
diff --git a/src/lib/components/News.svelte b/src/lib/components/News.svelte
index 9adfe5bd..b534a026 100644
--- a/src/lib/components/News.svelte
+++ b/src/lib/components/News.svelte
@@ -6,14 +6,12 @@
export let data;
let rawData = [];
- let rawDataPressRelease;
+ let rawDataPressRelease = [];
let newsList = [];
let displaySection = "all";
- let isLoaded = true;
async function getPressRelease() {
- isLoaded = false;
displaySection = "press-releases";
const cachedData = getCache($stockTicker, "getPressRelease");
if (cachedData) {
@@ -31,7 +29,6 @@
rawDataPressRelease = await response?.json();
setCache($stockTicker, rawDataPressRelease, "getPressRelease");
}
- isLoaded = true;
}
function checkIfYoutubeVideo(link: string): string | null {
@@ -67,9 +64,8 @@
: newsList;
$: {
- if (($stockTicker || $etfTicker) && typeof window !== "undefined") {
- isLoaded = true;
- rawData = data?.getNews;
+ if ($stockTicker || $etfTicker) {
+ rawData = data?.getNews || [];
rawDataPressRelease = [];
newsList = rawData?.slice(0, 20) ?? [];
displaySection = "all";
@@ -143,41 +139,76 @@
{#if rawData?.length > 0}
- {#if isLoaded}
- {#if filteredNewsList?.length > 0}
-
- {#each filteredNewsList as item, index}
-
- {#if checkIfYoutubeVideo(item.url)}
- {#if showVideo[index]}
-
-
- VIDEO
-
- {:else}
-
-
-
+ {#if filteredNewsList?.length > 0}
+
+ {#each filteredNewsList as item, index}
+
+ {#if checkIfYoutubeVideo(item.url)}
+ {#if showVideo[index]}
+
+
+ VIDEO
+
+ {:else}
+
+
+
+
handlePlayClick(index)}
+ >
handlePlayClick(index)}
- >
-
-
+ class="absolute left-[50%] top-[50%] z-10 h-[46px] w-[70px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-[#212121] opacity-80 transition-all before:absolute before:left-[50%] before:top-[50%] before:-translate-x-1/2 before:-translate-y-1/2 before:border-y-[11px] before:border-l-[19px] before:border-r-0 before:border-transparent before:border-l-white before:content-[''] group-hover:bg-[#ff0000] group-hover:opacity-100"
+ >
- {/if}
-
+
+ {/if}
+
+ {:else}
+
+
+
+
+
+
+
+
{formatDate(item?.publishedDate)} · {item?.site}
@@ -195,96 +226,48 @@
- {:else}
-
-
- {/if}
-
-
- {/each}
-
- {:else}
-
-
-
-
-
-
-
- No {displaySection === "videos" ? "videos" : "articles"} found
- for this stock.
-
+
+ {/if}
+
+
+ {/each}
+
+ {:else}
+
+
+
+
+
+
+
+ No {displaySection === "videos" ? "videos" : "articles"} found
+ for this stock.
- {/if}
- {#if newsList?.length !== rawData?.length && filteredNewsList?.length > 0 && displaySection === "all"}
-
- Load More News
-
- {/if}
- {:else}
-
{/if}
+ {#if newsList?.length !== rawData?.length && filteredNewsList?.length > 0 && displaySection === "all"}
+
+ Load More News
+
+ {/if}
{:else}
No News article available yet
{/if}
diff --git a/src/lib/components/NextEarnings.svelte b/src/lib/components/NextEarnings.svelte
index 4bc149cb..92edc852 100644
--- a/src/lib/components/NextEarnings.svelte
+++ b/src/lib/components/NextEarnings.svelte
@@ -20,7 +20,7 @@
}
$: {
- if ($stockTicker && typeof window !== "undefined") {
+ if ($stockTicker) {
rawData = data?.getNextEarnings?.next;
epsRatio =
rawData?.epsPrior !== 0
diff --git a/src/lib/components/PastEarnings.svelte b/src/lib/components/PastEarnings.svelte
index e72b714f..87446fcd 100644
--- a/src/lib/components/PastEarnings.svelte
+++ b/src/lib/components/PastEarnings.svelte
@@ -5,8 +5,6 @@
export let userTier;
export let rawData;
- let isLoaded = false;
-
let xData = [];
let tableRevenue = [];
@@ -65,10 +63,8 @@
}
$: {
- if ($stockTicker && typeof window !== "undefined") {
- isLoaded = false;
+ if ($stockTicker) {
prepareDataset();
- isLoaded = true;
}
}
@@ -76,182 +72,163 @@
- {#if isLoaded}
- {#if rawData?.length !== 0}
-
- The average price volatility over this 3-day period is
- {#if userTier !== "Pro"}
- ... Unlock content with
- Pro Subscription
- {:else}
- ±{averageVolatility?.toFixed(2)}% .
- During this period, the reported revenue exceeded expectations
- {positiveRevenueSurprisePercentage}%
- of the time & the reported EPS surpassed analyst estimates
- {positiveEpsSurprisePercentage}% of
- the time.
- {/if}
-
-
diff --git a/src/lib/components/Sidecard.svelte b/src/lib/components/Sidecard.svelte
index 9af68688..6536dfac 100644
--- a/src/lib/components/Sidecard.svelte
+++ b/src/lib/components/Sidecard.svelte
@@ -34,7 +34,7 @@
}
$: {
- if ($stockTicker && typeof window !== "undefined") {
+ if ($stockTicker) {
info = data?.getStockDeck;
ipoDate =
info?.ipoDate !== null && info?.ipoDate?.length > 0
diff --git a/src/lib/components/WIIM.svelte b/src/lib/components/WIIM.svelte
index 454722c7..caee318d 100644
--- a/src/lib/components/WIIM.svelte
+++ b/src/lib/components/WIIM.svelte
@@ -6,8 +6,7 @@
export let data;
- let isLoaded = false;
- let wiim;
+ let wiim = [];
let showFullHistory = false;
function latestInfoDate(inputDate) {
@@ -36,11 +35,9 @@
}
$: {
- if ((get(stockTicker) || get(etfTicker)) && typeof window !== "undefined") {
- isLoaded = false;
+ if (get(stockTicker) || get(etfTicker)) {
showFullHistory = false;
wiim = data?.getWhyPriceMoved || [];
- isLoaded = true;
}
}
@@ -61,185 +58,172 @@
/>
- {#if isLoaded}
- {#if wiim?.length !== 0}
-
- {#each showFullHistory ? wiim : wiim?.slice(0, 2) as item, index}
-
-
-
-
-
-
-
-
-
+ {#if wiim?.length !== 0}
+
+ {#each showFullHistory ? wiim : wiim?.slice(0, 2) as item, index}
+
+
+
+
+
+
+
+
+
-
-
-
-
{formatDate(item?.date)} ·
-
- Source
-
+
+
-
-
- {#if index === 0 && data?.user?.tier !== "Pro"}
-
- {item?.text?.slice(0, 50) + "..."}
- Unlock content with
- Pro Subscription
-
- {:else}
-
- {item?.text}
-
+ >
+
+
+
{/if}
+
+
+ {#if index === 0 && data?.user?.tier !== "Pro"}
+
+ {item?.text?.slice(0, 50) + "..."}
+ Unlock content with
+ Pro Subscription
+
+ {:else}
+
+ {item?.text}
+
+ {/if}
+
-
+
- {/each}
-
-
- {#if wiim?.length > 2}
-
(showFullHistory = !showFullHistory)}
- class="cursor-pointer flex justify-center items-center mt-5"
- >
-
-
- {/if}
- {/if}
- {:else}
-
+ {/each}
+
+ {#if wiim?.length > 2}
+
(showFullHistory = !showFullHistory)}
+ class="cursor-pointer flex justify-center items-center mt-5"
+ >
+
+
+ {/if}
{/if}
diff --git a/src/routes/etf/[tickerID]/+layout.server.ts b/src/routes/etf/[tickerID]/+layout.server.ts
index e26a0616..3d096758 100644
--- a/src/routes/etf/[tickerID]/+layout.server.ts
+++ b/src/routes/etf/[tickerID]/+layout.server.ts
@@ -44,15 +44,15 @@ const fetchWatchlist = async (pb, userId) => {
export const load = async ({ params, locals }) => {
const { apiURL, apiKey, pb, user } = locals;
-
const { tickerID } = params;
const endpoints = [
- "/etf-profile",
+ "/etf-profile",
"/etf-holdings",
"/etf-sector-weighting",
"/stock-dividend",
"/stock-quote",
+ "/pre-post-quote",
"/wiim",
"/one-day-price",
"/stock-news",
@@ -66,23 +66,27 @@ export const load = async ({ params, locals }) => {
];
const [
- getETFProfile,
+ getETFProfile,
getETFHoldings,
getETFSectorWeighting,
getStockDividend,
getStockQuote,
+ getPrePostQuote,
getWhyPriceMoved,
getOneDayPrice,
getNews,
getUserWatchlist,
] = await Promise.all(promises);
+
+
return {
- getETFProfile,
+ getETFProfile,
getETFHoldings,
getETFSectorWeighting,
getStockDividend,
getStockQuote,
+ getPrePostQuote,
getWhyPriceMoved,
getOneDayPrice,
getNews,
@@ -90,4 +94,4 @@ export const load = async ({ params, locals }) => {
companyName: cleanString(getETFProfile?.at(0)?.name),
getParams: params.tickerID,
};
-};
+};
\ No newline at end of file
diff --git a/src/routes/etf/[tickerID]/+layout.svelte b/src/routes/etf/[tickerID]/+layout.svelte
index 3032acee..079e2127 100644
--- a/src/routes/etf/[tickerID]/+layout.svelte
+++ b/src/routes/etf/[tickerID]/+layout.svelte
@@ -22,16 +22,21 @@
import { onMount, onDestroy, afterUpdate } from "svelte";
import { page } from "$app/stores";
import toast from "svelte-french-toast";
- import Markethour from "$lib/components/Markethour.svelte";
+ import { convertTimestamp } from "$lib/utils";
import PriceAlert from "$lib/components/PriceAlert.svelte";
export let data;
+ let prePostData = data?.getPrePostQuote || {};
$: $realtimePrice = data?.getStockQuote?.price?.toFixed(2);
-
+ let oneDayPrice = [];
let previousRealtimePrice = null;
let previousTicker;
let socket;
+ $etfTicker = data?.getParams;
+ $assetType = "stock";
+ $displayCompanyName = data?.companyName;
+
let isScrolled = false;
let y;
@@ -42,16 +47,17 @@
//let availableCash = 0;
let displaySection = "";
+ let displayLegend = {};
function shareContent(url) {
if (navigator.share) {
navigator
- .share({
+ ?.share({
title: document.title,
url,
})
- .then(() => console.log("Content shared successfully."))
- .catch((error) => console.log("Error sharing content:", error));
+ ?.then(() => console.log("Content shared successfully."))
+ ?.catch((error) => console.log("Error sharing content:", error));
} else {
toast.error("Sharing is not supported by your device", {
style: "background: #2A2E39; color: #fff;",
@@ -65,7 +71,12 @@
options: "/options",
"dark-pool": "/dark-pool",
dividends: "/dividends",
+ statistics: "/statistics",
+ metrics: "metrics",
+ forecast: "/forecast",
+ financials: "/financials",
history: "/history",
+ profile: "/profile",
};
if (state !== "overview" && sectionMap[state]) {
@@ -241,14 +252,74 @@
});
$: {
- if (
- $etfTicker &&
- $etfTicker?.length !== 0 &&
- typeof window !== "undefined"
- ) {
+ if ($etfTicker && $etfTicker?.length !== 0) {
// add a check to see if running on client-side
-
+ $etfTicker = data?.getParams;
+ $assetType = "stock";
+ $displayCompanyName = data?.companyName;
$currentPortfolioPrice = data?.getStockQuote?.price;
+ prePostData = data?.getPrePostQuote || {};
+ const output = [...data?.getOneDayPrice] ?? [];
+ oneDayPrice = output?.map((item) => ({
+ time: Date?.parse(item?.time + "Z") / 1000,
+ open: item?.open !== null ? item?.open : NaN,
+ high: item?.high !== null ? item?.high : NaN,
+ low: item?.low !== null ? item?.low : NaN,
+ close: item?.close !== null ? item?.close : NaN,
+ }));
+
+ let change;
+ let currentDataRowOneDay;
+ let baseClose =
+ data?.getStockQuote?.previousClose || oneDayPrice?.at(0)?.open;
+
+ const length = oneDayPrice?.length;
+ for (let i = length - 1; i >= 0; i--) {
+ if (!isNaN(oneDayPrice[i]?.close)) {
+ currentDataRowOneDay = oneDayPrice[i];
+ break;
+ }
+ }
+
+ // Calculate percentage change if baseClose and currentDataRow are valid
+ const closeValue =
+ $realtimePrice !== null && $realtimePrice !== undefined
+ ? $realtimePrice
+ : currentDataRowOneDay?.close || currentDataRowOneDay?.value;
+
+ if (closeValue && baseClose) {
+ change = ((closeValue / baseClose - 1) * 100)?.toFixed(2);
+ }
+
+ // Format date
+ const date = new Date(currentDataRowOneDay?.time * 1000);
+
+ const options = {
+ day: "2-digit",
+ month: "short",
+ year: "numeric",
+ hour: "numeric",
+ minute: "2-digit",
+ timeZone: "UTC",
+ };
+
+ const formattedDate = date?.toLocaleString("en-US", options);
+
+ const safeFormattedDate =
+ formattedDate === "Invalid Date"
+ ? convertTimestamp(data?.getStockQuote?.timestamp)
+ : formattedDate;
+
+ // Set display legend
+ displayLegend = {
+ close:
+ $realtimePrice !== null && $realtimePrice !== undefined
+ ? $realtimePrice
+ : currentDataRowOneDay?.close?.toFixed(2) ||
+ data?.getStockQuote?.price?.toFixed(2),
+ date: safeFormattedDate,
+ change,
+ };
}
}
@@ -256,24 +327,21 @@
(item) => item.user === data?.user?.id && item.ticker?.includes($etfTicker),
);
- $: charNumber = $screenWidth < 640 ? 15 : 25;
+ $: charNumber = $screenWidth < 640 ? 25 : 40;
$: {
- if (
- $etfTicker &&
- typeof window !== "undefined" &&
- $page.url.pathname === `/etf/${$etfTicker}`
- ) {
+ if ($etfTicker && $page.url.pathname === `/etf/${$etfTicker}`) {
displaySection = "overview";
}
}
$: {
- if ($page?.url?.pathname && typeof window !== "undefined") {
+ if ($page?.url?.pathname) {
const parts = $page?.url?.pathname?.split("/");
const sectionMap = {
holdings: "holdings",
options: "options",
+ options: "options",
"dark-pool": "dark-pool",
insider: "insider",
dividends: "dividends",
@@ -292,10 +360,10 @@
-
+
@@ -330,9 +398,7 @@
? "hidden"
: "flex flex-col items-center ml-6 transition-transform ease-in"}
>
-
+
{$etfTicker}
@@ -497,23 +563,19 @@
-
+
-
+
-
+
-
-
{#if data?.user}
@@ -640,22 +702,135 @@
-
+
-
-
- {$etfTicker?.toUpperCase()}
-
-
+
- {$displayCompanyName?.length > charNumber
- ? $displayCompanyName?.slice(0, charNumber) +
- "..."
- : $displayCompanyName}
-
+
+ {$displayCompanyName?.length > charNumber
+ ? $displayCompanyName?.slice(0, charNumber) +
+ "..."
+ : $displayCompanyName}
+ ({$etfTicker?.toUpperCase()})
+
+
+
+
+
+
+ {displayLegend?.close}
+
+
+ {displayLegend?.change}%
+
+
+ {#if !$isOpen}
+ At close:
+ {/if}
+ {displayLegend?.date}
+ {#if $isOpen}
+ - Market open
+ {/if}
+
+
+ {#if Object?.keys(prePostData)?.length !== 0 && !$isOpen}
+
+
+ {prePostData?.price?.toFixed(2)}
+
+
+ {prePostData?.changesPercentage?.toFixed(
+ 2,
+ )}%
+
+
+
+ {#if prePostData?.time?.includes("AM")}
+
+ {:else}
+
+ {/if}
+ {prePostData?.time?.includes("AM")
+ ? "Pre-market"
+ : "After-hours"}
+
{prePostData?.time}
+
+
+ {/if}
+
@@ -664,7 +839,6 @@
-
@@ -676,28 +850,28 @@
on:click={() => changeSection("overview")}
class="p-2 px-5 cursor-pointer {displaySection ===
'overview'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Overview
+
changeSection("holdings")}
class="p-2 px-5 cursor-pointer {displaySection ===
'holdings'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Holdings
-
changeSection("options")}
class="p-2 px-5 cursor-pointer {displaySection ===
'options'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Options
@@ -707,7 +881,7 @@
on:click={() => changeSection("dark-pool")}
class="p-2 px-5 cursor-pointer {displaySection ===
'dark-pool'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Dark Pool
@@ -717,7 +891,7 @@
on:click={() => changeSection("insider")}
class="p-2 px-5 cursor-pointer {displaySection ===
'insider'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Insider
@@ -727,7 +901,7 @@
on:click={() => changeSection("dividends")}
class="p-2 px-5 cursor-pointer {displaySection ===
'dividends'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Dividends
@@ -737,7 +911,7 @@
on:click={() => changeSection("history")}
class="p-2 px-5 cursor-pointer {displaySection ===
'history'
- ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
+ ? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
History
@@ -746,6 +920,7 @@
+
@@ -767,6 +942,7 @@
+
@@ -798,7 +974,7 @@
class="cursor-pointer w-full flex flex-row justify-start items-center mb-5"
>
-
+
{#if item?.ticker?.includes($etfTicker)}
{
- etfTicker.set(data?.getParams?.toUpperCase());
- assetType.set("etf");
- displayCompanyName.set(data?.companyName);
-};
diff --git a/src/routes/etf/[tickerID]/+page.svelte b/src/routes/etf/[tickerID]/+page.svelte
index 7862eb1e..9f156ede 100644
--- a/src/routes/etf/[tickerID]/+page.svelte
+++ b/src/routes/etf/[tickerID]/+page.svelte
@@ -6,22 +6,18 @@
setCache,
numberOfUnreadNotification,
globalForm,
- isCrosshairMoveActive,
realtimePrice,
priceIncrease,
wsBidPrice,
wsAskPrice,
currentPortfolioPrice,
etfTicker,
- displayCompanyName,
- isOpen,
- isBeforeMarketOpen,
- isWeekend,
shouldUpdatePriceChart,
priceChartData,
} from "$lib/store";
import { onDestroy, onMount } from "svelte";
import WIIM from "$lib/components/WIIM.svelte";
+
import News from "$lib/components/News.svelte";
import ETFSidecard from "$lib/components/ETFSidecard.svelte";
@@ -30,8 +26,8 @@
export let data;
export let form;
- let prePostData = {};
let stockDeck = {};
+
$: previousClose = data?.getStockQuote?.previousClose;
//============================================//
const intervals = ["1D", "1W", "1M", "6M", "1Y", "MAX"];
@@ -51,62 +47,71 @@
$: {
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 !== null && $realtimePrice !== undefined
+ ? $realtimePrice
+ : (currentDataRowOneDay?.close ?? currentDataRowOneDay?.value);
+
+ const graphCloseValue =
+ $realtimePrice !== null && $realtimePrice !== undefined
? $realtimePrice
: (currentDataRow?.close ?? currentDataRow?.value);
if (closeValue && baseClose) {
- change = ((closeValue / baseClose - 1) * 100).toFixed(2);
+ 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",
@@ -117,15 +122,7 @@
timeZone: "UTC",
};
- //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"
@@ -135,11 +132,11 @@
// Set display legend
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,
};
}
}
@@ -413,34 +410,8 @@
}
}
- async function getPrePostQuote() {
- if (!$isOpen) {
- const postData = { ticker: $etfTicker, 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);
- }
- }
-
let displayLastLogicalRangeValue;
const fitContentChart = async () => {
@@ -686,19 +657,11 @@
oneMonthPrice = [];
oneYearPrice = [];
maxPrice = [];
- prePostData = {};
output = null;
stockDeck = data?.getETFProfile?.at(0); // 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();
}
}
@@ -708,21 +671,21 @@
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""}
- {$displayCompanyName} ({$etfTicker}) Stock Price, Quote & News · Stocknear
+ {data?.companyName} ({$etfTicker}) Stock Price, Quote & News · Stocknear
@@ -732,11 +695,11 @@
@@ -749,100 +712,7 @@
>
-
-
-
-
-
-
-
- {$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}
-
- {:else}
-
- {/if}
-
- {/if}
-
-
-
-
+
@@ -877,20 +747,6 @@
{/each}
-
- = 0
- ? "before:content-['+'] text-[#00FC50]"
- : "text-[#FF2F1F]"}
- >
- {displayLegend?.change ?? "-"}%
-
- ({displayData})
-
= 0
+ class={displayLegend?.graphChange >= 0
? "before:content-['+'] text-[#00FC50]"
: "text-[#FF2F1F]"}
>
- {displayLegend?.change}%
+ {displayLegend?.graphChange}%
({displayData})
-
+
diff --git a/src/routes/stocks/[tickerID]/+layout.svelte b/src/routes/stocks/[tickerID]/+layout.svelte
index c4100577..0502b996 100644
--- a/src/routes/stocks/[tickerID]/+layout.svelte
+++ b/src/routes/stocks/[tickerID]/+layout.svelte
@@ -254,11 +254,7 @@
});
$: {
- if (
- $stockTicker &&
- $stockTicker?.length !== 0 &&
- typeof window !== "undefined"
- ) {
+ if ($stockTicker && $stockTicker?.length !== 0) {
// add a check to see if running on client-side
$stockTicker = data?.getParams;
$assetType = "stock";
@@ -337,17 +333,13 @@
$: charNumber = $screenWidth < 640 ? 25 : 40;
$: {
- if (
- $stockTicker &&
- typeof window !== "undefined" &&
- $page.url.pathname === `/stocks/${$stockTicker}`
- ) {
+ if ($stockTicker && $page.url.pathname === `/stocks/${$stockTicker}`) {
displaySection = "overview";
}
}
$: {
- if ($page?.url?.pathname && typeof window !== "undefined") {
+ if ($page?.url?.pathname) {
const parts = $page?.url?.pathname?.split("/");
const sectionMap = {
statistics: "statistics",
diff --git a/src/routes/stocks/[tickerID]/+page.svelte b/src/routes/stocks/[tickerID]/+page.svelte
index ffee2a0a..f6f860a2 100644
--- a/src/routes/stocks/[tickerID]/+page.svelte
+++ b/src/routes/stocks/[tickerID]/+page.svelte
@@ -1230,7 +1230,7 @@
-