update etf page

This commit is contained in:
MuslemRahimi 2024-12-25 00:28:53 +01:00
parent 6eb6b661ce
commit 89ae8e8e62
7 changed files with 124 additions and 134 deletions

View File

@ -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..."

View File

@ -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>

View File

@ -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)} &#183;
<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>

View File

@ -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}

View File

@ -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}

View File

@ -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">

View File

@ -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