update forecast overview page

This commit is contained in:
MuslemRahimi 2024-08-31 13:35:47 +02:00
parent f8ed49b3d4
commit defd8a9283
4 changed files with 113 additions and 39 deletions

View File

@ -1,8 +1,20 @@
<script lang="ts">
import { numberOfUnreadNotification, displayCompanyName, stockTicker, analystEstimateComponent, currentPortfolioPrice } from "$lib/store";
import { numberOfUnreadNotification, displayCompanyName, stockTicker, analystEstimateComponent } from "$lib/store";
import { abbreviateNumber } from "$lib/utils";
import Lazy from "$lib/components/Lazy.svelte";
export let data;
function findIndex(data) {
const currentYear = new Date().getFullYear();
return data.findIndex(item => item.date >= currentYear && item.revenue === null);
}
const index = findIndex(data?.getAnalystEstimate);
const changeRevenue = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg/data?.getAnalystEstimate[index-2]?.revenue-1)*100))?.toFixed(1)
const changeNetIncome = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg/data?.getAnalystEstimate[index-2]?.netIncome-1)*100))?.toFixed(1)
const changeEBITDA = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg/data?.getAnalystEstimate[index-2]?.ebitda-1)*100)?.toFixed(1))
const changeEPS = abbreviateNumber(((data?.getAnalystEstimate[index-1]?.estimatedEpsAvg/data?.getAnalystEstimate[index-2]?.eps-1)*100))?.toFixed(1)
</script>
<svelte:head>
@ -31,6 +43,84 @@
<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">
<h2 class="mt-5 text-xl sm:text-2xl text-gray-200 font-bold mb-4">
Financial Forecast this Year
</h2>
<div class="mb-4 grid grid-cols-2 grid-rows-1 divide-gray-500 rounded-lg border border-gray-600 bg-[#272727] shadow md:grid-cols-4 md:grid-rows-1 md:divide-x">
<div class="p-4 bp:p-5 sm:p-6">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
Revenue
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedRevenueAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeRevenue > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeRevenue}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.revenue)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-l border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
Net Income
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedNetIncomeAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeNetIncome > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeNetIncome}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.netIncome,true)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-t border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
EBITDA
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{abbreviateNumber(data?.getAnalystEstimate[index-1]?.estimatedEbitdaAvg,true)}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeEBITDA > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeEBITDA}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {abbreviateNumber(data?.getAnalystEstimate[index-2]?.ebitda,true)}
</div>
</div>
<div class="p-4 bp:p-5 sm:p-6 border-t border-contrast md:border-0 border-l border-contrast md:border-0">
<label class="mr-1 cursor-pointer flex flex-row items-center text-white text-[1rem] font-semibold">
EPS
</label>
<div class="mt-1 flex flex-col items-baseline justify-start space-y-2 bp:space-y-0">
<div class="flex items-baseline text-2xl font-semibold text-white">
{data?.getAnalystEstimate[index-1]?.estimatedEpsAvg}
</div>
<div class="inline-flex items-baseline rounded-full px-2.5 py-0.5 text-sm font-semibold md:mt-2 lg:mt-0 bg-green-100 text-green-800 dark:bg-green-700 dark:text-dark-100">
<svg class="-ml-1 mr-0.5 h-5 w-5 flex-shrink-0 self-center {changeEPS > 0 ? 'text-green-500' : 'text-red-500 rotate-180'}" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="max-width:40px" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 11l5-5m0 0l5 5m-5-5v12"></path></svg>
{changeEPS}%
</div>
</div>
<div class="ml-0.5 mt-1.5 text-sm font-semibold text-white/60 lg:block">
from {data?.getAnalystEstimate[index-2]?.eps}
</div>
</div>
</div>
<Lazy>
<div class="w-full m-auto sm:pb-6 sm:pt-6 {!$analystEstimateComponent ? 'hidden' : ''}">
{#await import("$lib/components/AnalystEstimate.svelte") then { default: Comp }}

View File

@ -1,36 +1,32 @@
import { getCache, setCache } from '$lib/store';
import { getCache, setCache } from "$lib/store";
export const load = async ({ parent, params }) => {
const getAnalystTickerHistory = async () => {
const getAnalystEstimate = async () => {
let output;
const cachedData = getCache(params.tickerID, 'getAnalystTickerHistory');
if (cachedData) {
output = cachedData;
} else {
const cachedData = getCache(params.tickerID, "getAnalystEstimate");
if (cachedData) {
output = cachedData;
} else {
const { apiURL, apiKey } = await parent();
const {apiURL, apiKey} = await parent();
const postData = {
ticker: params.tickerID
};
const postData = {
ticker: params.tickerID,
};
// make the POST request to the endpoint
const response = await fetch(apiURL + '/analyst-ticker-history', {
method: 'POST',
const response = await fetch(apiURL + "/analyst-estimate", {
method: "POST",
headers: {
"Content-Type": "application/json", "X-API-KEY": apiKey
"Content-Type": "application/json",
"X-API-KEY": apiKey,
},
body: JSON.stringify(postData)
body: JSON.stringify(postData),
});
output = await response.json();
output = await response.json();
setCache(params.tickerID, output, 'getAnalystTickerHistory');
setCache(params.tickerID, output, "getAnalystEstimate");
}
return output;
@ -38,6 +34,6 @@ export const load = async ({ parent, params }) => {
// Make sure to return a promise
return {
getAnalystTickerHistory: await getAnalystTickerHistory()
getAnalystEstimate: await getAnalystEstimate(),
};
};

View File

@ -190,7 +190,7 @@ changeTab(0)
{/if}
</div>
</div>
</div>
</div>

View File

@ -3,21 +3,12 @@
import ReturnCard from "$lib/components/ReturnCard.svelte";
import { numberOfUnreadNotification, displayCompanyName, screenWidth, stockTicker, revenueSegmentationComponent } from "$lib/store";
import { abbreviateNumber } from "$lib/utils";
import RevenueSegmentation from "$lib/components/RevenueSegmentation.svelte";
export let data;
let quantStats = {};
let stockQuote;
let marketCap = "-";
let currentPrice = 0;
let previousClose = "-";
let volume = "-";
let eps = "-";
let pe = "-";
let alpha = "-";
let beta = "-";
// Function to check if a date is today or yesterday, adjusting for weekends
function ongoingDD(dateString: string) {
@ -75,7 +66,6 @@ if (progressYearPriceValue < currentPrice) {
stockQuote = data?.getStockQuote;
quantStats = data?.getQuantStats ?? {};
@ -218,9 +208,7 @@ updateYearRange()
<!--Start RevenueSegmentation-->
<Lazy>
<div class="w-full pt-10 sm:pb-6 sm:pt-6 m-auto {!$revenueSegmentationComponent ? 'hidden' : ''}">
{#await import("$lib/components/RevenueSegmentation.svelte") then { default: Comp }}
<svelte:component this={Comp} apiURL={data?.apiURL} apiKey={data?.apiKey} userTier={data?.user?.tier} />
{/await}
<RevenueSegmentation apiURL={data?.apiURL} apiKey={data?.apiKey} userTier={data?.user?.tier} />
</div>
</Lazy>
<!--End RevenueSegmentation-->
@ -230,7 +218,7 @@ updateYearRange()
{#if $stockTicker in quantStats && Object.keys(quantStats[$stockTicker]).length > 0}
<h3 class="text-start w-full mt-8 mb-2 text-lg sm:text-2xl font-bold text-white">
<h3 class="text-start w-full mb-2 text-lg sm:text-2xl font-bold text-white">
Worst 10 Drawdowns of {$stockTicker}
</h3>
<div class="w-full overflow-x-scroll">