This commit is contained in:
MuslemRahimi 2024-10-28 00:37:30 +01:00
parent d6edfe2dc9
commit c7f8f9c48c
7 changed files with 263 additions and 217 deletions

View File

@ -73,7 +73,7 @@
<!--Start Header-->
<div
class="bg-[#313131] w-fit relative flex flex-wrap items-center justify-center rounded-lg p-1 -mt-2"
class="bg-[#313131] w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 -mt-2"
>
{#each tabs as item, i}
<button
@ -83,7 +83,7 @@
: ''} "
>
{#if activeIdx === i}
<div class="absolute inset-0 rounded-lg bg-purple-600"></div>
<div class="absolute inset-0 rounded-md bg-purple-600"></div>
{/if}
<span
class="relative text-sm block font-medium duration-200 text-white"
@ -112,7 +112,7 @@
<label
class="{latestInfoDate(rawData?.date)
? ''
: 'hidden'} bg-purple-600 mr-2 text-white font-medium not-italic text-xs rounded-lg px-2 py-0.5"
: 'hidden'} bg-purple-600 mr-2 text-white font-medium not-italic text-xs rounded-md px-2 py-0.5"
>New</label
>
Updated {rawData?.date}
@ -130,7 +130,7 @@
<p class="pr-1">{rawData?.bearSays}</p>
{:else}
<div
class="shadow-lg shadow-bg-[#000] bg-[#111112] 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"
class="bg-[#111112] 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"

View File

@ -1,6 +1,5 @@
<script lang="ts">
import { stockTicker, displayCompanyName } from "$lib/store";
import InfoModal from "$lib/components/InfoModal.svelte";
import { abbreviateNumber } from "$lib/utils";
export let data;
@ -49,17 +48,11 @@
<div class="flex flex-row justify-start mr-auto items-center">
<!--<img class="h-10 inline-block mr-2" src={copilotIcon} />-->
<div class="flex flex-row items-center">
<label
for="earningsSurprise"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
<h3
class="mr-1 flex flex-row items-center text-white text-xl sm:text-2xl font-bold"
>
Earnings Surprise
</label>
<InfoModal
title={"Earnings Surprise"}
content={`The earnings surprise is when a company's actual EPS differs from analysts' forecasts. Positive surprises boost stock prices; negative ones can lower them.`}
id={"earningsSurprise"}
/>
</h3>
</div>
</div>
</div>

View File

