add Analyst Insight Component

This commit is contained in:
MuslemRahimi 2024-07-07 18:44:00 +02:00
parent 098a5696e7
commit c11c5f8f85
3 changed files with 238 additions and 2 deletions

View File

@ -0,0 +1,228 @@
<script lang ='ts'>
import { analystInsightComponent, displayCompanyName, stockTicker, screenWidth, userRegion, getCache, setCache} from '$lib/store';
import InfoModal from '$lib/components/InfoModal.svelte';
import { abbreviateNumber, formatString } from "$lib/utils";
export let data;
let isLoaded = false;
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
let rawData = {};
function latestInfoDate(inputDate) {
// Convert the input date string to milliseconds since epoch
const inputDateMs = Date?.parse(inputDate);
// Get today's date in milliseconds since epoch
const todayMs = Date?.now();
// Calculate the difference in milliseconds
const differenceInMs = todayMs - inputDateMs;
// Convert milliseconds to days
const differenceInDays = Math?.floor(differenceInMs / (1000 * 60 * 60 * 24));
// Return the difference in days
return differenceInDays <=1;
}
const getAnalystInsight = async (ticker) => {
// Get cached data for the specific tickerID
const cachedData = getCache(ticker, 'getAnalystInsight');
if (cachedData) {
rawData = cachedData;
} else {
const postData = {'ticker': ticker};
// make the POST request to the endpoint
const response = await fetch(apiURL + '/analyst-insight', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData)
});
rawData = await response.json();
// Cache the data for this specific tickerID with a specific name 'getAnalystInsight'
setCache(ticker, rawData, 'getAnalystInsight');
}
if(Object?.keys(rawData)?.length !== 0) {
$analystInsightComponent = true;
} else {
$analystInsightComponent = false;
}
};
$: {
if($stockTicker && typeof window !== 'undefined') {
isLoaded=false;
const ticker = $stockTicker;
const asyncFunctions = [
getAnalystInsight(ticker)
];
Promise.all(asyncFunctions)
.then((results) => {
})
.catch((error) => {
console.error('An error occurred:', error);
});
isLoaded = true;
}
}
let charNumber = 20;
$: {
if($screenWidth < 640)
{
charNumber = 20;
}
else {
charNumber =40;
}
}
</script>
<section class="overflow-hidden text-white h-full pb-8">
<main class="overflow-hidden ">
<div class="flex flex-row items-center">
<label for="analystInsightInfo" class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold">
AI Analyst Insight
</label>
<InfoModal
title={"AI Analyst Insight"}
content={"We use large language models to analyze the latest reports from Wall Street analysts, providing concise summaries and key insights. This approach helps save time and allows you to focus on the most important information."}
id={"analystInsightInfo"}
/>
</div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded}
{#if Object?.keys(rawData)?.length !== 0}
<div class="w-full flex flex-col items-start">
<div class="text-white text-sm sm:text-[1rem] mt-2 mb-2 w-full">
The AI model summarizes the latest Wallstreet Analyst Insight Report and extracts key points for you, focusing on what matters most.
</div>
</div>
<div class="w-full mt-4">
<a href="{'/stocks/'+$stockTicker+'/analyst'}" class="text-blue-400 hover:text-white flex justify-end mb-3 text-sm sm:text-[1rem]">
See All Ratings
</a>
<div class="relative">
<div class="">
<div class="flex justify-center ">
<!--<div class="{rawData.changesPercentage >= 0 ? 'bg-[#10DB06]' : 'bg-[#FF2F1F]'} w-1.5 mb-5 rounded-l-xl" />-->
<!--Start Item-->
<div class="flex flex-row items-center w-full mb-6">
<div class="w-full rounded-lg {latestInfoDate(rawData?.date) ? 'bg-[#F9AB00] bg-opacity-[0.1]' : 'bg-[#202020]'} shadow-lg h-full pl-3 pt-2 pb-4">
<div class="flex flex-col items-start">
<div class="flex flex-row items-start w-full pt-2">
<span class="text-white text-sm pl-2 italic">Last Report from {rawData.date}</span>
{#if latestInfoDate(rawData.date)}
<label class="bg-[#2D4F8A] text-white font-medium text-xs rounded-lg px-2 py-0.5 ml-3">New</label>
{/if}
</div>
<div class="flex flex-col w-full pt-3 pl-2 pr-2 sm:pr-4">
<span class="text-white text-sm ">
{rawData?.insight }
</span>
</div>
</div>
</div>
</div>
<!--End Item-->
</div>
</div>
</div>
</div>
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label class="bg-[#202020] 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"></span>
</label>
</div>
</div>
{/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#202020] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" 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>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main>
</section>
<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

@ -78,7 +78,7 @@ export const borrowedShareComponent= writable(<boolean>(false));
export const impliedVolatilityComponent= writable(<boolean>(false)); export const impliedVolatilityComponent= writable(<boolean>(false));
export const optionsNetFlowComponent= writable(<boolean>(false)); export const optionsNetFlowComponent= writable(<boolean>(false));
export const governmentContractComponent= writable(<boolean>(false)); export const governmentContractComponent= writable(<boolean>(false));
export const analystInsightComponent= writable(<boolean>(false));

View File

@ -3,7 +3,7 @@
import {AreaSeries, Chart, PriceLine, CandlestickSeries} from 'svelte-lightweight-charts'; import {AreaSeries, Chart, PriceLine, CandlestickSeries} from 'svelte-lightweight-charts';
import { TrackingModeExitMode } from 'lightweight-charts'; import { TrackingModeExitMode } from 'lightweight-charts';
import {getCache, setCache, governmentContractComponent, optionsNetFlowComponent, impliedVolatilityComponent, borrowedShareComponent, clinicalTrialComponent, optionComponent, failToDeliverComponent, marketMakerComponent, analystEstimateComponent, sentimentComponent, screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, varComponent, shareStatisticsComponent, enterpriseComponent, darkPoolComponent, retailVolumeComponent, shareholderComponent, trendAnalysisComponent, revenueSegmentationComponent, priceAnalysisComponent, fundamentalAnalysisComponent, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, stockTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store'; import {getCache, setCache, analystInsightComponent, governmentContractComponent, optionsNetFlowComponent, impliedVolatilityComponent, borrowedShareComponent, clinicalTrialComponent, optionComponent, failToDeliverComponent, marketMakerComponent, analystEstimateComponent, sentimentComponent, screenWidth, displayCompanyName, numberOfUnreadNotification, globalForm, varComponent, shareStatisticsComponent, enterpriseComponent, darkPoolComponent, retailVolumeComponent, shareholderComponent, trendAnalysisComponent, revenueSegmentationComponent, priceAnalysisComponent, fundamentalAnalysisComponent, userRegion, isCrosshairMoveActive, realtimePrice, priceIncrease, currentPortfolioPrice, currentPrice, stockTicker, isOpen, isBeforeMarketOpen, isWeekend} from '$lib/store';
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte';
import BullBearSay from '$lib/components/BullBearSay.svelte'; import BullBearSay from '$lib/components/BullBearSay.svelte';
import CommunitySentiment from '$lib/components/CommunitySentiment.svelte'; import CommunitySentiment from '$lib/components/CommunitySentiment.svelte';
@ -1244,6 +1244,14 @@ function changeChartType() {
{/if} {/if}
<Lazy>
<div class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pt-6 {!$analystInsightComponent ? 'hidden' : ''}">
{#await import('$lib/components/AnalystInsight.svelte') then {default: Comp}}
<svelte:component this={Comp} data={data} />
{/await}
</div>
</Lazy>
<Lazy> <Lazy>
<div class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 sm:pt-6 {!$clinicalTrialComponent ? 'hidden' : ''}"> <div class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 sm:pt-6 {!$clinicalTrialComponent ? 'hidden' : ''}">
{#await import('$lib/components/ClinicalTrial.svelte') then {default: Comp}} {#await import('$lib/components/ClinicalTrial.svelte') then {default: Comp}}