bugfixing websocket

This commit is contained in:
MuslemRahimi 2024-12-03 17:20:01 +01:00
parent 36b7a25e90
commit 681d9cc423
5 changed files with 208 additions and 560 deletions

View File

@ -1,21 +1,10 @@
<script lang="ts">
import { analystEstimateComponent, stockTicker } from "$lib/store";
import { Chart } from "svelte-echarts";
import { init, use } from "echarts/core";
import { LineChart, CustomChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import { abbreviateNumber } from "$lib/utils";
import EstimationGraph from "$lib/components/EstimationGraph.svelte";
import Lazy from "svelte-lazy";
export let data;
use([
LineChart,
CustomChart,
GridComponent,
TooltipComponent,
CanvasRenderer,
]);
let analystEstimateList = [];
let isLoaded = false;
@ -829,530 +818,53 @@
{/if}
<div class="space-y-6 lg:grid lg:grid-cols-2 lg:gap-6 lg:space-y-0 mt-10">
<div>
<h2 class="mb-2 text-xl font-bold">Revenue Forecast</h2>
<div class="rounded-sm border p-2 border-gray-600">
<div class="app h-[275px] w-full">
{#if optionsRevenue !== null}
<Chart {init} options={optionsRevenue} class="chart" />
{/if}
</div>
<div
class="mt-3 overflow-x-auto p-0 text-center sm:p-0.5 lg:mt-3.5"
>
<table class="w-full text-right">
<thead
><tr
class="border-b border-gray-600 align-bottom text-white font-normal"
><th
class="p-1 text-left font-semibold text-sm sm:text-[1rem]"
>Revenue</th
>
{#each revenueDateList as date, index}
<th class="p-1 font-semibold text-sm sm:text-[1rem]">
{#if index !== 0}{date}{/if}</th
>
{/each}
</tr></thead
>
<tbody
><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>High</td
>
{#each highRevenueList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= highRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Avg</td
>
{#each avgRevenueList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= avgRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Low</td
>
{#each lowRevenueList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= lowRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr></tbody
>
</table>
</div>
</div>
</div>
<Lazy>
<EstimationGraph
userTier={data?.user?.tier}
title="Revenue"
options={optionsRevenue}
tableDataList={revenueDateList}
highDataList={highRevenueList}
avgDataList={avgRevenueList}
lowDataList={lowRevenueList}
/>
</Lazy>
<div>
<h2 class="mb-2 text-xl font-bold">Revenue Growth</h2>
<div class="rounded-sm border p-2 border-gray-600">
<div class="app h-[275px] w-full">
{#if optionsRevenueGrowth !== null}
<Chart {init} options={optionsRevenueGrowth} class="chart" />
{/if}
</div>
<div
class="mt-3 overflow-x-auto p-0 text-center sm:p-0.5 lg:mt-3.5"
>
<table class="w-full text-right">
<thead
><tr
class="border-b border-gray-600 align-bottom text-white font-normal whitespace-nowrap"
><th
class="p-1 text-left font-semibold text-sm sm:text-[1rem]"
>Revenue Growth</th
>
{#each revenueDateList as date, index}
<th class="p-1 font-semibold text-sm sm:text-[1rem]"
>{#if index !== 0}{date}{/if}</th
>
{/each}
</tr></thead
>
<tbody
><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>High</td
>
{#each computeGrowthSingleList(highRevenueList, avgRevenueList) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= highRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Avg</td
>
{#each revenueAvgGrowthList?.filter((item) => item.FY >= 24) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= avgRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Low</td
>
{#each computeGrowthSingleList(lowRevenueList, avgRevenueList) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= lowRevenueList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr></tbody
>
</table>
</div>
</div>
</div>
<Lazy>
<EstimationGraph
userTier={data?.user?.tier}
title="Revenue Growth"
options={optionsRevenueGrowth}
tableDataList={revenueDateList}
highDataList={highRevenueList}
avgDataList={avgRevenueList}
lowDataList={lowRevenueList}
/>
</Lazy>
<div>
<h2 class="mb-2 text-xl font-bold">EPS Forecast</h2>
<div class="rounded-sm border p-2 border-gray-600">
<div class="app h-[275px] w-full">
{#if optionsEPS !== null}
<Chart {init} options={optionsEPS} class="chart" />
{/if}
</div>
<div
class="mt-3 overflow-x-auto p-0 text-center sm:p-0.5 lg:mt-3.5"
data-test="forecast-estimate-table"
>
<table class="w-full text-right">
<thead
><tr class="border-b border-gray-600 align-bottom font-normal"
><th
class="p-1 text-left font-semibold text-sm sm:text-[1rem]"
>EPS</th
>
{#each epsDateList as date, index}
<th class="p-1 font-semibold text-sm sm:text-[1rem]">
{#if index !== 0}{date}{/if}</th
>
{/each}
</tr></thead
>
<tbody
><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>High</td
>
{#each highEPSList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= highEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Avg</td
>
{#each avgEPSList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= avgEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Low</td
>
{#each lowEPSList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= lowEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr></tbody
>
</table>
</div>
</div>
</div>
<div>
<h2 class="mb-2 text-xl font-bold">EPS Growth</h2>
<div class="rounded-sm border p-2 border-gray-600">
<div class="app h-[275px] w-full">
{#if optionsEPSGrowth !== null}
<Chart {init} options={optionsEPSGrowth} class="chart" />
{/if}
</div>
<div
class="mt-3 overflow-x-auto p-0 text-center sm:p-0.5 lg:mt-3.5"
>
<table class="w-full text-right">
<thead
><tr class="border-b border-gray-600 align-bottom font-normal"
><th
class="p-1 text-left font-semibold text-sm sm:text-[1rem]"
>EPS Growth</th
>
{#each epsDateList as date, index}
<th class="p-1 font-semibold text-sm sm:text-[1rem]"
>{#if index !== 0}{date}{/if}</th
>
{/each}
</tr></thead
>
<tbody
><tr
class="border-b border-gray-600 last:border-0 whitespace-nowrap"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>High</td
>
{#each computeGrowthSingleList(highEPSList, avgEPSList) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= highEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Avg</td
>
{#each epsAvgGrowthList?.filter((item) => item.FY >= 24) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= avgEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left"
>Low</td
>
{#each computeGrowthSingleList(lowEPSList, avgEPSList) as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if data?.user?.tier !== "Pro" && index >= lowEPSList?.length - 2}
<a
class="inline-block ml-0.5 text-white"
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}
<span
class={item?.growth !== null && item?.growth > 0
? "text-[#00FC50] before:content-['+']"
: item?.growth < 0
? "text-[#FF2F1F]"
: "text-white"}
>
{item?.growth !== null &&
Math.abs(item?.growth - 0) > 0
? abbreviateNumber(item?.growth) + "%"
: "-"}
</span>
{/if}
{/if}
</td>
{/each}
</tr></tbody
>
</table>
</div>
</div>
</div>
<Lazy>
<EstimationGraph
userTier={data?.user?.tier}
title="EPS"
options={optionsEPS}
tableDataList={epsDateList}
highDataList={highEPSList}
avgDataList={avgEPSList}
lowDataList={lowEPSList}
/>
</Lazy>
<Lazy>
<EstimationGraph
userTier={data?.user?.tier}
title="EPS Growth"
options={optionsEPSGrowth}
tableDataList={epsDateList}
highDataList={highEPSList}
avgDataList={avgEPSList}
lowDataList={lowEPSList}
/>
</Lazy>
</div>
</div>
</main>

View File

@ -0,0 +1,140 @@
<script lang="ts">
import { Chart } from "svelte-echarts";
import { init, use } from "echarts/core";
import { LineChart, CustomChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import { abbreviateNumber } from "$lib/utils";
use([
LineChart,
CustomChart,
GridComponent,
TooltipComponent,
CanvasRenderer,
]);
export let userTier;
export let title;
export let options;
export let tableDataList;
export let highDataList;
export let avgDataList;
export let lowDataList;
</script>
<div>
<h2 class="mb-2 text-xl font-bold">{title} Forecast</h2>
<div class="rounded-sm border p-2 border-gray-600">
<div class="app h-[275px] w-full">
{#if options !== null}
<Chart {init} {options} class="chart" />
{/if}
</div>
<div class="mt-3 overflow-x-auto p-0 text-center sm:p-0.5 lg:mt-3.5">
<table class="w-full text-right">
<thead
><tr
class="border-b border-gray-600 align-bottom text-white font-normal"
><th class="p-1 text-left font-semibold text-sm sm:text-[1rem]"
>{title}</th
>
{#each tableDataList as date, index}
<th class="p-1 font-semibold text-sm sm:text-[1rem]">
{#if index !== 0}{date}{/if}</th
>
{/each}
</tr></thead
>
<tbody
><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left">High</td>
{#each highDataList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if userTier !== "Pro" && index >= highDataList?.length - 2}
<a class="inline-block ml-0.5 text-white" 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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left">Avg</td>
{#each avgDataList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if userTier !== "Pro" && index >= avgDataList?.length - 2}
<a class="inline-block ml-0.5 text-white" 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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr><tr class="border-b border-gray-600 last:border-0"
><td class="whitespace-nowrap px-1 py-[3px] text-left">Low</td>
{#each lowDataList as item, index}
<td class="px-1 py-[3px] text-sm sm:text-[1rem]">
{#if index !== 0}
{#if userTier !== "Pro" && index >= lowDataList?.length - 2}
<a class="inline-block ml-0.5 text-white" 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}
{abbreviateNumber(item?.val)}
{/if}
{/if}
</td>
{/each}
</tr></tbody
>
</table>
</div>
</div>
</div>
<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>

View File

@ -135,30 +135,29 @@
function sendMessage(message) {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(message);
socket.send(JSON?.stringify(message));
} else {
console.error("WebSocket is not open. Unable to send message.");
}
}
async function websocketRealtimeData() {
previousTicker = $etfTicker;
try {
socket = new WebSocket(data?.wsURL + "/realtime-data");
socket = new WebSocket(data?.wsURL + "/price-data");
socket.addEventListener("open", () => {
//console.log('WebSocket connection opened');
// Send the initial value of etfTicker
sendMessage($etfTicker?.toLowerCase());
console.log("WebSocket connection opened");
// Send only current watchlist symbols
const tickerList = [$etfTicker] || [];
sendMessage(tickerList);
});
socket.addEventListener("message", (event) => {
const data = event.data;
//console.log('Received message:', data);
console.log("Received message:", data);
try {
const parsedData = JSON.parse(data);
const { type, lp, time, bp, ap } = parsedData || {};
const { type, lp, time, bp, ap, avgPrice } = parsedData?.at(0) || {};
if (type === "T") {
$realtimePrice = typeof lp !== "undefined" ? lp : null;
@ -170,7 +169,8 @@
} else if (type === "Q") {
$wsBidPrice = typeof bp !== "undefined" ? bp : null;
$wsAskPrice = typeof ap !== "undefined" ? ap : null;
$realtimePrice = $wsAskPrice;
$realtimePrice =
typeof avgPrice !== "undefined" ? avgPrice?.toFixed(2) : null;
}
// Update price increase state
@ -187,11 +187,9 @@
socket.addEventListener("close", (event) => {
console.log("WebSocket connection closed:", event.reason);
// Handle disconnection, you might want to attempt to reconnect here
});
} catch (error) {
console.error("WebSocket connection error:", error);
// Handle connection errors here
}
}

View File

@ -144,30 +144,29 @@
function sendMessage(message) {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(message);
socket.send(JSON?.stringify(message));
} else {
console.error("WebSocket is not open. Unable to send message.");
}
}
async function websocketRealtimeData() {
previousTicker = $stockTicker;
try {
socket = new WebSocket(data?.wsURL + "/realtime-data");
socket = new WebSocket(data?.wsURL + "/price-data");
socket.addEventListener("open", () => {
//console.log('WebSocket connection opened');
// Send the initial value of stockTicker
sendMessage($stockTicker?.toLowerCase());
console.log("WebSocket connection opened");
// Send only current watchlist symbols
const tickerList = [$stockTicker] || [];
sendMessage(tickerList);
});
socket.addEventListener("message", (event) => {
const data = event.data;
//console.log('Received message:', data);
console.log("Received message:", data);
try {
const parsedData = JSON.parse(data);
const { type, lp, time, bp, ap, avgPrice } = parsedData || {};
const { type, lp, time, bp, ap, avgPrice } = parsedData?.at(0) || {};
if (type === "T") {
$realtimePrice = typeof lp !== "undefined" ? lp : null;
@ -179,7 +178,8 @@
} else if (type === "Q") {
$wsBidPrice = typeof bp !== "undefined" ? bp : null;
$wsAskPrice = typeof ap !== "undefined" ? ap : null;
$realtimePrice = typeof avgPrice !== "undefined" ? avgPrice : null;
$realtimePrice =
typeof avgPrice !== "undefined" ? avgPrice?.toFixed(2) : null;
}
// Update price increase state
@ -196,11 +196,9 @@
socket.addEventListener("close", (event) => {
console.log("WebSocket connection closed:", event.reason);
// Handle disconnection, you might want to attempt to reconnect here
});
} catch (error) {
console.error("WebSocket connection error:", error);
// Handle connection errors here
}
}

View File

@ -183,7 +183,7 @@
async function websocketRealtimeData() {
try {
socket = new WebSocket(data?.wsURL + "/multiple-realtime-data");
socket = new WebSocket(data?.wsURL + "/price-data");
socket.addEventListener("open", () => {
console.log("WebSocket connection opened");