@ -1,24 +1,247 @@
<script lang="ts">
import TickerInfoCard from "$lib/components/TickerInfoCard.svelte";
import AnalystCard from "$lib/components/AnalystCard.svelte";
//import ESGCard from '$lib/components/ESGCard.svelte';
import SimilarTickerCard from "$lib/components/SimilarTickerCard.svelte";
import TopETFTickerHolder from "$lib/components/TopETFTickerHolder.svelte";
import { stockTicker, screenWidth } from "$lib/store";
import { abbreviateNumber } from "$lib/utils";
export let data;
export let stockDeck;
export let lastPrice;
export let similarstock;
export let topETFHolder;
export let analystRating;
let info;
let sector = "-";
let industry = "-";
let exchange = "-";
let employees = "-";
let description = "";
let website = "-";
let snippet;
let buyCount = 0;
let holdCount = 0;
let sellCount = 0;
let priceTarget = "n/a";
let numOfAnalyst = 0;
let consensusRating = "n/a";
let changesPercentage = 0;
let showFullText = false;
$: {
if (
$stockTicker &&
typeof window !== "undefined" &&
typeof data?.getStockDeck !== "undefined" &&
data?.getStockDeck?.length !== 0
) {
info = data?.getStockDeck?.at(0);
//ceoName = info?.ceoName?.length !== 0 ? getAbbreviatedName(info?.ceoName) : "-";
sector = info?.sector ?? "-";
industry = info?.industry ?? "-";
exchange = info?.exchange;
employees = info?.fullTimeEmployees ?? "-";
//country = info?.country ?? "-";
description =
info?.description ??
"A detailed description of the company is not yet available.";
website = info?.website;
snippet = description?.slice(0, 450) + "...";
numOfAnalyst = data?.getAnalystRating?.numOfAnalyst;
buyCount = ((data?.getAnalystRating?.Buy / numOfAnalyst) * 100)?.toFixed(
2,
);
holdCount = (
(data?.getAnalystRating?.Hold / numOfAnalyst) *
100
)?.toFixed(2);
sellCount = (
(data?.getAnalystRating?.Sell / numOfAnalyst) *
100
)?.toFixed(2);
priceTarget =
data?.getAnalystRating?.priceTarget !== ("n/a" && 0)
? data?.getAnalystRating?.priceTarget
: "-";
consensusRating = data?.getAnalystRating?.consensusRating;
try {
changesPercentage =
((priceTarget / data?.getStockQuote?.price - 1) * 100)?.toFixed(2) ??
0;
} catch (e) {
changesPercentage = 0;
}
}
}
</script>
<TickerInfoCard {data} {stockDeck} />
<div class="px-0.5 lg:px-0">
<h2 class="mb-2 text-2xl text-white font-semibold">
About {$stockTicker}
</h2>
<p class="text-gray-200">
{#if showFullText}
{description}
{:else}
{snippet}
{/if}
</p>
{#if description.length !== 0}
<div class="inline-block">
<label
on:click={() => (showFullText = !showFullText)}
class="hidden lg:block w-full text-md mt-1 cursor-pointer font-medium sm:hover:text-white text-blue-400 sm:hover:underline"
>
{#if showFullText}
[Show less]
{:else}
[Show more]
{/if}
</label>
</div>
{/if}
<AnalystCard {lastPrice} {analystRating} />
<div class="mt-3 grid grid-cols-2 gap-3 w-full">
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Industry</span>
<a
href={`/stocks/${$stockTicker}/statistics/employees`}
class="sm:hover:text-blue-400 text-white underline underline-offset-4"
>{industry}</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Sector</span>
<a
href={`/stocks/${$stockTicker}/statistics/employees`}
class="sm:hover:text-blue-400 text-white underline underline-offset-4"
>{sector}</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">IPO Date</span>
<span>Jan 22, 1999</span>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Employees</span>
<a
href={`/stocks/${$stockTicker}/statistics/employees`}
class="sm:hover:text-blue-400 text-white underline underline-offset-4"
>{new Intl.NumberFormat("en")?.format(employees)}</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Stock Exchange</span>
<span>{exchange}</span>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Ticker Symbol</span>
<span>{$stockTicker}</span>
</div>
<div class="col-span-1 whitespace-nowrap text-gray-200">
<span class="block font-semibold">Website</span>
<a
href={website}
class="hover:sm:text-white truncate text-blue-400"
target="_blank">{website}</a
>
</div>
</div>
</div>
<!--<ESGCard stockDeck={stockDeck} />-->
<div
class="space-y-3 sm:pt-5 hidden sm:block sm:{Object?.keys(
data?.getAnalystRating ?? {},
)?.length !== 0
? ''
: 'hidden'}"
>
<div class="h-auto w-full">
<!--Start Content-->
<div class="w-auto lg:w-full flex flex-col m-auto pb-14 sm:pb-10">
<h2 class="mb-2 text-2xl text-white font-semibold">Analyst Forecast</h2>
<p class="text-gray-200">
According to 40 analysts, the average rating for NVDA stock is "Strong
Buy." The 12-month stock price forecast is $145.84, which is an increase
of 3.04% from the latest price.
</p>
<!--<SimilarTickerCard similarstock={similarstock}/>-->
<div class="text-white mt-6">
{#if changesPercentage < 0}
The Stock Price has a downside of
<span style="color: #FF2F1F; font-weight: 500"
>{abbreviateNumber(Math.abs(changesPercentage))}%</span
>
{:else if changesPercentage >= 0}
The Stock Price has an upside of
<span style="color: #37C97D; font-weight: 500"
>{abbreviateNumber(Math.abs(changesPercentage))}%</span
>
{/if}
based on <span style="font-weight: 600">{numOfAnalyst}</span> analysts in
the past 12 months.
</div>
<!--<TopETFTickerHolder topETFHolder={topETFHolder}/>-->
<div class="mt-5 w-full m-auto flex justify-center items-center mb-5">
<div class="flex flex-col items-center w-full">
<!--Start Progress-->
<div class="flex flex-col items-center w-full">
<div class="flex flex-row items-center w-full mt-5 mb-2">
<span class="text-white font-medium text-start mr-auto">
Buy
</span>
<span class="text-white text-md font-medium ml-auto">
{buyCount}%
</span>
</div>
<progress
class="progress bg-[#3B3D3F] w-full [&::-webkit-progress-value]:bg-[#37C97D] [&::-moz-progress-bar]:bg-[#37C97D]"
value={buyCount}
max="100"
></progress>
</div>
<div class="flex flex-col items-center w-full">
<div class="flex flex-row items-center w-full mt-5 mb-2">
<span class="text-white font-medium text-start mr-auto">
Hold
</span>
<span class="text-white text-md font-medium ml-auto">
{holdCount}%
</span>
</div>
<progress
class="progress bg-[#3B3D3F] w-full [&::-webkit-progress-value]:bg-[#fff] [&::-moz-progress-bar]:bg-[#fff]"
value={holdCount}
max="100"
></progress>
</div>
<div class="flex flex-col items-center w-full">
<div class="flex flex-row items-center w-full mt-5 mb-2">
<span class="text-white font-medium text-start mr-auto">
Sell
</span>
<span class="text-white text-md font-medium ml-auto">
{sellCount}%
</span>
</div>
<progress
class="progress bg-[#3B3D3F] w-full [&::-webkit-progress-value]:bg-[#FF2F1F] [&::-moz-progress-bar]:bg-[#FF2F1F]"
value={sellCount}
max="100"
></progress>
</div>
<!--End Progress-->
</div>
</div>
<a
href={`/stocks/${$stockTicker}/forecast/analyst`}
class="rounded-md cursor-pointer w-full m-auto py-2 h-full mt-6 text-lg text-center font-bold text-white hover:bg-purple-700 bg-purple-600 transition duration-100"
>
Analyst Ratings
</a>
</div>
</div>
</div>

View File

@ -72,7 +72,7 @@
info?.description ??
"A detailed description of the company is not yet available.";
website = info?.website;
snippet = description?.slice(0, 150) + "...";
snippet = description?.slice(0, 250) + "...";
forwardPE = info?.forwardPE;
beta = info?.beta !== undefined ? info?.beta?.toFixed(2) : "-";
}

View File

@ -43,18 +43,16 @@ const fetchWatchlist = async (pb, userId) => {
return output;
};
export const load = async ({ params, locals, cookies, setHeaders }) => {
export const load = async ({ params, locals }) => {
const { apiURL, apiKey, pb, user } = locals;
const { tickerID } = params;
const endpoints = [
"/similar-stocks",
"/stockdeck",
"/analyst-summary-rating",
"/stock-quote",
"/bull-bear-say",
"/wiim",
"/top-etf-ticker-holder",
"/one-day-price",
"/next-earnings",
"/earnings-surprise",
@ -70,13 +68,11 @@ export const load = async ({ params, locals, cookies, setHeaders }) => {
];
const [
getSimilarStock,
getStockDeck,
getAnalystRating,
getStockQuote,
getBullBearSay,
getWhyPriceMoved,
getTopETFHolder,
getOneDayPrice,
getNextEarnings,
getEarningsSurprise,
@ -86,13 +82,11 @@ export const load = async ({ params, locals, cookies, setHeaders }) => {
] = await Promise.all(promises);
return {
getSimilarStock,
getStockDeck,
getAnalystRating,
getStockQuote,
getBullBearSay,
getWhyPriceMoved,
getTopETFHolder,
getOneDayPrice,
getNextEarnings,
getEarningsSurprise,

View File

@ -20,7 +20,6 @@
} from "$lib/store";
import { onMount, onDestroy, afterUpdate } from "svelte";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import toast from "svelte-french-toast";
import Sidecard from "$lib/components/Sidecard.svelte";
@ -62,8 +61,6 @@
let displaySection = "";
let stockDeck;
let similarstock = [];
let topETFHolder = [];
function shareContent(url) {
if (navigator.share) {
@ -298,8 +295,7 @@ function handleTypeOfTrade(state:string)
) {
// add a check to see if running on client-side
stockDeck = data?.getStockDeck;
similarstock = data?.getSimilarStock;
topETFHolder = data?.getTopETFHolder;
$currentPortfolioPrice = data?.getStockQuote?.price;
}
}
@ -893,54 +889,6 @@ function handleTypeOfTrade(state:string)
<!--End Main Content-->
</div>
</div>
<aside
class="hidden w-fit max-w-xl xl:w-[120px] md:pt-10 pb-12 md:pb-20"
>
<div class="sm:pl-10">
<!--Start Company Info -->
<Sidecard
{data}
{stockDeck}
lastPrice={data?.getStockQuote?.price}
analystRating={data?.getAnalystRating}
{similarstock}
{topETFHolder}
/>
<!--End Company Info -->
</div>
</aside>
<!--
{#if $screenWidth < 640 && MobileStockNavbar}
<MobileStockNavbar
logoUrl={logoUrl}
holdingShares={holdingShares}
userPortfolio={userPortfolio}
stockDeck={stockDeck}
similarstock={similarstock}
data={data}
/>
{/if}
-->
<!--
<div class="sm:hidden fixed z-20 bottom-8 sm:bottom-10 right-5">
<div class="h-full mx-auto">
<div class="flex items-center justify-end">
{#if holdingShares !== 0 && data?.user}
<label for="{!data?.user ? 'userLogin' : userPortfolio?.length !== 0 ? 'typeOfTrade' : ''}" class="inline-flex items-center justify-center w-32 h-11 border border-[#000] ring-[#000] bg-[#0DDE00] text-[0.95rem] font-medium rounded-full text-[#09090B]">
Invest
</label>
{:else}
<label for="{!data?.user ? 'userLogin' : userPortfolio?.length === 0 ? 'addPortfolio' : 'buyTradeModal'}"
class="inline-flex items-center justify-center w-32 h-11 border border-[#000] ring-[#000] bg-[#0DDE00] text-[0.95rem] font-medium rounded-full text-[#09090B]">
Invest
</label>
{/if}
</div>
</div>
</div>
-->
</div>
</div>
</div>

View File

@ -20,10 +20,13 @@
} from "$lib/store";
import { onDestroy, onMount } from "svelte";
import BullBearSay from "$lib/components/BullBearSay.svelte";
import WIIM from "$lib/components/WIIM.svelte";
import News from "$lib/components/News.svelte";
import NextEarnings from "$lib/components/NextEarnings.svelte";
import EarningsSurprise from "$lib/components/EarningsSurprise.svelte";
import DividendAnnouncement from "$lib/components/DividendAnnouncement.svelte";
import Sidecard from "$lib/components/Sidecard.svelte";
import Lazy from "$lib/components/Lazy.svelte";
import { convertTimestamp } from "$lib/utils";
@ -1579,123 +1582,12 @@
<!--End Graph-->
<div class="mt-6 flex flex-row gap-x-14 items-start w-full">
<div class="space-y-6 lg:order-2 lg:pt-1 w-[40%] ml-auto">
<div class="px-0.5 lg:px-0">
<h2 class="mb-2 text-2xl text-white font-semibold">
About {$stockTicker}
</h2>
<p class="text-gray-200">
NVIDIA Corporation provides graphics and compute and
networking solutions in the United States, Taiwan, China, Hong
Kong, and internationally. The Graphics segment offers GeForce
GPUs for gaming and PCs, the GeForce NOW game streaming
service and related infrastructure, and solutions for gaming
platforms; Quadro/NVIDIA RTX GPUs for enterprise workstation
graphics; virtual GPU or vGPU software for cloud-based visual
and virtual computing; automotive platforms for infotainment
systems; and Omniverse software for building and operating
metaverse a... <a
href="/stocks/nvda/company/"
title="View company profile"
tabindex="-1">[Read more]</a
>
</p>
<div
class="mt-3 grid grid-cols-2 gap-3"
data-test="overview-profile-values"
>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Industry</span>
<a
href="/stocks/industry/semiconductors/"
class="dothref text-default">Semiconductors</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Sector</span>
<a
href="/stocks/sector/technology/"
class="dothref text-default">Technology</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">IPO Date</span>
<span>Jan 22, 1999</span>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Employees</span>
<a
href="/stocks/nvda/employees/"
class="dothref text-default">29,600</a
>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Stock Exchange</span>
<span>NASDAQ</span>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Ticker Symbol</span>
<span>{$stockTicker}</span>
</div>
<div class="col-span-1 whitespace-nowrap text-gray-200">
<span class="block font-semibold">Website</span>
<a href="https://www.nvidia.com" target="_blank"
>https://www.nvidia.com</a
>
</div>
</div>
</div>
<div>
<h2 class="mb-2 text-white text-2xl font-semibold">
Analyst Forecast
</h2>
<p class="mb-4 text-gray-200">
According to 40 analysts, the average rating for NVDA stock is
"Strong Buy." The 12-month stock price forecast is $145.84,
which is an increase of 3.04% from the latest price.
</p>
<div
data-test="overview-forecast-targetchart"
class="border border-gray-600 p-2 xs:p-3"
>
<div
class="m-auto mb-2 text-center text-xl font-semibold text-default"
data-svelte-h="svelte-5xi68b"
>
Price Target
</div>
<div
class="mb-0.5 text-center text-4xl font-semibold text-green-vivid"
>
$145.84
</div>
<div class="mb-1.5 text-center text-xl">(3.04% upside)</div>
<div
class="py-1 text-center text-lg font-semibold text-default"
>
Analyst Consensus: <span
class="font-bold text-green-default">Strong Buy</span
>
</div>
<div></div>
</div>
</div>
<div class="space-y-6 lg:order-2 lg:pt-1 w-[45%] ml-auto">
<Sidecard {data} />
<div class="lg:sticky lg:top-20"></div>
</div>
<div class="w-full">
<div class="w-full mt-10 m-auto sm:p-6 lg:hidden">
<Lazy>
<h3
class="cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
>
Key Information
</h3>
{#await import("$lib/components/StockKeyInformation.svelte") then { default: Comp }}
<svelte:component this={Comp} {data} />
{/await}
</Lazy>
</div>
<div class="w-full">
<div
class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 {Object?.keys(
data?.getEarningsSurprise || {},
@ -1736,18 +1628,14 @@
<BullBearSay {data} />
</div>
<Lazy>
<div
class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 {data
?.getWhyPriceMoved?.length !== 0
? ''
: 'hidden'}"
>
{#await import("$lib/components/WIIM.svelte") then { default: Comp }}
<svelte:component this={Comp} {data} />
{/await}
</div>
</Lazy>
<div
class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 {data
?.getWhyPriceMoved?.length !== 0
? ''
: 'hidden'}"
>
<WIIM {data} />
</div>
<div
class="w-full mt-10 sm:mt-0 m-auto sm:pl-6 sm:pb-6 sm:pt-6 {data