optimize for seo
This commit is contained in:
parent
da8a443ee5
commit
cbefa701ce
@ -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;
|
||||
}
|
||||
|
||||
@ -1,170 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { stockTicker, displayCompanyName } from "$lib/store";
|
||||
import InfoModal from "$lib/components/InfoModal.svelte";
|
||||
import { formatDate } from "$lib/utils";
|
||||
export let data;
|
||||
|
||||
let rawData = {};
|
||||
|
||||
function latestInfoDate(inputDate) {
|
||||
// Convert the input date string to milliseconds since epoch
|
||||
const inputDateMs = new Date(inputDate);
|
||||
|
||||
// Get today's date in milliseconds since epoch
|
||||
const todayMs = Date?.now();
|
||||
|
||||
// Calculate the difference in milliseconds
|
||||
const differenceInMs = todayMs - inputDateMs;
|
||||
|
||||
// Convert milliseconds to days
|
||||
const differenceInDays = Math?.floor(
|
||||
differenceInMs / (1000 * 60 * 60 * 24),
|
||||
);
|
||||
|
||||
// Return the difference in days
|
||||
return differenceInDays <= 1;
|
||||
}
|
||||
|
||||
function handleMode(i) {
|
||||
activeIdx = i;
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: "Bull Case",
|
||||
},
|
||||
{
|
||||
title: "Bear Case",
|
||||
},
|
||||
];
|
||||
|
||||
let activeIdx = 0;
|
||||
|
||||
$: {
|
||||
if ($stockTicker && typeof window !== "undefined") {
|
||||
rawData = data?.getBullBearSay;
|
||||
activeIdx = 0;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if Object?.keys(rawData)?.length !== 0}
|
||||
<div class="space-y-3 overflow-hidden">
|
||||
<!--Start Content-->
|
||||
<div class="w-auto lg:w-full p-1 flex flex-col m-auto">
|
||||
<div class="flex flex-col items-center w-full mb-1">
|
||||
<div class="flex flex-row justify-start mr-auto items-center">
|
||||
<!--<img class="h-10 inline-block mr-2" src={copilotIcon} />-->
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="bullBearCase"
|
||||
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
|
||||
>
|
||||
Bull Case vs Bear Case
|
||||
</label>
|
||||
<InfoModal
|
||||
title={"Bull Case vs Bear Case"}
|
||||
content={`Before investing, examine both perspectives. We offer brief analyst report summaries, highlighting both positive ("Bulls Say") and negative ("Bears Say") viewpoints on ${$displayCompanyName}`}
|
||||
id={"bullBearCase"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Start Header-->
|
||||
<div
|
||||
class="inline-flex justify-center sm:justify-start w-full rounded-md sm:w-auto"
|
||||
>
|
||||
<div
|
||||
class="bg-secondary w-full min-w-24 sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4"
|
||||
>
|
||||
{#each tabs as item, i}
|
||||
<button
|
||||
on:click={() => 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}
|
||||
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx === i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
>
|
||||
{item.title}
|
||||
</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--End Header-->
|
||||
<span class="text-white text-sm italic mt-6 ml-auto">
|
||||
<label
|
||||
class="{latestInfoDate(rawData?.date)
|
||||
? ''
|
||||
: 'hidden'} text-black bg-[#fff] mr-2 font-semibold not-italic text-xs rounded px-2 py-0.5"
|
||||
>New</label
|
||||
>
|
||||
Updated {formatDate(rawData?.date)}
|
||||
</span>
|
||||
<div class="flex mt-5 h-auto">
|
||||
<div
|
||||
class="{activeIdx === 0
|
||||
? 'bg-[#00FC50]'
|
||||
: 'bg-[#FF2F1F]'} w-full max-w-[3px] rounded-l-xl"
|
||||
/>
|
||||
<span class="text-gray-100 ml-3 text-[1rem] w-full">
|
||||
{#if activeIdx === 0 && data?.user?.tier === "Pro"}
|
||||
<p class="pr-1">{rawData?.bullSays}</p>
|
||||
{:else if activeIdx === 1 && data?.user?.tier === "Pro"}
|
||||
<p class="pr-1">{rawData?.bearSays}</p>
|
||||
{:else if activeIdx === 0 && data?.user?.tier !== "Pro"}
|
||||
<p>
|
||||
{rawData?.bullSays?.slice(0, 150) + "..."}
|
||||
<span class="mt-3">
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
</span>
|
||||
</p>
|
||||
{:else if activeIdx === 1 && data?.user?.tier !== "Pro"}
|
||||
<p>
|
||||
{rawData?.bearSays?.slice(0, 150) + "..."}
|
||||
<span class="mt-3">
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
</span>
|
||||
</p>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@ -1,366 +0,0 @@
|
||||
<script lang 'ts'></script>
|
||||
|
||||
<section class="overflow-hidden text-white h-full pb-8">
|
||||
<main class="overflow-hidden">
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="clinicalTrialInfo"
|
||||
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
|
||||
>
|
||||
Clinical Trials
|
||||
</label>
|
||||
<InfoModal
|
||||
title={"Clinical Trial"}
|
||||
content={"Info description coming soon! But first a word of our sponsor skillshare... just kidding"}
|
||||
id={"clinicalTrialInfo"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if data?.user?.tier === "Pro"}
|
||||
{#if isLoaded}
|
||||
{#if rawData?.length >= 5}
|
||||
<div class="w-full flex flex-col items-start">
|
||||
<div class="text-white text-sm sm:text-[1rem] mt-2 mb-2 w-full">
|
||||
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.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pb-2 rounded-md bg-default">
|
||||
<div class="app w-full h-[300px] mt-5">
|
||||
<Chart {init} options={optionsData} class="chart" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<h2 class="mt-10 mr-1 flex flex-row items-center text-white text-xl sm:text-2xl font-bold mb-3">
|
||||
Latest Information
|
||||
</h2>
|
||||
|
||||
<div class="rounded-md sm:min-h-[330px]">
|
||||
<div class="w-full m-auto h-auto max-h-[500px] overflow-x-scroll sm:overflow-hidden sm:overflow-y-scroll scroller ">
|
||||
<table class="table table-sm table-compact table-pin-rows table-pin-cols w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-white shadow-md font-semibold text-sm text-start bg-default">Drug</th>
|
||||
<th class="text-white shadow-md font-semibold text-sm text-start bg-default">Stage</th>
|
||||
<th class="text-white shadow-md font-semibold text-sm text-center bg-default">Phase Status</th>
|
||||
<th class="text-white shadow-md font-semibold text-sm text-end bg-default">Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each displayList as item,index}
|
||||
<tr on:click={() => handleViewData(item)} class="border-y border-gray-800 odd:bg-odd sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] bg-default border-b-[#09090B] cursor-pointer">
|
||||
|
||||
<td class="text-white font-medium whitespace-nowrap">
|
||||
{item["Interventions"]?.length === 0 ? '-' : item["Interventions"]?.length > charNumber ? formatString(item["Interventions"]?.slice(0,charNumber)) + "..." : formatString(item["Interventions"])}
|
||||
</td>
|
||||
<td class="text-white font-medium w-full text-start">
|
||||
{item['Start Date'] === null ? 'n/a' : new Date(item["Start Date"])?.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', daySuffix: '2-digit' })}
|
||||
</td>
|
||||
|
||||
<td class="text-white text-start font-medium">
|
||||
{formatString(item['Study Status'])}
|
||||
</td>
|
||||
|
||||
<td class="text-white text-center font-medium">
|
||||
{item['Phases'] !== 'NA' ? formatString(item["Phases"])?.replace('Phase','') : '-'}
|
||||
</td>
|
||||
|
||||
<td class="text-white text-end font-medium ">
|
||||
{formatString(item["Study Results"])}
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div
|
||||
class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold"
|
||||
>
|
||||
<svg
|
||||
class="mr-1.5 w-5 h-5 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#A3A3A3"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
>
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-2 text-blue-400 hover:sm:text-white"
|
||||
href="/pricing">Pro Subscription</a
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</section>
|
||||
|
||||
<!-- Put this part before </body> tag -->
|
||||
<input type="checkbox" id="clinicalDesktopModal" class="modal-toggle" />
|
||||
|
||||
<label
|
||||
for="clinicalDesktopModal"
|
||||
class="hidden lg:modal modal-bottom sm:modal-middle cursor-pointer"
|
||||
>
|
||||
<label for="clinicalDesktopModal" class="cursor-pointer modal-backdrop"
|
||||
></label>
|
||||
|
||||
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||
<label
|
||||
class="modal-box w-full relative bg-primary h-auto max-h-[900px] overflow-y-scroll"
|
||||
>
|
||||
<label
|
||||
for="clinicalDesktopModal"
|
||||
class="cursor-pointer absolute right-5 top-2 bg-primary text-2xl text-white"
|
||||
>
|
||||
✕
|
||||
</label>
|
||||
|
||||
<h3 class="text-xl font-semibold text-white mt-10">
|
||||
Title: {trialTitle}
|
||||
</h3>
|
||||
<p class="py-4 text-gray-200 bg-primary w-full">
|
||||
<span class="font-semibold text-white">Brief Summary:</span>
|
||||
{trialSummary}
|
||||
</p>
|
||||
|
||||
<table
|
||||
class="table table-sm table-compact bg-primary w-full mt-5 mb-10 text-white"
|
||||
>
|
||||
<tbody>
|
||||
<!-- row 1 -->
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">NCT Number</td>
|
||||
<td class="bg-primary">{trialId}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Start Date</td>
|
||||
<td class="bg-primary">{trialStart}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">End Date</td>
|
||||
<td class="bg-primary">{trialEnd}</td>
|
||||
</tr>
|
||||
<!-- row 2 -->
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Study Status</td>
|
||||
<td class="bg-primary">{trialStage}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Phase Status</td>
|
||||
<td class="bg-primary">{trialPhase}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Study Results</td>
|
||||
<td class="bg-primary">{trialResult}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Sex</td>
|
||||
<td class="bg-primary">{formatString(trialSex)}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Age</td>
|
||||
<td class="bg-primary"
|
||||
>{formatString(trialAge)?.replace("Older_adult", "Older Adult")}</td
|
||||
>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Sponsor</td>
|
||||
<td class="bg-primary">{trialSponsor}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Enrollment</td>
|
||||
<td class="bg-primary">{trialEnrollment}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Study Type</td>
|
||||
<td class="bg-primary">{trialStudyType}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Funder Type</td>
|
||||
<td class="bg-primary">{trialFunderType}</td>
|
||||
</tr>
|
||||
<tr class="border-b border-slate-700">
|
||||
<td class="bg-primary font-semibold">Website</td>
|
||||
<td class="bg-primary"
|
||||
><a
|
||||
class="text-blue-400 sm:hover:text-white"
|
||||
href={trialLink}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">{trialLink}</a
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</label>
|
||||
</label>
|
||||
|
||||
<!--Start ETF Modal-->
|
||||
<div class="lg:hidden drawer drawer-end z-40 overflow-hidden w-screen">
|
||||
<input id="clinicalMobileModal" type="checkbox" class="drawer-toggle" />
|
||||
<div class="drawer-side overflow-hidden">
|
||||
<div class="bg-default min-h-screen w-screen pb-20 overflow-hidden">
|
||||
<label for="clinicalMobileModal" class="absolute left-6 top-6">
|
||||
<svg
|
||||
class="w-6 h-6 inline-block mb-0.5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#fff"
|
||||
d="M9.125 21.1L.7 12.7q-.15-.15-.213-.325T.425 12q0-.2.063-.375T.7 11.3l8.425-8.425q.35-.35.875-.35t.9.375q.375.375.375.875t-.375.875L3.55 12l7.35 7.35q.35.35.35.863t-.375.887q-.375.375-.875.375t-.875-.375Z"
|
||||
/></svg
|
||||
>
|
||||
</label>
|
||||
|
||||
<div class="w-full overflow-hidden overflow-y-scroll p-2">
|
||||
<h3 class="text-xl font-semibold text-white mt-14 p-3">
|
||||
Title: {trialTitle}
|
||||
</h3>
|
||||
<p class="py-4 text-gray-200 w-full p-3">
|
||||
<span class="font-semibold text-white">Brief Summary:</span>
|
||||
{trialSummary}
|
||||
</p>
|
||||
|
||||
<table
|
||||
class="table table-sm table-compact w-full mt-5 mb-10 text-white"
|
||||
>
|
||||
<tbody>
|
||||
<!-- row 1 -->
|
||||
<tr class="border-b border-slate-700 odd:bg-odd">
|
||||
<td class="font-semibold w-full">NCT Number</td>
|
||||
<td class="">{trialId}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Start Date</td>
|
||||
<td class="">{trialStart}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">End Date</td>
|
||||
<td class="">{trialEnd}</td>
|
||||
</tr>
|
||||
<!-- row 2 -->
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Study Status</td>
|
||||
<td class="">{trialStage}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Phase Status</td>
|
||||
<td class="">{trialPhase}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Study Results</td>
|
||||
<td class="">{trialResult}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Sex</td>
|
||||
<td class="">{formatString(trialSex)}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Age</td>
|
||||
<td class=""
|
||||
>{formatString(trialAge)?.replace(
|
||||
"Older_adult",
|
||||
"Older Adult",
|
||||
)}</td
|
||||
>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Sponsor</td>
|
||||
<td class="">{trialSponsor}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Enrollment</td>
|
||||
<td class="">{trialEnrollment}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Study Type</td>
|
||||
<td class="">{trialStudyType}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Funder Type</td>
|
||||
<td class="">{trialFunderType}</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="border-b border-slate-700 odd:bg-odd even:bg-default"
|
||||
>
|
||||
<td class="font-semibold">Website</td>
|
||||
<td class=""
|
||||
><a
|
||||
class="text-blue-400 sm:hover:text-white"
|
||||
href={trialLink}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">{trialLink}</a
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--End ETF Modal-->
|
||||
|
||||
<style>
|
||||
.app {
|
||||
height: 300px;
|
||||
max-width: 100%; /* Ensure chart width doesn't exceed the container */
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.app {
|
||||
height: 210px;
|
||||
}
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,90 +0,0 @@
|
||||
<script lang 'ts'></script>
|
||||
|
||||
<section class="overflow-hidden text-white h-full">
|
||||
<main class="overflow-hidden">
|
||||
<div class="flex flex-row items-center">
|
||||
<label
|
||||
for="lobbyingInfo"
|
||||
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
|
||||
>
|
||||
Corporate Lobbying
|
||||
</label>
|
||||
<InfoModal
|
||||
title={"Corporate Lobbying"}
|
||||
content={"Lobbying the Senate involves special interest groups hiring professional advocates to influence lawmakers and government policies. It is a constitutionally protected activity, but critics argue it can undermine democratic representation by giving disproportionate influence to wealthy and well-organized groups."}
|
||||
id={"lobbyingInfo"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isLoaded}
|
||||
{#if rawData?.length !== 0}
|
||||
<div class="mt-2 pb-8 sm:pb-2 rounded-md bg-default sm:bg-default">
|
||||
<div class="w-full flex flex-col items-start">
|
||||
<div class="text-white text-[1rem] mt-1 sm:mt-3 mb-1 w-full">
|
||||
Explore {$displayCompanyName}'s lobbying strategy by analyzing
|
||||
their annual spending to influence lawmakers towards favorable
|
||||
regulation and legislation alignment.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="app w-full h-[300px]">
|
||||
<Chart {init} options={optionsData} class="chart" />
|
||||
</div>
|
||||
|
||||
<div class="w-full text-white text-[1rem] mt-6">
|
||||
The company allocated an average of {abbreviateNumber(
|
||||
avgAmount,
|
||||
true,
|
||||
)} annually towards lobbying efforts, reaching its peak at {abbreviateNumber(
|
||||
displayMaxLobbying,
|
||||
true,
|
||||
)} in {displayYear}.
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<h2
|
||||
class="mt-10 mb-5 flex justify-center items-center text-3xl font-bold text-slate-700 m-auto"
|
||||
>
|
||||
No data available
|
||||
<svg
|
||||
class="w-10 sm:w-12 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#334155"
|
||||
d="M18.68 12.32a4.49 4.49 0 0 0-6.36.01a4.49 4.49 0 0 0 0 6.36a4.508 4.508 0 0 0 5.57.63L21 22.39L22.39 21l-3.09-3.11c1.13-1.77.87-4.09-.62-5.57m-1.41 4.95c-.98.98-2.56.97-3.54 0c-.97-.98-.97-2.56.01-3.54c.97-.97 2.55-.97 3.53 0c.97.98.97 2.56 0 3.54M10.9 20.1a6.527 6.527 0 0 1-1.48-2.32C6.27 17.25 4 15.76 4 14v3c0 2.21 3.58 4 8 4c-.4-.26-.77-.56-1.1-.9M4 9v3c0 1.68 2.07 3.12 5 3.7v-.2c0-.93.2-1.85.58-2.69C6.34 12.3 4 10.79 4 9m8-6C7.58 3 4 4.79 4 7c0 2 3 3.68 6.85 4h.05c1.2-1.26 2.86-2 4.6-2c.91 0 1.81.19 2.64.56A3.215 3.215 0 0 0 20 7c0-2.21-3.58-4-8-4Z"
|
||||
/></svg
|
||||
>
|
||||
</h2>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.app {
|
||||
height: 300px;
|
||||
max-width: 100%; /* Ensure chart width doesn't exceed the container */
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.app {
|
||||
height: 230px;
|
||||
}
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -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 @@
|
||||
>
|
||||
<td class="">
|
||||
<div class="flex flex-row items-center">
|
||||
<div
|
||||
class="rounded-full w-10 h-10 relative flex items-center justify-center"
|
||||
>
|
||||
<img
|
||||
style="clip-path: circle(50%);"
|
||||
class="w-6 h-6 rounded-full"
|
||||
src={item?.symbol?.length !== 0
|
||||
? `https://financialmodelingprep.com/image-stock/${item?.symbol}.png`
|
||||
: defaultLogo}
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col ml-3 w-full">
|
||||
<div class="flex flex-col w-full">
|
||||
<span class="text-sm font-medium"
|
||||
>{item?.symbol ?? "-"}</span
|
||||
>{item?.symbol ?? "n/a"}</span
|
||||
>
|
||||
<span class="text-white text-sm">
|
||||
{#if typeof item?.name !== "undefined"}
|
||||
|
||||
@ -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 @@
|
||||
</div>
|
||||
|
||||
{#if rawData?.length > 0}
|
||||
{#if isLoaded}
|
||||
{#if filteredNewsList?.length > 0}
|
||||
<div class="grid grid-cols-1 gap-2 pb-5 pt-5">
|
||||
{#each filteredNewsList as item, index}
|
||||
<div class="w-full flex flex-col bg-default rounded-md m-auto">
|
||||
{#if checkIfYoutubeVideo(item.url)}
|
||||
{#if showVideo[index]}
|
||||
<!-- Show the YouTube iframe when the user clicks play -->
|
||||
<div class="w-full aspect-video mb-4">
|
||||
<iframe
|
||||
class="w-full h-full rounded-md border border-gray-800"
|
||||
src={`https://www.youtube.com/embed/${checkIfYoutubeVideo(item.url)}`}
|
||||
frameborder="0"
|
||||
allow="clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Show the image placeholder with a play button -->
|
||||
<div class="w-full aspect-video">
|
||||
<div class="mb-3 sm:order-3 lg:pr-2">
|
||||
{#if filteredNewsList?.length > 0}
|
||||
<div class="grid grid-cols-1 gap-2 pb-5 pt-5">
|
||||
{#each filteredNewsList as item, index}
|
||||
<div class="w-full flex flex-col bg-default rounded-md m-auto">
|
||||
{#if checkIfYoutubeVideo(item.url)}
|
||||
{#if showVideo[index]}
|
||||
<!-- Show the YouTube iframe when the user clicks play -->
|
||||
<div class="w-full aspect-video mb-4">
|
||||
<iframe
|
||||
class="w-full h-full rounded-md border border-gray-800"
|
||||
src={`https://www.youtube.com/embed/${checkIfYoutubeVideo(item.url)}`}
|
||||
frameborder="0"
|
||||
allow="clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Show the image placeholder with a play button -->
|
||||
<div class="w-full aspect-video">
|
||||
<div class="mb-3 sm:order-3 lg:pr-2">
|
||||
<div
|
||||
class="group relative block cursor-pointer bg-black bg-cover bg-[center_50%] object-contain after:block after:pb-[56.25%] after:content-[''] rounded-sm focus:outline-none focus:ring-2 focus:ring-blue-brand_light focus:ring-offset-2"
|
||||
style="background-image: url({item?.image});"
|
||||
tabindex="0"
|
||||
on:click={() => handlePlayClick(index)}
|
||||
>
|
||||
<div
|
||||
class="group relative block cursor-pointer bg-black bg-cover bg-[center_50%] object-contain after:block after:pb-[56.25%] after:content-[''] rounded-sm focus:outline-none focus:ring-2 focus:ring-blue-brand_light focus:ring-offset-2"
|
||||
style="background-image: url({item?.image});"
|
||||
tabindex="0"
|
||||
on:click={() => handlePlayClick(index)}
|
||||
>
|
||||
<div
|
||||
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"
|
||||
></div>
|
||||
</div>
|
||||
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"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-3 w-full">
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-3 w-full">
|
||||
<h3 class="text-sm text-white/80 truncate mb-2">
|
||||
{formatDate(item?.publishedDate)} · {item?.site}
|
||||
</h3>
|
||||
<a
|
||||
href={item?.url}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
class="text-lg sm:text-xl font-bold text-white"
|
||||
>
|
||||
{item?.title}
|
||||
<p class="text-white text-sm mt-2 font-normal">
|
||||
{item?.text?.length > 200
|
||||
? item?.text?.slice(0, 200) + "..."
|
||||
: item?.text}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Default news article display -->
|
||||
<div class="w-full flex flex-col sm:flex-row">
|
||||
<a
|
||||
href={item?.url}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
class="w-full sm:max-w-56 h-fit max-h-96 sm:mr-3 border border-gray-800 rounded-md"
|
||||
>
|
||||
<div class="flex-shrink-0 m-auto">
|
||||
<img
|
||||
src={item?.image}
|
||||
class="h-auto w-full rounded-md"
|
||||
alt="news image"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<div class="mt-3 sm:mt-0 w-full">
|
||||
<h3 class="text-sm text-white/80 truncate mb-2">
|
||||
{formatDate(item?.publishedDate)} · {item?.site}
|
||||
</h3>
|
||||
@ -195,96 +226,48 @@
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Default news article display -->
|
||||
<div class="w-full flex flex-col sm:flex-row">
|
||||
<a
|
||||
href={item?.url}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
class="w-full sm:max-w-56 h-fit max-h-96 sm:mr-3 border border-gray-800 rounded-md"
|
||||
>
|
||||
<div class="flex-shrink-0 m-auto">
|
||||
<img
|
||||
src={item?.image}
|
||||
class="h-auto w-full rounded-md"
|
||||
alt="news image"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<div class="mt-3 sm:mt-0 w-full">
|
||||
<h3 class="text-sm text-white/80 truncate mb-2">
|
||||
{formatDate(item?.publishedDate)} · {item?.site}
|
||||
</h3>
|
||||
<a
|
||||
href={item?.url}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
class="text-lg sm:text-xl font-bold text-white"
|
||||
>
|
||||
{item?.title}
|
||||
<p class="text-white text-sm mt-2 font-normal">
|
||||
{item?.text?.length > 200
|
||||
? item?.text?.slice(0, 200) + "..."
|
||||
: item?.text}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<hr class="border-gray-600 w-full m-auto mt-5 mb-5" />
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-5 mt-4 px-3 xs:px-4 sm:px-0">
|
||||
<div class="border-l-4 border-white p-4 text-white">
|
||||
<div class="flex flex-row items-center">
|
||||
<svg
|
||||
class="h-6 w-6"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:40px"
|
||||
aria-hidden="true"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
<div class="ml-3 w-full sm:ml-4">
|
||||
<div class="flex w-full flex-row justify-between">
|
||||
<div>
|
||||
No {displaySection === "videos" ? "videos" : "articles"} found
|
||||
for this stock.
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<hr class="border-gray-600 w-full m-auto mt-5 mb-5" />
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-5 mt-4 px-3 xs:px-4 sm:px-0">
|
||||
<div class="border-l-4 border-white p-4 text-white">
|
||||
<div class="flex flex-row items-center">
|
||||
<svg
|
||||
class="h-6 w-6"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:40px"
|
||||
aria-hidden="true"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
>
|
||||
<div class="ml-3 w-full sm:ml-4">
|
||||
<div class="flex w-full flex-row justify-between">
|
||||
<div>
|
||||
No {displaySection === "videos" ? "videos" : "articles"} found
|
||||
for this stock.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if newsList?.length !== rawData?.length && filteredNewsList?.length > 0 && displaySection === "all"}
|
||||
<label
|
||||
on:click={loadMoreData}
|
||||
class="shadow-lg rounded-md cursor-pointer w-5/6 sm:w-full flex justify-center items-center py-3 h-full text-sm sm:text-[1rem] text-center font-semibold text-black m-auto sm:hover:bg-gray-300 bg-[#fff]"
|
||||
>
|
||||
Load More News
|
||||
</label>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if newsList?.length !== rawData?.length && filteredNewsList?.length > 0 && displaySection === "all"}
|
||||
<label
|
||||
on:click={loadMoreData}
|
||||
class="shadow-lg rounded-md cursor-pointer w-5/6 sm:w-full flex justify-center items-center py-3 h-full text-sm sm:text-[1rem] text-center font-semibold text-black m-auto sm:hover:bg-gray-300 bg-[#fff]"
|
||||
>
|
||||
Load More News
|
||||
</label>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="text-white"> No News article available yet </span>
|
||||
{/if}
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($stockTicker && typeof window !== "undefined") {
|
||||
if ($stockTicker) {
|
||||
rawData = data?.getNextEarnings?.next;
|
||||
epsRatio =
|
||||
rawData?.epsPrior !== 0
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -76,182 +72,163 @@
|
||||
<section class="overflow-hidden text-white h-full pb-8 sm:pb-2">
|
||||
<main class="overflow-hidden">
|
||||
<div class="w-full m-auto">
|
||||
{#if isLoaded}
|
||||
{#if rawData?.length !== 0}
|
||||
<span class="">
|
||||
The average price volatility over this 3-day period is
|
||||
{#if userTier !== "Pro"}
|
||||
... Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
{:else}
|
||||
<span class="font-bold">±{averageVolatility?.toFixed(2)}%</span>.
|
||||
During this period, the reported revenue exceeded expectations
|
||||
<span class="font-bold">{positiveRevenueSurprisePercentage}%</span
|
||||
>
|
||||
of the time & the reported EPS surpassed analyst estimates
|
||||
<span class="font-bold">{positiveEpsSurprisePercentage}%</span> of
|
||||
the time.
|
||||
{/if}
|
||||
</span>
|
||||
<div
|
||||
class="no-scrollbar flex justify-start items-center w-screen sm:w-full mt-3 m-auto overflow-x-scroll pr-5 sm:pr-0"
|
||||
{#if rawData?.length !== 0}
|
||||
<span class="">
|
||||
The average price volatility over this 3-day period is
|
||||
{#if userTier !== "Pro"}
|
||||
... Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
{:else}
|
||||
<span class="font-bold">±{averageVolatility?.toFixed(2)}%</span>.
|
||||
During this period, the reported revenue exceeded expectations
|
||||
<span class="font-bold">{positiveRevenueSurprisePercentage}%</span>
|
||||
of the time & the reported EPS surpassed analyst estimates
|
||||
<span class="font-bold">{positiveEpsSurprisePercentage}%</span> of the
|
||||
time.
|
||||
{/if}
|
||||
</span>
|
||||
<div
|
||||
class="no-scrollbar flex justify-start items-center w-screen sm:w-full mt-3 m-auto overflow-x-scroll pr-5 sm:pr-0"
|
||||
>
|
||||
<table
|
||||
class="table table-sm table-pin-cols table-compact rounded-none sm:rounded-md w-full bg-table border border-gray-800"
|
||||
>
|
||||
<table
|
||||
class="table table-sm table-pin-cols table-compact rounded-none sm:rounded-md w-full bg-table border border-gray-800"
|
||||
>
|
||||
<thead class="">
|
||||
<tr class="">
|
||||
<th
|
||||
class="bg-primary border-b border-[#000] text-white font-semibold text-sm text-start"
|
||||
>Date</th
|
||||
<thead class="">
|
||||
<tr class="">
|
||||
<th
|
||||
class="bg-primary border-b border-[#000] text-white font-semibold text-sm text-start"
|
||||
>Date</th
|
||||
>
|
||||
{#each xData as item}
|
||||
<td
|
||||
class="z-20 bg-primary border-b border-[#000] text-white font-semibold text-sm text-end bg-default"
|
||||
>{item}</td
|
||||
>
|
||||
{#each xData as item}
|
||||
<td
|
||||
class="z-20 bg-primary border-b border-[#000] text-white font-semibold text-sm text-end bg-default"
|
||||
>{item}</td
|
||||
>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="shadow-md">
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="shadow-md">
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Reported Revenue
|
||||
</th>
|
||||
{#each tableRevenue as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
Reported Revenue
|
||||
</th>
|
||||
{#each tableRevenue as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
>{@html abbreviateNumber(item, false, true)}</span
|
||||
>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{@html abbreviateNumber(item, false, true)}</span>
|
||||
{:else}
|
||||
{@html abbreviateNumber(item, false, true)}
|
||||
n/a
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{:else}
|
||||
{@html abbreviateNumber(item, false, true)}
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Est. Revenue
|
||||
</th>
|
||||
{#each tableRevenueEst as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
Est. Revenue
|
||||
</th>
|
||||
{#each tableRevenueEst as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
>{@html abbreviateNumber(item, false, true)}</span
|
||||
>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{@html abbreviateNumber(item, false, true)}</span>
|
||||
{:else}
|
||||
{@html abbreviateNumber(item, false, true)}
|
||||
n/a
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{:else}
|
||||
{@html abbreviateNumber(item, false, true)}
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Revenue Surprise
|
||||
</th>
|
||||
{#each tableRevenueSurprise as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
Revenue Surprise
|
||||
</th>
|
||||
{#each tableRevenueSurprise as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
: item < 0
|
||||
? "text-[#FF2F1F]"
|
||||
: ""}
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
{:else}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
@ -261,133 +238,133 @@
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Reported EPS
|
||||
</th>
|
||||
{#each tableEPS as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{abbreviateNumber(item)}</span>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
{:else}
|
||||
{abbreviateNumber(item)}
|
||||
n/a
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{:else}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
: item < 0
|
||||
? "text-[#FF2F1F]"
|
||||
: ""}
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Reported EPS
|
||||
</th>
|
||||
{#each tableEPS as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
Est. EPS
|
||||
</th>
|
||||
{#each tableEPSEst as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{abbreviateNumber(item)}</span>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{abbreviateNumber(item)}</span>
|
||||
{:else}
|
||||
{abbreviateNumber(item)}
|
||||
n/a
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{:else}
|
||||
{abbreviateNumber(item)}
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Est. EPS
|
||||
</th>
|
||||
{#each tableEPSEst as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-medium bg-default"
|
||||
>
|
||||
EPS Surprise
|
||||
</th>
|
||||
{#each tableEPSSurprise as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
: item < 0
|
||||
? "text-[#FF2F1F]"
|
||||
: ""}
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span>{abbreviateNumber(item)}</span>
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
{:else}
|
||||
{abbreviateNumber(item)}
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
EPS Surprise
|
||||
</th>
|
||||
{#each tableEPSSurprise as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
@ -397,64 +374,65 @@
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Volatility
|
||||
</th>
|
||||
{#each tableVolatility as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
±{abbreviateNumber(item)}%
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
{:else}
|
||||
<span
|
||||
class={item > 0
|
||||
? "text-[#00FC50] before:content-['+']"
|
||||
: item < 0
|
||||
? "text-[#FF2F1F]"
|
||||
: ""}
|
||||
>
|
||||
{abbreviateNumber(item)}%
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<tr class="bg-primary border-b-[#27272A]">
|
||||
<th
|
||||
class="bg-primary whitespace-nowrap text-sm sm:text-[1rem] text-white text-start font-medium border-b border-[#27272A]"
|
||||
>
|
||||
Volatility
|
||||
</th>
|
||||
{#each tableVolatility as item, index}
|
||||
<td
|
||||
class="text-white text-sm sm:text-[1rem] text-end font-semibold bg-default"
|
||||
>
|
||||
{#if index !== 0}
|
||||
{#if userTier !== "Pro"}
|
||||
<a
|
||||
class="inline-block ml-0.5 text-white whitespace-nowrap font-normal"
|
||||
href="/pricing"
|
||||
>
|
||||
Pro
|
||||
<svg
|
||||
class="w-4 h-4 ml-0.5 mb-1 inline-block text-[#A3A3A3]"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
{:else if item !== undefined && item !== null}
|
||||
±{abbreviateNumber(item)}%
|
||||
{:else}
|
||||
n/a
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
{:else}
|
||||
±{abbreviateNumber(item)}%
|
||||
{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($stockTicker && typeof window !== "undefined") {
|
||||
if ($stockTicker) {
|
||||
info = data?.getStockDeck;
|
||||
ipoDate =
|
||||
info?.ipoDate !== null && info?.ipoDate?.length > 0
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -61,185 +58,172 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isLoaded}
|
||||
{#if wiim?.length !== 0}
|
||||
<div class="mt-5">
|
||||
{#each showFullHistory ? wiim : wiim?.slice(0, 2) as item, index}
|
||||
<div
|
||||
class="w-full {index === 1 && !showFullHistory && wiim?.length > 2
|
||||
? 'opacity-[0.5]'
|
||||
: ''} "
|
||||
>
|
||||
<div class="relative">
|
||||
<div class="">
|
||||
<div class="flex justify-center">
|
||||
<!--Start Item-->
|
||||
<div class="flex flex-row items-center w-full mb-8">
|
||||
<!-- Vertical Line -->
|
||||
<div
|
||||
class="w-1 h-full mr-4 rounded-lg {item?.changesPercentage ===
|
||||
'-'
|
||||
? 'bg-white'
|
||||
: item?.changesPercentage >= 0
|
||||
? 'bg-[#00FC50]'
|
||||
: 'bg-[#FF2F1F]'}"
|
||||
></div>
|
||||
<!-- Item Content -->
|
||||
{#if wiim?.length !== 0}
|
||||
<div class="mt-5">
|
||||
{#each showFullHistory ? wiim : wiim?.slice(0, 2) as item, index}
|
||||
<div
|
||||
class="w-full {index === 1 && !showFullHistory && wiim?.length > 2
|
||||
? 'opacity-[0.5]'
|
||||
: ''} "
|
||||
>
|
||||
<div class="relative">
|
||||
<div class="">
|
||||
<div class="flex justify-center">
|
||||
<!--Start Item-->
|
||||
<div class="flex flex-row items-center w-full mb-8">
|
||||
<!-- Vertical Line -->
|
||||
<div
|
||||
class="w-1 h-full mr-4 rounded-lg {item?.changesPercentage ===
|
||||
'-'
|
||||
? 'bg-white'
|
||||
: item?.changesPercentage >= 0
|
||||
? 'bg-[#00FC50]'
|
||||
: 'bg-[#FF2F1F]'}"
|
||||
></div>
|
||||
<!-- Item Content -->
|
||||
|
||||
<div class="w-full h-full">
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="flex flex-row items-start w-full">
|
||||
<span class="text-white text-sm"
|
||||
>{formatDate(item?.date)} ·
|
||||
<a
|
||||
href={item?.url}
|
||||
class="inline-block text-sm text-white sm:hover:underline sm:hover:underline-offset-4"
|
||||
>
|
||||
Source
|
||||
</a></span
|
||||
<div class="w-full h-full">
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="flex flex-row items-start w-full">
|
||||
<span class="text-white text-sm"
|
||||
>{formatDate(item?.date)} ·
|
||||
<a
|
||||
href={item?.url}
|
||||
class="inline-block text-sm text-white sm:hover:underline sm:hover:underline-offset-4"
|
||||
>
|
||||
{#if latestInfoDate(item?.date)}
|
||||
<label
|
||||
class="bg-[#fff] rounded text-black font-semibold text-xs px-2 py-0.5 ml-3"
|
||||
>New</label
|
||||
>
|
||||
{/if}
|
||||
<div
|
||||
class="text-white text-sm sm:text-[1rem] ml-auto font-medium"
|
||||
Source
|
||||
</a></span
|
||||
>
|
||||
{#if latestInfoDate(item?.date)}
|
||||
<label
|
||||
class="bg-[#fff] rounded text-black font-semibold text-xs px-2 py-0.5 ml-3"
|
||||
>New</label
|
||||
>
|
||||
{#if item?.changesPercentage >= 0}
|
||||
<span class="text-[#00FC50] inline-block"
|
||||
>+{item?.changesPercentage}%</span
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 hidden sm:inline-block"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
transform="rotate(180)matrix(-1, 0, 0, 1, 0, 0)"
|
||||
><g id="SVGRepo_bgCarrier" stroke-width="0"
|
||||
></g><g
|
||||
id="SVGRepo_tracerCarrier"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></g><g id="SVGRepo_iconCarrier">
|
||||
<g clip-path="url(#clip0_1076_36065)">
|
||||
<path
|
||||
d="M1.70711 5.29289C1.31658 4.90237 0.683417 4.90237 0.292893 5.29289C-0.0976311 5.68342 -0.0976311 6.31658 0.292893 6.70711L7.79289 14.2071C8.18342 14.5976 8.81658 14.5976 9.20711 14.2071L13.5 9.91421L20.5858 17H17C16.4477 17 16 17.4477 16 18C16 18.5523 16.4477 19 17 19H22.9993L23.003 19C23.1375 18.9996 23.2657 18.9727 23.3828 18.9241C23.5007 18.8753 23.6112 18.803 23.7071 18.7071C23.8902 18.524 23.9874 18.2877 23.9989 18.048C23.9996 18.032 24 18.016 24 18V12C24 11.4477 23.5523 11 23 11C22.4477 11 22 11.4477 22 12V15.5858L14.2071 7.79289C13.8166 7.40237 13.1834 7.40237 12.7929 7.79289L8.5 12.0858L1.70711 5.29289Z"
|
||||
{/if}
|
||||
<div
|
||||
class="text-white text-sm sm:text-[1rem] ml-auto font-medium"
|
||||
>
|
||||
{#if item?.changesPercentage >= 0}
|
||||
<span class="text-[#00FC50] inline-block"
|
||||
>+{item?.changesPercentage}%</span
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 hidden sm:inline-block"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
transform="rotate(180)matrix(-1, 0, 0, 1, 0, 0)"
|
||||
><g id="SVGRepo_bgCarrier" stroke-width="0"
|
||||
></g><g
|
||||
id="SVGRepo_tracerCarrier"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></g><g id="SVGRepo_iconCarrier">
|
||||
<g clip-path="url(#clip0_1076_36065)">
|
||||
<path
|
||||
d="M1.70711 5.29289C1.31658 4.90237 0.683417 4.90237 0.292893 5.29289C-0.0976311 5.68342 -0.0976311 6.31658 0.292893 6.70711L7.79289 14.2071C8.18342 14.5976 8.81658 14.5976 9.20711 14.2071L13.5 9.91421L20.5858 17H17C16.4477 17 16 17.4477 16 18C16 18.5523 16.4477 19 17 19H22.9993L23.003 19C23.1375 18.9996 23.2657 18.9727 23.3828 18.9241C23.5007 18.8753 23.6112 18.803 23.7071 18.7071C23.8902 18.524 23.9874 18.2877 23.9989 18.048C23.9996 18.032 24 18.016 24 18V12C24 11.4477 23.5523 11 23 11C22.4477 11 22 11.4477 22 12V15.5858L14.2071 7.79289C13.8166 7.40237 13.1834 7.40237 12.7929 7.79289L8.5 12.0858L1.70711 5.29289Z"
|
||||
fill="#00FC50"
|
||||
></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1076_36065">
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#00FC50"
|
||||
></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1076_36065">
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#00FC50"
|
||||
></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</g></svg
|
||||
>
|
||||
{:else if item?.changesPercentage < 0}
|
||||
<span class="text-[#FF2F1F] inline-block"
|
||||
>{item?.changesPercentage}%
|
||||
</span>
|
||||
<svg
|
||||
class="w-5 h-5 hidden sm:inline-block"
|
||||
viewBox="0 0 24 24"
|
||||
fill="#FF2F1F"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><g id="SVGRepo_bgCarrier" stroke-width="0"
|
||||
></g><g
|
||||
id="SVGRepo_tracerCarrier"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></g><g id="SVGRepo_iconCarrier">
|
||||
<g clip-path="url(#clip0_1076_36065)">
|
||||
<path
|
||||
d="M1.70711 5.29289C1.31658 4.90237 0.683417 4.90237 0.292893 5.29289C-0.0976311 5.68342 -0.0976311 6.31658 0.292893 6.70711L7.79289 14.2071C8.18342 14.5976 8.81658 14.5976 9.20711 14.2071L13.5 9.91421L20.5858 17H17C16.4477 17 16 17.4477 16 18C16 18.5523 16.4477 19 17 19H22.9993L23.003 19C23.1375 18.9996 23.2657 18.9727 23.3828 18.9241C23.5007 18.8753 23.6112 18.803 23.7071 18.7071C23.8902 18.524 23.9874 18.2877 23.9989 18.048C23.9996 18.032 24 18.016 24 18V12C24 11.4477 23.5523 11 23 11C22.4477 11 22 11.4477 22 12V15.5858L14.2071 7.79289C13.8166 7.40237 13.1834 7.40237 12.7929 7.79289L8.5 12.0858L1.70711 5.29289Z"
|
||||
></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</g></svg
|
||||
>
|
||||
{:else if item?.changesPercentage < 0}
|
||||
<span class="text-[#FF2F1F] inline-block"
|
||||
>{item?.changesPercentage}%
|
||||
</span>
|
||||
<svg
|
||||
class="w-5 h-5 hidden sm:inline-block"
|
||||
viewBox="0 0 24 24"
|
||||
fill="#FF2F1F"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><g id="SVGRepo_bgCarrier" stroke-width="0"
|
||||
></g><g
|
||||
id="SVGRepo_tracerCarrier"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></g><g id="SVGRepo_iconCarrier">
|
||||
<g clip-path="url(#clip0_1076_36065)">
|
||||
<path
|
||||
d="M1.70711 5.29289C1.31658 4.90237 0.683417 4.90237 0.292893 5.29289C-0.0976311 5.68342 -0.0976311 6.31658 0.292893 6.70711L7.79289 14.2071C8.18342 14.5976 8.81658 14.5976 9.20711 14.2071L13.5 9.91421L20.5858 17H17C16.4477 17 16 17.4477 16 18C16 18.5523 16.4477 19 17 19H22.9993L23.003 19C23.1375 18.9996 23.2657 18.9727 23.3828 18.9241C23.5007 18.8753 23.6112 18.803 23.7071 18.7071C23.8902 18.524 23.9874 18.2877 23.9989 18.048C23.9996 18.032 24 18.016 24 18V12C24 11.4477 23.5523 11 23 11C22.4477 11 22 11.4477 22 12V15.5858L14.2071 7.79289C13.8166 7.40237 13.1834 7.40237 12.7929 7.79289L8.5 12.0858L1.70711 5.29289Z"
|
||||
fill="#FF2F1F"
|
||||
></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1076_36065">
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#FF2F1F"
|
||||
></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1076_36065">
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#FF2F1F"
|
||||
></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</g></svg
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col w-full pt-2">
|
||||
{#if index === 0 && data?.user?.tier !== "Pro"}
|
||||
<span class="mt-3">
|
||||
{item?.text?.slice(0, 50) + "..."}
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-white text-[1rem]">
|
||||
{item?.text}
|
||||
</span>
|
||||
></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</g></svg
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col w-full pt-2">
|
||||
{#if index === 0 && data?.user?.tier !== "Pro"}
|
||||
<span class="mt-3">
|
||||
{item?.text?.slice(0, 50) + "..."}
|
||||
Unlock content with
|
||||
<a
|
||||
class="inline-block ml-0.5 text-blue-400 sm:hover:text-white"
|
||||
href="/pricing"
|
||||
>Pro Subscription <svg
|
||||
class="w-4 h-4 mb-1 inline-block text[#A3A3A3] sm:hover:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
|
||||
/></svg
|
||||
></a
|
||||
>
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-white text-[1rem]">
|
||||
{item?.text}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--End Item-->
|
||||
</div>
|
||||
<!--End Item-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if wiim?.length > 2}
|
||||
<label
|
||||
on:click={() => (showFullHistory = !showFullHistory)}
|
||||
class="cursor-pointer flex justify-center items-center mt-5"
|
||||
>
|
||||
<svg
|
||||
class="w-10 h-10 transform {showFullHistory ? 'rotate-180' : ''} "
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#2A323C"
|
||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 13.5L7.5 11l1.42-1.41L12 12.67l3.08-3.08L16.5 11L12 15.5z"
|
||||
/></svg
|
||||
>
|
||||
</label>
|
||||
{/if}
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex justify-center items-center h-80">
|
||||
<div class="relative">
|
||||
<label
|
||||
class="bg-default h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
||||
>
|
||||
<span class="loading loading-spinner loading-md text-gray-400"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if wiim?.length > 2}
|
||||
<label
|
||||
on:click={() => (showFullHistory = !showFullHistory)}
|
||||
class="cursor-pointer flex justify-center items-center mt-5"
|
||||
>
|
||||
<svg
|
||||
class="w-10 h-10 transform {showFullHistory ? 'rotate-180' : ''} "
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="#2A323C"
|
||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 13.5L7.5 11l1.42-1.41L12 12.67l3.08-3.08L16.5 11L12 15.5z"
|
||||
/></svg
|
||||
>
|
||||
</label>
|
||||
{/if}
|
||||
{/if}
|
||||
</main>
|
||||
</section>
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -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 @@
|
||||
<svelte:window bind:scrollY={y} />
|
||||
|
||||
<body
|
||||
class="bg-default w-full max-w-screen sm:max-w-7xl min-h-screen sm:max-w-[1400px] overflow-hidden"
|
||||
class="bg-default w-full max-w-screen sm:max-w-[1400px] min-h-screen overflow-hidden"
|
||||
>
|
||||
<!-- Page wrapper -->
|
||||
<div class="flex flex-col w-full mt-5 relative w-full">
|
||||
<div class="mt-5 flex flex-col w-full relative w-full">
|
||||
<main class="grow w-full">
|
||||
<section class="w-full">
|
||||
<div class="w-full">
|
||||
@ -330,9 +398,7 @@
|
||||
? "hidden"
|
||||
: "flex flex-col items-center ml-6 transition-transform ease-in"}
|
||||
>
|
||||
<span
|
||||
class="text-white text-[0.70rem] font-medium text-opacity-[0.6]"
|
||||
>
|
||||
<span class="text-white text-xs font-semibold">
|
||||
{$etfTicker}
|
||||
</span>
|
||||
<span class="text-white font-medium text-sm">
|
||||
@ -497,23 +563,19 @@
|
||||
</div>
|
||||
<!--End Mobile Navbar-->
|
||||
|
||||
<div class="pt-14 sm:pt-0 w-full px-3 sm:px-0">
|
||||
<div class="pt-14 sm:pt-0 w-full px-3 sm:px-0 lg:pr-3">
|
||||
<div
|
||||
class="md:flex md:justify-between md:divide-x md:divide-slate-800"
|
||||
>
|
||||
<!-- Main content -->
|
||||
<div class="pb-12 md:pb-20 w-full">
|
||||
<div class="md:pr-6 lg:pr-10">
|
||||
<div class="">
|
||||
<!-----Start-Header-CandleChart-Indicators------>
|
||||
|
||||
<div
|
||||
class="m-auto pl-0 sm:pl-4 overflow-hidden mb-3 md:mt-10 xl:pr-7"
|
||||
>
|
||||
<div class="m-auto pl-0 sm:pl-4 overflow-hidden mb-3">
|
||||
<div
|
||||
class="hidden sm:flex flex-row w-full justify-between items-center"
|
||||
>
|
||||
<Markethour />
|
||||
|
||||
<!--Start Watchlist-->
|
||||
|
||||
{#if data?.user}
|
||||
@ -640,22 +702,135 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||
|
||||
<div class="flex items-center w-full mt-3">
|
||||
<div class="flex items-center w-full mt-5">
|
||||
<div
|
||||
class="flex flex-row justify-start w-full items-center"
|
||||
>
|
||||
<div class="flex flex-col items-start ml-2 sm:ml-3">
|
||||
<span class="text-md sm:text-lg text-blue-400">
|
||||
{$etfTicker?.toUpperCase()}
|
||||
</span>
|
||||
<span
|
||||
class="text-xl sm:text-2xl font-semibold sm:font-bold text-white"
|
||||
<div class="flex flex-col items-start w-full">
|
||||
<div
|
||||
class="flex flex-row justify-between items-center w-full sm:-mt-[50px] mb-5 sm:mb-10"
|
||||
>
|
||||
{$displayCompanyName?.length > charNumber
|
||||
? $displayCompanyName?.slice(0, charNumber) +
|
||||
"..."
|
||||
: $displayCompanyName}
|
||||
</span>
|
||||
<div
|
||||
class="text-2xl lg:text-3xl font-bold text-white"
|
||||
>
|
||||
{$displayCompanyName?.length > charNumber
|
||||
? $displayCompanyName?.slice(0, charNumber) +
|
||||
"..."
|
||||
: $displayCompanyName}
|
||||
<span class="hidden sm:inline-block"
|
||||
>({$etfTicker?.toUpperCase()})</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="-mt-5 sm:-mt-8 mb-5 flex flex-row items-end space-x-2 xs:space-x-3 sm:space-x-5 text-white"
|
||||
>
|
||||
<div class="w-full max-w-[50%] whitespace-nowrap">
|
||||
<div
|
||||
class="text-3xl sm:text-4xl font-bold {Object?.keys(
|
||||
prePostData,
|
||||
)?.length === 0
|
||||
? 'inline'
|
||||
: 'block sm:inline'}"
|
||||
>
|
||||
{displayLegend?.close}
|
||||
</div>
|
||||
<div
|
||||
class="font-semibold {Object?.keys(
|
||||
prePostData,
|
||||
)?.length === 0
|
||||
? 'inline'
|
||||
: 'block sm:inline'} text-lg xs:text-xl sm:text-2xl {displayLegend?.change >=
|
||||
0
|
||||
? "before:content-['+'] text-[#00FC50]"
|
||||
: 'text-[#FF2F1F]'}"
|
||||
>
|
||||
{displayLegend?.change}%
|
||||
</div>
|
||||
<div class="mt-0.5 text-xs sm:text-sm">
|
||||
{#if !$isOpen}
|
||||
<span
|
||||
class="block font-semibold sm:inline mb-0.5 sm:mb-0"
|
||||
>At close:</span
|
||||
>
|
||||
{/if}
|
||||
{displayLegend?.date}
|
||||
{#if $isOpen}
|
||||
<span
|
||||
class="{Object?.keys(prePostData)
|
||||
?.length !== 0
|
||||
? 'block sm:inline'
|
||||
: 'inline'} mb-0.5 sm:mb-0"
|
||||
>- Market open</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if Object?.keys(prePostData)?.length !== 0 && !$isOpen}
|
||||
<div
|
||||
class="border-l border-default pl-3 bp:pl-5"
|
||||
>
|
||||
<div
|
||||
class="block text-2xl sm:text-[1.7rem] font-semibold leading-5 text-faded sm:inline"
|
||||
>
|
||||
{prePostData?.price?.toFixed(2)}
|
||||
</div>
|
||||
<div
|
||||
class="mt-1.5 block text-sm xs:text-base sm:mt-0 sm:inline sm:text-lg {prePostData?.changesPercentage >=
|
||||
0
|
||||
? "before:content-['+'] text-[#00FC50]"
|
||||
: 'text-[#FF2F1F]'}"
|
||||
>
|
||||
{prePostData?.changesPercentage?.toFixed(
|
||||
2,
|
||||
)}%
|
||||
</div>
|
||||
<div class="mt-1 text-xs sm:text-sm sm:flex">
|
||||
<span class="flex items-center">
|
||||
{#if prePostData?.time?.includes("AM")}
|
||||
<svg
|
||||
class="h-4 w-4 inline text-yellow-500"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
style="max-width:40px"
|
||||
><path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
||||
></path></svg
|
||||
>
|
||||
{:else}
|
||||
<svg
|
||||
class="h-4 w-4 inline text-blue-400"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
style="max-width:40px"
|
||||
><path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
||||
></path></svg
|
||||
>
|
||||
{/if}
|
||||
<span
|
||||
class="ml-0.5 whitespace-nowrap font-semibold md:ml-1 mb-0.5 sm:mb-0"
|
||||
>{prePostData?.time?.includes("AM")
|
||||
? "Pre-market"
|
||||
: "After-hours"}</span
|
||||
></span
|
||||
>
|
||||
<span class="sm:ml-1 whitespace-nowrap"
|
||||
>{prePostData?.time}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -664,7 +839,6 @@
|
||||
|
||||
<!--Start Ticker Section-->
|
||||
|
||||
<!--<div class="w-full max-w-3xl sm:max-w-2xl m-auto pt-2 pb-5 sm:pl-3 sticky z-20 bg-default" style="top: {$screenWidth < 520 && $isScrollingUp ? '4rem' : '0rem'};">-->
|
||||
<nav
|
||||
class="sm:ml-4 border-b-[2px] overflow-x-scroll md:overflow-hidden whitespace-nowrap"
|
||||
>
|
||||
@ -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
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`/etf/${$etfTicker}/holdings`}
|
||||
on:click={() => 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
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`/etf/${$etfTicker}/options`}
|
||||
on:click={() => 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 @@
|
||||
</nav>
|
||||
|
||||
<!--Start-Main Content-->
|
||||
|
||||
<slot />
|
||||
<!--End Main Content-->
|
||||
</div>
|
||||
@ -767,6 +942,7 @@
|
||||
|
||||
<!--Start SellTrade Modal-->
|
||||
<PriceAlert {data} ticker={$etfTicker} assetType={$assetType} />
|
||||
|
||||
<!--Start Add Watchlist Modal-->
|
||||
<input type="checkbox" id="addWatchListModal" class="modal-toggle" />
|
||||
|
||||
@ -798,7 +974,7 @@
|
||||
class="cursor-pointer w-full flex flex-row justify-start items-center mb-5"
|
||||
>
|
||||
<div
|
||||
class="flex flex-row items-center w-full p-3 border rounded-md {item?.ticker?.includes(
|
||||
class="flex flex-row items-center w-full border p-3 rounded-md {item?.ticker?.includes(
|
||||
$etfTicker,
|
||||
)
|
||||
? 'border border-gray-400'
|
||||
@ -814,7 +990,9 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="rounded-full w-8 h-8 relative border border-gray-600">
|
||||
<div
|
||||
class="rounded-full w-8 h-8 relative border border-[#737373]"
|
||||
>
|
||||
{#if item?.ticker?.includes($etfTicker)}
|
||||
<svg
|
||||
class="w-full h-full rounded-full"
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
import {
|
||||
etfTicker,
|
||||
displayCompanyName,
|
||||
assetType,
|
||||
} from "$lib/store";
|
||||
|
||||
|
||||
export const load = async ({ data }) => {
|
||||
etfTicker.set(data?.getParams?.toUpperCase());
|
||||
assetType.set("etf");
|
||||
displayCompanyName.set(data?.companyName);
|
||||
};
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -708,21 +671,21 @@
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>
|
||||
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""}
|
||||
{$displayCompanyName} ({$etfTicker}) Stock Price, Quote & News · Stocknear
|
||||
{data?.companyName} ({$etfTicker}) Stock Price, Quote & News · Stocknear
|
||||
</title>
|
||||
|
||||
<meta
|
||||
name="description"
|
||||
content={`Get a real-time ${$displayCompanyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
content={`Get a real-time ${data?.companyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
/>
|
||||
<!-- Other meta tags -->
|
||||
<meta
|
||||
property="og:title"
|
||||
content={`${$displayCompanyName} (${$etfTicker}) Stock Price, Quote & News · Stocknear`}
|
||||
content={`${data?.companyName} (${$etfTicker}) Stock Price, Quote & News · Stocknear`}
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content={`Get a real-time ${$displayCompanyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
content={`Get a real-time ${data?.companyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
/>
|
||||
<!--<meta property="og:image" content="https://stocknear-pocketbase.s3.amazonaws.com/logo/meta_logo.jpg"/>-->
|
||||
<meta property="og:type" content="website" />
|
||||
@ -732,11 +695,11 @@
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content={`${$displayCompanyName} (${$etfTicker}) Stock Price, Quote & News · Stocknear`}
|
||||
content={`${data?.companyName} (${$etfTicker}) Stock Price, Quote & News · Stocknear`}
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content={`Get a real-time ${$displayCompanyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
content={`Get a real-time ${data?.companyName} (${$etfTicker}) stock chart, price quote with breaking news, financials, statistics, charts and more.`}
|
||||
/>
|
||||
<!--<meta name="twitter:image" content="https://stocknear-pocketbase.s3.amazonaws.com/logo/meta_logo.jpg"/>-->
|
||||
<!-- Add more Twitter meta tags as needed -->
|
||||
@ -749,100 +712,7 @@
|
||||
>
|
||||
<!-- Main content -->
|
||||
<div class="pb-12 md:pb-20 w-full sm:pr-6 xl:pr-0">
|
||||
<div class="xl:pr-10">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||
|
||||
<div class="flex flex-row items-start w-full sm:pl-6 mt-4">
|
||||
<div class="flex flex-col items-start justify-start w-full">
|
||||
<div
|
||||
class="text-2xl md:text-3xl font-bold text-white flex flex-row items-center w-full"
|
||||
>
|
||||
{$realtimePrice ?? displayLegend?.close}
|
||||
|
||||
{#if $priceIncrease === true}
|
||||
<div
|
||||
style="background-color: green;"
|
||||
class="inline-block pulse rounded-full w-3 h-3 ml-2"
|
||||
></div>
|
||||
{:else if $priceIncrease === false}
|
||||
<div
|
||||
style="background-color: red;"
|
||||
class="inline-block pulse rounded-full w-3 h-3 ml-2"
|
||||
></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row items-center w-full">
|
||||
<span
|
||||
class="items-center justify-start {displayLegend?.change > 0
|
||||
? "before:content-['+'] text-[#00FC50]"
|
||||
: 'text-[#FF2F1F]'} font-medium text-xs sm:text-sm"
|
||||
>{displayLegend?.change ?? "-"}%</span
|
||||
>
|
||||
|
||||
<span class="ml-3 text-white text-xs sm:text-sm"
|
||||
>{displayLegend?.date}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto">
|
||||
{#if Object?.keys(prePostData)?.length !== 0 && prePostData?.price !== 0}
|
||||
<div class="flex flex-col justify-end items-end">
|
||||
<div class="flex flex-row items-center justify-end">
|
||||
<span class="text-white text-lg sm:text-2xl font-bold">
|
||||
{prePostData?.price}
|
||||
</span>
|
||||
{#if prePostData?.changesPercentage >= 0}
|
||||
<span
|
||||
class="ml-1 items-center justify-start text-[#00FC50] font-medium text-xs sm:text-sm"
|
||||
>({prePostData?.changesPercentage}%)</span
|
||||
>
|
||||
{:else if prePostData?.changesPercentage < 0}
|
||||
<span
|
||||
class="ml-1 items-center justify-start text-[#FF2F1F] font-medium text-xs sm:text-sm"
|
||||
>({prePostData?.changesPercentage}%)</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{#if $isBeforeMarketOpen && !$isOpen && !$isWeekend}
|
||||
<div
|
||||
class="flex flex-row items-center justify-end text-white text-xs sm:text-sm font-normal text-end w-24"
|
||||
>
|
||||
<span>Pre-market:</span>
|
||||
<svg
|
||||
class="ml-1 w-4 h-4 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#EA9703"
|
||||
d="M120 40V16a8 8 0 0 1 16 0v24a8 8 0 0 1-16 0m72 88a64 64 0 1 1-64-64a64.07 64.07 0 0 1 64 64m-16 0a48 48 0 1 0-48 48a48.05 48.05 0 0 0 48-48M58.34 69.66a8 8 0 0 0 11.32-11.32l-16-16a8 8 0 0 0-11.32 11.32Zm0 116.68l-16 16a8 8 0 0 0 11.32 11.32l16-16a8 8 0 0 0-11.32-11.32M192 72a8 8 0 0 0 5.66-2.34l16-16a8 8 0 0 0-11.32-11.32l-16 16A8 8 0 0 0 192 72m5.66 114.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32-11.32ZM48 128a8 8 0 0 0-8-8H16a8 8 0 0 0 0 16h24a8 8 0 0 0 8-8m80 80a8 8 0 0 0-8 8v24a8 8 0 0 0 16 0v-24a8 8 0 0 0-8-8m112-88h-24a8 8 0 0 0 0 16h24a8 8 0 0 0 0-16"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="flex flex-row items-center justify-end text-white text-xs sm:text-sm font-normal text-end w-28"
|
||||
>
|
||||
<span>After-hours:</span>
|
||||
<svg
|
||||
class="ml-1 w-4 h-4 inline-block"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#70A1EF"
|
||||
d="M232.13 143.64a6 6 0 0 0-6-1.49a90.07 90.07 0 0 1-112.27-112.3a6 6 0 0 0-7.49-7.48a102.88 102.88 0 0 0-51.89 36.31a102 102 0 0 0 142.84 142.84a102.88 102.88 0 0 0 36.31-51.89a6 6 0 0 0-1.5-5.99m-42 48.29a90 90 0 0 1-126-126a90.9 90.9 0 0 1 35.52-28.27a102.06 102.06 0 0 0 118.69 118.69a90.9 90.9 0 0 1-28.24 35.58Z"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<!-----End-Header-CandleChart-Indicators------>
|
||||
|
||||
<div class="mt-2">
|
||||
<!--End Ticker Section-->
|
||||
<!-- Start Graph -->
|
||||
|
||||
@ -877,20 +747,6 @@
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="flex shrink flex-row space-x-1 pr-1 text-sm sm:text-[1rem]"
|
||||
>
|
||||
<span
|
||||
class={displayLegend?.change >= 0
|
||||
? "before:content-['+'] text-[#00FC50]"
|
||||
: "text-[#FF2F1F]"}
|
||||
>
|
||||
{displayLegend?.change ?? "-"}%
|
||||
</span>
|
||||
<span class="hidden text-gray-200 sm:block"
|
||||
>({displayData})</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[250px] sm:h-[350px]">
|
||||
<div
|
||||
@ -938,11 +794,11 @@
|
||||
class="flex shrink flex-row space-x-1 pr-1 text-sm sm:text-[1rem]"
|
||||
>
|
||||
<span
|
||||
class={displayLegend?.change >= 0
|
||||
class={displayLegend?.graphChange >= 0
|
||||
? "before:content-['+'] text-[#00FC50]"
|
||||
: "text-[#FF2F1F]"}
|
||||
>
|
||||
{displayLegend?.change}%
|
||||
{displayLegend?.graphChange}%
|
||||
</span>
|
||||
<span class="hidden text-gray-200 sm:block"
|
||||
>({displayData})</span
|
||||
@ -968,7 +824,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -988,7 +843,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -1008,7 +862,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -1028,7 +881,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -1048,7 +900,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -1068,7 +919,6 @@
|
||||
lineColor={colorChange}
|
||||
topColor={topColorChange}
|
||||
bottomColor={bottomColorChange}
|
||||
ref={handleSeriesReference}
|
||||
priceLineVisible={false}
|
||||
>
|
||||
<PriceLine
|
||||
@ -1101,7 +951,7 @@
|
||||
class="mt-10 lg:mt-0 order-5 lg:order-1 flex flex-row space-x-2 sm:space-x-3 xs:space-x-4"
|
||||
>
|
||||
<table
|
||||
class="w-[50%] text-sm text-white tiny:text-small lg:w-full lg:min-w-[210px]"
|
||||
class="w-[50%] text-sm text-white sm:text-[1rem] lg:min-w-[250px] 2xl:min-w-[300px]"
|
||||
>
|
||||
<tbody
|
||||
><tr
|
||||
@ -1221,8 +1071,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<table
|
||||
class="w-[48%] text-sm text-white tiny:text-small lg:w-auto lg:min-w-[210px]"
|
||||
data-test="overview-quote"
|
||||
class="w-[50%] text-sm text-white lg:min-w-[250px] 2xl:min-w-[300px]"
|
||||
>
|
||||
<tbody
|
||||
><tr
|
||||
@ -1332,16 +1181,15 @@
|
||||
<!--End Graph-->
|
||||
|
||||
<div
|
||||
class="mt-6 flex flex-col lg:flex-row gap-x-14 items-start w-full"
|
||||
class="mt-6 flex flex-col lg:flex-row gap-x-14 items-start w-full justify-between"
|
||||
>
|
||||
<div
|
||||
class="lg:space-y-6 lg:order-2 lg:pt-1 sm:pl-7 lg:pl-0 w-full lg:w-[45%] sm:ml-auto"
|
||||
class="lg:space-y-6 lg:order-2 lg:pt-1 sm:pl-7 lg:pl-0 w-full lg:w-[45%] sm:ml-auto lg:max-w-[400px]"
|
||||
>
|
||||
<ETFSidecard {data} />
|
||||
<div class="lg:sticky lg:top-20"></div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="w-full lg:w-[65%] 2xl:w-[70%]">
|
||||
<div
|
||||
class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 {data
|
||||
?.getWhyPriceMoved?.length !== 0
|
||||
@ -1351,7 +1199,7 @@
|
||||
<WIIM {data} />
|
||||
</div>
|
||||
|
||||
<div class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 sm:pt-6">
|
||||
<div class="w-full mt-5 sm:mt-0 m-auto sm:pl-6 sm:pb-6">
|
||||
<News {data} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -1230,7 +1230,7 @@
|
||||
<WIIM {data} />
|
||||
</div>
|
||||
|
||||
<div class="w-full mt-5 sm:mt-0 m-auto sm:pl-6 sm:pb-6 sm:pt-6">
|
||||
<div class="w-full mt-5 sm:mt-0 m-auto sm:pl-6 sm:pb-6">
|
||||
<News {data} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user