254 lines
8.7 KiB
Svelte
254 lines
8.7 KiB
Svelte
<script lang="ts">
|
|
import { secFilingsClicked, stockTicker, clientSideCache } from "$lib/store";
|
|
import * as Tabs from "$lib/components/shadcn/tabs/index.js";
|
|
|
|
import { fade } from "svelte/transition";
|
|
|
|
let secFilingsList;
|
|
|
|
let displayList = [];
|
|
let accordionOpen = {};
|
|
let newData;
|
|
let isLoaded = false;
|
|
|
|
function changeSECType(secType) {
|
|
switch (secType) {
|
|
case "8-K":
|
|
prepareData(secFilingsList?.eightK);
|
|
break;
|
|
case "10-K":
|
|
prepareData(secFilingsList?.tenK);
|
|
break;
|
|
case "10-Q":
|
|
prepareData(secFilingsList?.tenQ);
|
|
break;
|
|
// Default case in case changeType doesn't match any of the specified cases
|
|
default:
|
|
// Handle the default case or leave it empty if not needed
|
|
break;
|
|
}
|
|
}
|
|
|
|
function prepareData(dataset) {
|
|
if (dataset?.length !== 0) {
|
|
newData = {};
|
|
accordionOpen = {};
|
|
|
|
dataset?.forEach((item) => {
|
|
// Extract year from the date
|
|
const year = new Date(item?.date)?.getFullYear()?.toString();
|
|
|
|
// Check if the year already exists in newData
|
|
if (!newData[year]) {
|
|
// If not, initialize a new entry for the year
|
|
newData[year] = {
|
|
year: year,
|
|
totalReports: 0,
|
|
data: [],
|
|
};
|
|
}
|
|
// Increment the totalReports count
|
|
newData[year].totalReports++;
|
|
|
|
// Add the current item to the 'data' array
|
|
newData[year].data?.push(item);
|
|
});
|
|
|
|
// Convert newData object to an array of values
|
|
displayList = Object?.values(newData);
|
|
displayList = displayList?.sort((a, b) => b?.year - a?.year);
|
|
// Output the displayList
|
|
displayList = [...displayList];
|
|
//console.log(displayList)
|
|
} else {
|
|
displayList = [];
|
|
}
|
|
}
|
|
|
|
async function handleAccordion(year) {
|
|
accordionOpen[year] = !accordionOpen[year];
|
|
}
|
|
|
|
async function fetchData() {
|
|
if ($clientSideCache[$stockTicker]?.getSECFilings) {
|
|
secFilingsList = $clientSideCache[$stockTicker]?.getSECFilings;
|
|
} else {
|
|
const postData = { ticker: $stockTicker, path: "get-sec-filings" };
|
|
const response = await fetch("/api/ticker-data", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(postData),
|
|
});
|
|
|
|
secFilingsList = await response.json();
|
|
$clientSideCache[$stockTicker].getSECFilings = secFilingsList;
|
|
}
|
|
}
|
|
|
|
$: {
|
|
if (
|
|
$stockTicker &&
|
|
typeof window !== "undefined" &&
|
|
$secFilingsClicked === true
|
|
) {
|
|
isLoaded = false;
|
|
$secFilingsClicked = false;
|
|
accordionOpen = {};
|
|
|
|
const asyncFunctions = [fetchData()];
|
|
Promise.all(asyncFunctions)
|
|
.then((results) => {
|
|
prepareData(secFilingsList?.eightK);
|
|
})
|
|
.catch((error) => {
|
|
console.error("An error occurred:", error);
|
|
});
|
|
|
|
isLoaded = true;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="space-y-3 sm:pt-5">
|
|
<div class="bg-[#000] h-auto w-screen">
|
|
<!--Start Header-->
|
|
<div class="bg-[#000] w-full p-1 flex flex-col items-center pb-5 h-auto">
|
|
<h2 class="text-center m-auto text-lg font-semibold text-white mt-5">
|
|
SEC Filings
|
|
</h2>
|
|
|
|
<div class="w-11/12 mt-5">
|
|
<div class="relative right-0 bg-[#27272A] rounded-md">
|
|
<Tabs.Root value="eightK" class="w-full">
|
|
<Tabs.List class="grid w-full grid-cols-3 bg-[#27272A]">
|
|
<Tabs.Trigger on:click={() => changeSECType("8-K")} value="eightK"
|
|
>8-K</Tabs.Trigger
|
|
>
|
|
<Tabs.Trigger on:click={() => changeSECType("10-K")} value="tenK"
|
|
>10-K</Tabs.Trigger
|
|
>
|
|
<Tabs.Trigger on:click={() => changeSECType("10-Q")} value="tenQ"
|
|
>10-Q</Tabs.Trigger
|
|
>
|
|
</Tabs.List>
|
|
</Tabs.Root>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--End Header-->
|
|
{#if isLoaded}
|
|
{#if displayList?.length !== 0}
|
|
<div class="mt-5 w-full">
|
|
{#each displayList as item}
|
|
<div
|
|
class="flex flex-col justify-center m-auto items-start rounded-md bg-[#27272A] shadow-lg h-auto w-11/12 mb-3"
|
|
transition:fade={{ delay: 0, duration: 80 }}
|
|
in={accordionOpen[item?.year]}
|
|
>
|
|
<div class="flex flex-row items-center w-full p-3">
|
|
<div
|
|
class="flex-shrink-0 mr-2 rounded-full w-12 h-12 relative bg-[#000]"
|
|
>
|
|
<svg
|
|
class="rounded-full w-7 h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 24 24"
|
|
><path
|
|
fill="white"
|
|
d="m18 22l3-3l-.7-.7l-1.8 1.8V16h-1v4.1l-1.8-1.8l-.7.7zm-6-11.15l5.925-3.425L12 4L6.075 7.425zm-9 6.275V6.875L12 1.7l9 5.175V12h-2V9.1l-7.025 4.05L5 9.1v6.85l6.025 3.475v2.3zM18 24q-2.075 0-3.537-1.463T13 19q0-2.075 1.463-3.537T18 14q2.075 0 3.538 1.463T23 19q0 2.075-1.463 3.538T18 24m-6.975-12.275"
|
|
/></svg
|
|
>
|
|
</div>
|
|
|
|
<div
|
|
on:click={() => handleAccordion(item?.year)}
|
|
class="flex flex-row items-center w-full"
|
|
>
|
|
<div class="flex flex-col items-start w-full">
|
|
<span
|
|
class="text-white text-sm sm:text-md font-medium text-start mt-2"
|
|
>
|
|
{item?.year}
|
|
</span>
|
|
<span
|
|
class="text-white text-opacity-[0.6] text-xs text-start mb-2"
|
|
>
|
|
Total Reports: {item?.totalReports}
|
|
</span>
|
|
</div>
|
|
<svg
|
|
class="h-6 w-6 inline-block transform transition-transform mr-5 {accordionOpen[
|
|
item?.year
|
|
]
|
|
? ''
|
|
: 'rotate-180'}"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 1024 1024"
|
|
><path
|
|
fill="#fff"
|
|
d="m488.832 344.32l-339.84 356.672a32 32 0 0 0 0 44.16l.384.384a29.44 29.44 0 0 0 42.688 0l320-335.872l319.872 335.872a29.44 29.44 0 0 0 42.688 0l.384-.384a32 32 0 0 0 0-44.16L535.168 344.32a32 32 0 0 0-46.336 0z"
|
|
/></svg
|
|
>
|
|
</div>
|
|
</div>
|
|
{#if accordionOpen[item?.year]}
|
|
{#each item?.data as entry}
|
|
<div
|
|
class="shadow-lg bg-[#000] bg-opacity-[0.5] w-11/12 rounded-md p-4 mb-3 m-auto flex flex-row justify-center items-center"
|
|
>
|
|
<div class="flex flex-col -mt-2 w-full">
|
|
<div class="flex flex-row items-center w-full">
|
|
<span
|
|
class="text-white text-sm sm:text-md font-medium text-start mb-2 mr-auto mt-2"
|
|
>
|
|
{new Date(entry?.date)?.toLocaleString("en-US", {
|
|
month: "short",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
daySuffix: "2-digit",
|
|
})}
|
|
</span>
|
|
<span
|
|
class="text-white text-sm sm:text-md font-medium ml-auto"
|
|
>
|
|
<a
|
|
href={entry?.link}
|
|
rel="noopener noreferrer"
|
|
target="_blank"
|
|
>
|
|
Check Report
|
|
</a>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else}
|
|
<div
|
|
class=" mt-20 flex justify-center items-center text-2xl font-bold text-slate-700 mb-20 m-auto"
|
|
>
|
|
No data available
|
|
</div>
|
|
{/if}
|
|
{:else}
|
|
<div class="flex justify-center items-center h-80">
|
|
<div class="relative">
|
|
<label
|
|
class="bg-[#09090B] rounded-xl 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}
|
|
</div>
|
|
</div>
|
|
<!--End Similar Stocks Card -->
|