update etf page
This commit is contained in:
parent
6eb6b661ce
commit
89ae8e8e62
@ -201,17 +201,11 @@
|
||||
if (event.ctrlKey && event.key === "k") {
|
||||
const keyboardSearch = document.getElementById("combobox-input");
|
||||
keyboardSearch?.dispatchEvent(new MouseEvent("click"));
|
||||
inputValue = "";
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const handleEscape = (event) => {
|
||||
if (event.key === "Escape") {
|
||||
// Escape key is pressed, close the modal
|
||||
searchBarModalChecked = false;
|
||||
}
|
||||
};
|
||||
|
||||
function saveRecentTicker() {
|
||||
try {
|
||||
// Save the version along with the rules
|
||||
@ -233,10 +227,8 @@
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handleControlK);
|
||||
window.addEventListener("keydown", handleEscape);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleControlK);
|
||||
window.removeEventListener("keydown", handleEscape);
|
||||
};
|
||||
});
|
||||
|
||||
@ -319,6 +311,7 @@
|
||||
<Combobox.Input
|
||||
id="combobox-input"
|
||||
on:input={search}
|
||||
on:click={() => (inputValue = "")}
|
||||
class="grow rounded-sm border border-gray-600 py-2 pl-9 text-[1rem] placeholder-gray-400 focus:border-default focus:shadow-lg focus:outline-none focus:ring-0 tiny:pl-8 xs:pl-10 text-white md:py-2 w-full bg-secondary focus:bg-secondary"
|
||||
placeholder="Company or stock symbol..."
|
||||
aria-label="Company or stock symbol..."
|
||||
|
||||
@ -676,8 +676,8 @@
|
||||
on:click={() => changeSection("overview")}
|
||||
class="p-2 px-5 cursor-pointer {displaySection ===
|
||||
'overview'
|
||||
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
|
||||
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
|
||||
>
|
||||
Overview
|
||||
</a>
|
||||
@ -686,8 +686,8 @@
|
||||
on:click={() => changeSection("holdings")}
|
||||
class="p-2 px-5 cursor-pointer {displaySection ===
|
||||
'holdings'
|
||||
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
|
||||
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
|
||||
>
|
||||
Holdings
|
||||
</a>
|
||||
@ -697,8 +697,8 @@
|
||||
on:click={() => changeSection("options")}
|
||||
class="p-2 px-5 cursor-pointer {displaySection ===
|
||||
'options'
|
||||
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
|
||||
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
|
||||
>
|
||||
Options
|
||||
</a>
|
||||
@ -707,8 +707,8 @@
|
||||
on:click={() => changeSection("insider")}
|
||||
class="p-2 px-5 cursor-pointer {displaySection ===
|
||||
'insider'
|
||||
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
|
||||
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
|
||||
>
|
||||
Insider
|
||||
</a>
|
||||
@ -717,8 +717,8 @@
|
||||
on:click={() => changeSection("dividends")}
|
||||
class="p-2 px-5 cursor-pointer {displaySection ===
|
||||
'dividends'
|
||||
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
|
||||
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95]'
|
||||
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
|
||||
>
|
||||
Dividends
|
||||
</a>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { etfTicker } from "$lib/store";
|
||||
import ArrowLogo from "lucide-svelte/icons/move-up-right";
|
||||
import { formatDate } from "$lib/utils";
|
||||
|
||||
export let data;
|
||||
|
||||
const similarStocks = data?.getSimilarStocks?.sort(
|
||||
(a, b) => b?.dividendYield - a?.dividendYield,
|
||||
);
|
||||
let newsList = data?.getNews ?? [];
|
||||
</script>
|
||||
|
||||
<section class="w-auto overflow-hidden min-h-screen">
|
||||
@ -40,44 +40,29 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if similarStocks?.length > 0}
|
||||
{#if newsList?.length !== 0}
|
||||
<div
|
||||
class="w-full p-2 text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
class="w-full sm:hover:text-white text-white border border-gray-600 bg-primary rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
>
|
||||
<h3 class="p-2 pt-4 text-xl font-semibold">Related Stocks</h3>
|
||||
<table class="table table-sm table-compact w-full text-white">
|
||||
<thead class="text-white"
|
||||
><tr
|
||||
><th
|
||||
class="whitespace-nowrap border-b font-semibold text-sm text-left"
|
||||
>Company</th
|
||||
>
|
||||
<th
|
||||
class="whitespace-nowrap border-b font-semibold text-sm text-right"
|
||||
>Dividend Yield</th
|
||||
></tr
|
||||
></thead
|
||||
>
|
||||
<tbody>
|
||||
{#each similarStocks?.slice(0, 8) as item}
|
||||
<tr class="border-gray-600 border-b"
|
||||
><td class="text-left"
|
||||
><a
|
||||
href={`/stocks/${item?.symbol}`}
|
||||
class="sm:hover:text-white text-blue-400"
|
||||
>{item?.symbol}</a
|
||||
></td
|
||||
<div class="p-4 text-sm">
|
||||
<h3 class="text-lg text-white font-semibold mb-3">
|
||||
{$etfTicker} News
|
||||
</h3>
|
||||
<ul class="text-white">
|
||||
{#each newsList?.slice(0, 10) as item}
|
||||
<li class="mb-3 last:mb-1">
|
||||
{formatDate(item?.publishedDate)} ·
|
||||
<a
|
||||
class="sm:hover:text-white text-blue-400"
|
||||
href={item?.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow">{item?.title}</a
|
||||
>
|
||||
<td class="text-right cursor-normal"
|
||||
>{item?.dividendYield !== null &&
|
||||
item?.dividendYield !== undefined
|
||||
? item?.dividendYield + "%"
|
||||
: "n/a"}</td
|
||||
>
|
||||
</tr>
|
||||
- {item?.site}
|
||||
</li>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</aside>
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
import { LineChart, BarChart } from "echarts/charts";
|
||||
import { GridComponent, TooltipComponent } from "echarts/components";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import Infobox from "$lib/components/Infobox.svelte";
|
||||
|
||||
use([LineChart, BarChart, TooltipComponent, GridComponent, CanvasRenderer]);
|
||||
|
||||
export let data;
|
||||
@ -112,6 +114,63 @@
|
||||
optionsDividend = await plotDividend();
|
||||
isLoaded = true;
|
||||
});
|
||||
|
||||
function generateDividendInfoHTML() {
|
||||
const history = rawData?.history || [];
|
||||
|
||||
if (history.length !== 0) {
|
||||
if (!dateDistance) {
|
||||
const formattedExDividendDate = new Date(exDividendDate).toLocaleString(
|
||||
"en-US",
|
||||
{
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
},
|
||||
);
|
||||
|
||||
const payoutFrequencyText =
|
||||
payoutFrequency === 4
|
||||
? "3 months"
|
||||
: payoutFrequency === 2
|
||||
? "6 months"
|
||||
: payoutFrequency === 1
|
||||
? "12 months"
|
||||
: "n/a";
|
||||
|
||||
return `
|
||||
<span>
|
||||
${$displayCompanyName} has an annual dividend of $${annualDividend} per share, with a forward yield of ${dividendYield}%.
|
||||
The dividend is paid every ${payoutFrequencyText} and the last ex-dividend date was ${formattedExDividendDate}.
|
||||
</span>
|
||||
`;
|
||||
} else {
|
||||
const latestDividendDate = new Date(history.at(0)?.date).toLocaleString(
|
||||
"en-US",
|
||||
{
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
},
|
||||
);
|
||||
|
||||
return `
|
||||
<span>
|
||||
${$displayCompanyName} issued its most recent dividend on ${latestDividendDate}.
|
||||
Since then, the company has not distributed any further dividends for over 12 months.
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
} else {
|
||||
return `
|
||||
<span>
|
||||
No dividend history available for ${$displayCompanyName}.
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
const htmlOutput = generateDividendInfoHTML();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -163,55 +222,7 @@
|
||||
Dividends
|
||||
</h1>
|
||||
|
||||
<div
|
||||
class="w-full text-white text-start p-3 sm:p-5 mb-10 rounded-md sm:flex sm:flex-row sm:items-center border border-gray-600 text-sm sm:text-[1rem]"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 flex-shrink-0 inline-block sm:mr-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#fff"
|
||||
d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"
|
||||
/></svg
|
||||
>
|
||||
|
||||
{#if rawData?.history?.length !== 0}
|
||||
{#if !dateDistance}
|
||||
{$displayCompanyName} has an annual dividend of ${annualDividend}
|
||||
per share, with a forward yield of
|
||||
{dividendYield}%. The dividend is paid every
|
||||
{payoutFrequency === 4
|
||||
? "3 months"
|
||||
: payoutFrequency === 2
|
||||
? "6 months"
|
||||
: payoutFrequency === 1
|
||||
? "12 months"
|
||||
: "n/a"}
|
||||
and the last ex-dividend date was
|
||||
{new Date(exDividendDate)?.toLocaleString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
daySuffix: "2-digit",
|
||||
})}
|
||||
{:else}
|
||||
{$displayCompanyName} issued its most recent dividend on
|
||||
{new Date(rawData?.history?.at(0)?.date)?.toLocaleString(
|
||||
"en-US",
|
||||
{
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
daySuffix: "2-digit",
|
||||
},
|
||||
)}. Since then, the company has not distributed any further
|
||||
dividends for over 12 months.
|
||||
{/if}
|
||||
{:else}
|
||||
No dividend history available for {$displayCompanyName}.
|
||||
{/if}
|
||||
</div>
|
||||
<Infobox text={htmlOutput} />
|
||||
</div>
|
||||
|
||||
{#if rawData?.history?.length !== 0}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
} from "$lib/store";
|
||||
import { formatString } from "$lib/utils";
|
||||
import Table from "$lib/components/Table/Table.svelte";
|
||||
import Infobox from "$lib/components/Infobox.svelte";
|
||||
|
||||
export let data;
|
||||
let rawData = data?.getETFHoldings?.holdings;
|
||||
@ -32,6 +33,28 @@
|
||||
{ name: "% Weight", rule: "weightPercentage", type: "percent" },
|
||||
{ name: "Shares", rule: "sharesNumber", type: "int" },
|
||||
];
|
||||
|
||||
function generateStatementInfoHTML() {
|
||||
if (rawData?.length > 0) {
|
||||
return `
|
||||
<span>
|
||||
The ${$displayCompanyName} holds ${rawData?.length} different assets
|
||||
and the largest one in the portfolio is ${formatString(
|
||||
rawData?.at(0)?.name,
|
||||
)}, making up ${rawData?.at(0)?.weightPercentage?.toFixed(2)}% of
|
||||
the total.
|
||||
</span>
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
<span>
|
||||
No financial data available for ${$displayCompanyName}.
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
let htmlOutput = generateStatementInfoHTML();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -72,37 +95,15 @@
|
||||
</svelte:head>
|
||||
|
||||
<section
|
||||
class="bg-[#09090B] overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-5 sm:mt-0"
|
||||
class="bg-[#09090B] overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-2 sm:mt-0"
|
||||
>
|
||||
<div class="flex justify-center m-auto h-full overflow-hidden w-full">
|
||||
<div
|
||||
class="relative flex justify-center items-center overflow-hidden w-full"
|
||||
>
|
||||
<div class="sm:p-7 w-full m-auto mt-2 sm:mt-0">
|
||||
<div class="mb-6">
|
||||
<div
|
||||
class="text-white p-3 sm:p-5 mb-10 rounded-md sm:flex sm:flex-row sm:items-center border border-gray-600 text-sm sm:text-[1rem]"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6 flex-shrink-0 inline-block sm:mr-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
fill="#fff"
|
||||
d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"
|
||||
/></svg
|
||||
>
|
||||
|
||||
{#if rawData?.length !== 0}
|
||||
The {$displayCompanyName} holds {rawData?.length} different assets
|
||||
and the largest one in the portfolio is {formatString(
|
||||
rawData?.at(0)?.name,
|
||||
)}, making up {rawData?.at(0)?.weightPercentage?.toFixed(2)}% of
|
||||
the total.
|
||||
{:else}
|
||||
No information available for {$displayCompanyName}.
|
||||
{/if}
|
||||
</div>
|
||||
<div class="sm:p-7 w-full m-auto">
|
||||
<div class="mb-10">
|
||||
<Infobox text={htmlOutput} />
|
||||
</div>
|
||||
|
||||
{#if rawData?.length !== 0}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
{#if newsList?.length !== 0}
|
||||
<div
|
||||
class="w-full sm:hover:text-white text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
class="w-full sm:hover:text-white text-white border border-gray-600 bg-primary rounded-md h-fit pb-4 mt-4 cursor-pointer"
|
||||
>
|
||||
<div class="p-4 text-sm">
|
||||
<h3 class="text-lg text-white font-semibold mb-3">
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
>
|
||||
<!--Start Buy/Sell-->
|
||||
<div
|
||||
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-4 border border-gray-600 rounded-md h-20"
|
||||
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-4 border border-gray-600 bg-primary rounded-md h-20"
|
||||
>
|
||||
<div class="flex flex-col items-start">
|
||||
<span
|
||||
@ -227,7 +227,7 @@
|
||||
<!--End Buy/Sell-->
|
||||
<!--Start Dem/Rep-->
|
||||
<div
|
||||
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-4 border border-gray-600 rounded-md h-20"
|
||||
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-4 border border-gray-600 bg-primary rounded-md h-20"
|
||||
>
|
||||
<div class="flex flex-col items-start">
|
||||
<span
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user