ui fix
This commit is contained in:
parent
5cf8d27ad1
commit
e442fb10d5
@ -163,7 +163,8 @@
|
||||
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx === i
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
>
|
||||
|
||||
@ -58,23 +58,23 @@
|
||||
website = info?.website;
|
||||
snippet = description?.slice(0, 450) + "...";
|
||||
|
||||
numOfAnalyst = data?.getAnalystRating?.numOfAnalyst;
|
||||
buyCount = ((data?.getAnalystRating?.Buy / numOfAnalyst) * 100)?.toFixed(
|
||||
numOfAnalyst = data?.getAnalystSummary?.numOfAnalyst;
|
||||
buyCount = ((data?.getAnalystSummary?.Buy / numOfAnalyst) * 100)?.toFixed(
|
||||
2,
|
||||
);
|
||||
holdCount = (
|
||||
(data?.getAnalystRating?.Hold / numOfAnalyst) *
|
||||
(data?.getAnalystSummary?.Hold / numOfAnalyst) *
|
||||
100
|
||||
)?.toFixed(2);
|
||||
sellCount = (
|
||||
(data?.getAnalystRating?.Sell / numOfAnalyst) *
|
||||
(data?.getAnalystSummary?.Sell / numOfAnalyst) *
|
||||
100
|
||||
)?.toFixed(2);
|
||||
priceTarget =
|
||||
data?.getAnalystRating?.medianPriceTarget !== ("n/a" && 0)
|
||||
? data?.getAnalystRating?.medianPriceTarget
|
||||
data?.getAnalystSummary?.medianPriceTarget !== ("n/a" && 0)
|
||||
? data?.getAnalystSummary?.medianPriceTarget
|
||||
: "n/a";
|
||||
consensusRating = data?.getAnalystRating?.consensusRating;
|
||||
consensusRating = data?.getAnalystSummary?.consensusRating;
|
||||
|
||||
try {
|
||||
changesPercentage =
|
||||
@ -165,9 +165,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if Object?.keys(data?.getAnalystRating ?? {})?.length !== 0}
|
||||
{#if Object?.keys(data?.getAnalystSummary ?? {})?.length !== 0}
|
||||
<div
|
||||
class="space-y-3 pt-10 sm:pt-5 {Object?.keys(data?.getAnalystRating ?? {})
|
||||
class="space-y-3 pt-10 sm:pt-5 {Object?.keys(data?.getAnalystSummary ?? {})
|
||||
?.length !== 0
|
||||
? ''
|
||||
: 'hidden'}"
|
||||
|
||||
@ -783,7 +783,7 @@
|
||||
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -96,7 +96,7 @@ export const load = async ({ params, locals }) => {
|
||||
try {
|
||||
const [
|
||||
getStockDeck,
|
||||
getAnalystRating,
|
||||
getAnalystSummary,
|
||||
getStockQuote,
|
||||
getPrePostQuote,
|
||||
getWhyPriceMoved,
|
||||
@ -118,7 +118,7 @@ export const load = async ({ params, locals }) => {
|
||||
|
||||
return {
|
||||
getStockDeck,
|
||||
getAnalystRating,
|
||||
getAnalystSummary,
|
||||
getStockQuote,
|
||||
getPrePostQuote,
|
||||
getWhyPriceMoved,
|
||||
|
||||
@ -941,7 +941,7 @@
|
||||
>Metrics</a
|
||||
>
|
||||
|
||||
{#if Object?.keys(data?.getAnalystRating ?? {})?.length > 0}
|
||||
{#if Object?.keys(data?.getAnalystSummary ?? {})?.length > 0}
|
||||
<a
|
||||
href={`/stocks/${$stockTicker}/forecast`}
|
||||
on:click={() => changeSection("forecast")}
|
||||
|
||||
@ -1031,11 +1031,11 @@
|
||||
><td
|
||||
class="whitespace-nowrap px-0.5 py-[1px] xs:px-1 sm:py-2 text-[1rem]"
|
||||
><a
|
||||
href={data?.getAnalystRating?.consensusRating !==
|
||||
href={data?.getAnalystSummary?.consensusRating !==
|
||||
undefined
|
||||
? `/stocks/${$stockTicker}/forecast`
|
||||
: ""}
|
||||
class={data?.getAnalystRating?.consensusRating !==
|
||||
class={data?.getAnalystSummary?.consensusRating !==
|
||||
undefined
|
||||
? "sm:hover:text-blue-400 text-white underline underline-offset-4"
|
||||
: "text-white cursor-text"}>Analyst</a
|
||||
@ -1043,10 +1043,10 @@
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-0.5 py-[1px] text-left text-sm font-semibold xs:px-1 sm:py-2 sm:text-right sm:text-[1rem]"
|
||||
>{data?.getAnalystRating?.consensusRating !== null &&
|
||||
data?.getAnalystRating?.consensusRating !== "n/a" &&
|
||||
data?.getAnalystRating?.consensusRating !== undefined
|
||||
? data?.getAnalystRating?.consensusRating
|
||||
>{data?.getAnalystSummary?.consensusRating !== null &&
|
||||
data?.getAnalystSummary?.consensusRating !== "n/a" &&
|
||||
data?.getAnalystSummary?.consensusRating !== undefined
|
||||
? data?.getAnalystSummary?.consensusRating
|
||||
: "n/a"}</td
|
||||
></tr
|
||||
>
|
||||
|
||||
@ -491,7 +491,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
import Infobox from "$lib/components/Infobox.svelte";
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
|
||||
use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
|
||||
|
||||
export let data;
|
||||
@ -478,8 +477,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<SEO
|
||||
title={`${$displayCompanyName} (${$stockTicker}) Balance Sheet · Stocknear`}
|
||||
description={`Detailed balance sheet for ${$displayCompanyName} (${$stockTicker}), including cash, debt, assets, liabilities, and book value.`}
|
||||
@ -550,7 +547,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
import Infobox from "$lib/components/Infobox.svelte";
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
|
||||
use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
|
||||
|
||||
export let data;
|
||||
@ -424,8 +423,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<SEO
|
||||
title={`${$displayCompanyName} (${$stockTicker}) Cash Flow Statement · Stocknear`}
|
||||
description={`Detailed cash flow statements for ${$displayCompanyName} (${$stockTicker}), including operating cash flow, capex and free cash flow.`}
|
||||
@ -494,7 +491,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -478,7 +478,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -50,10 +50,26 @@ export const load = async ({ locals, params }) => {
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
const getTopAnalystSummary = async () => {
|
||||
const response = await fetch(apiURL + "/top-analyst-summary-rating", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-API-KEY": apiKey,
|
||||
},
|
||||
body: JSON.stringify(postData),
|
||||
});
|
||||
|
||||
const output = await response.json();
|
||||
return output;
|
||||
};
|
||||
|
||||
// Make sure to return a promise
|
||||
return {
|
||||
getAnalystEstimate: await getAnalystEstimate(),
|
||||
getAnalystInsight: await getAnalystInsight(),
|
||||
getAnalystTickerHistory: await getAnalystTickerHistory(),
|
||||
getTopAnalystSummary: await getTopAnalystSummary(),
|
||||
};
|
||||
};
|
||||
|
||||
@ -2,6 +2,10 @@ import { error, fail, redirect } from "@sveltejs/kit";
|
||||
import { validateData } from "$lib/utils";
|
||||
import { loginUserSchema, registerUserSchema } from "$lib/schemas";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const actions = {
|
||||
login: async ({ url, request, locals }) => {
|
||||
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
import { LineChart, BarChart, GaugeChart } from "echarts/charts";
|
||||
import { GridComponent, TooltipComponent } from "echarts/components";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
export let data;
|
||||
@ -37,21 +39,75 @@
|
||||
|
||||
const calculatePriceChange = (targetPrice) =>
|
||||
targetPrice && price ? ((targetPrice / price - 1) * 100)?.toFixed(2) : 0;
|
||||
const numOfAnalyst = data?.getAnalystRating?.numOfAnalyst || 0;
|
||||
const avgPriceTarget = data?.getAnalystRating?.avgPriceTarget || 0;
|
||||
const medianPriceTarget = data?.getAnalystRating?.medianPriceTarget || 0;
|
||||
const lowPriceTarget = data?.getAnalystRating?.lowPriceTarget || 0;
|
||||
const highPriceTarget = data?.getAnalystRating?.highPriceTarget || 0;
|
||||
const consensusRating = data?.getAnalystRating?.consensusRating;
|
||||
|
||||
const lowChange = calculatePriceChange(lowPriceTarget);
|
||||
const medianChange = calculatePriceChange(medianPriceTarget);
|
||||
const avgChange = calculatePriceChange(avgPriceTarget);
|
||||
const highChange = calculatePriceChange(highPriceTarget);
|
||||
const rawAnalystList = data?.getAnalystRating?.recommendationList || [];
|
||||
const recommendationList =
|
||||
let numOfAnalyst = data?.getAnalystSummary?.numOfAnalyst || 0;
|
||||
let avgPriceTarget = data?.getAnalystSummary?.avgPriceTarget || 0;
|
||||
let medianPriceTarget = data?.getAnalystSummary?.medianPriceTarget || 0;
|
||||
let lowPriceTarget = data?.getAnalystSummary?.lowPriceTarget || 0;
|
||||
let highPriceTarget = data?.getAnalystSummary?.highPriceTarget || 0;
|
||||
let consensusRating = data?.getAnalystSummary?.consensusRating;
|
||||
|
||||
let lowChange = calculatePriceChange(lowPriceTarget);
|
||||
let medianChange = calculatePriceChange(medianPriceTarget);
|
||||
let avgChange = calculatePriceChange(avgPriceTarget);
|
||||
let highChange = calculatePriceChange(highPriceTarget);
|
||||
let rawAnalystList = data?.getAnalystSummary?.recommendationList || [];
|
||||
let recommendationList =
|
||||
rawAnalystList?.length > 5 ? rawAnalystList?.slice(-6) : rawAnalystList;
|
||||
const categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
|
||||
let categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: "All Analysts",
|
||||
},
|
||||
{
|
||||
title: "Top Analysts",
|
||||
},
|
||||
];
|
||||
let activeIdx = 0;
|
||||
|
||||
function changeTab(index) {
|
||||
activeIdx = index;
|
||||
if (activeIdx === 0) {
|
||||
numOfAnalyst = data?.getAnalystSummary?.numOfAnalyst || 0;
|
||||
avgPriceTarget = data?.getAnalystSummary?.avgPriceTarget || 0;
|
||||
medianPriceTarget = data?.getAnalystSummary?.medianPriceTarget || 0;
|
||||
lowPriceTarget = data?.getAnalystSummary?.lowPriceTarget || 0;
|
||||
highPriceTarget = data?.getAnalystSummary?.highPriceTarget || 0;
|
||||
consensusRating = data?.getAnalystSummary?.consensusRating;
|
||||
|
||||
lowChange = calculatePriceChange(lowPriceTarget);
|
||||
medianChange = calculatePriceChange(medianPriceTarget);
|
||||
avgChange = calculatePriceChange(avgPriceTarget);
|
||||
highChange = calculatePriceChange(highPriceTarget);
|
||||
rawAnalystList = data?.getAnalystSummary?.recommendationList || [];
|
||||
recommendationList =
|
||||
rawAnalystList?.length > 5 ? rawAnalystList?.slice(-6) : rawAnalystList;
|
||||
categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
|
||||
} else {
|
||||
numOfAnalyst = data?.getTopAnalystSummary?.numOfAnalyst || 0;
|
||||
avgPriceTarget = data?.getTopAnalystSummary?.avgPriceTarget || 0;
|
||||
medianPriceTarget = data?.getTopAnalystSummary?.medianPriceTarget || 0;
|
||||
lowPriceTarget = data?.getTopAnalystSummary?.lowPriceTarget || 0;
|
||||
highPriceTarget = data?.getTopAnalystSummary?.highPriceTarget || 0;
|
||||
consensusRating = data?.getTopAnalystSummary?.consensusRating;
|
||||
|
||||
lowChange = calculatePriceChange(lowPriceTarget);
|
||||
medianChange = calculatePriceChange(medianPriceTarget);
|
||||
avgChange = calculatePriceChange(avgPriceTarget);
|
||||
highChange = calculatePriceChange(highPriceTarget);
|
||||
rawAnalystList = data?.getTopAnalystSummary?.recommendationList || [];
|
||||
recommendationList =
|
||||
rawAnalystList?.length > 5 ? rawAnalystList?.slice(-6) : rawAnalystList;
|
||||
categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
|
||||
|
||||
console.log(recommendationList);
|
||||
}
|
||||
|
||||
optionsData = getPlotOptions() || null;
|
||||
optionsPieChart = getPieChart() || null;
|
||||
optionsPriceForecast = getPriceForecastChart() || null;
|
||||
}
|
||||
|
||||
function findIndex(data) {
|
||||
let year = new Date().getFullYear() - 1;
|
||||
@ -78,8 +134,8 @@
|
||||
return -1; // Return -1 if no matching index is found
|
||||
}
|
||||
|
||||
function getTotalForDate(index) {
|
||||
return categories.reduce(
|
||||
function getTotalForDate(index, recommendationList) {
|
||||
return categories?.reduce(
|
||||
(sum, cat) => sum + recommendationList[index][cat],
|
||||
0,
|
||||
);
|
||||
@ -291,7 +347,7 @@
|
||||
}
|
||||
|
||||
function getPriceForecastChart() {
|
||||
const historicalData = data?.getAnalystRating?.pastPriceList || [];
|
||||
const historicalData = data?.getAnalystSummary?.pastPriceList || [];
|
||||
const forecastTargets = {
|
||||
low: lowPriceTarget,
|
||||
avg: avgPriceTarget,
|
||||
@ -472,28 +528,52 @@
|
||||
{removeCompanyStrings($displayCompanyName)} Forecast
|
||||
</h1>
|
||||
|
||||
<div class="inline-flex justify-center w-full rounded-md sm:w-auto">
|
||||
<div
|
||||
class="mb-2 sm:mb-0 mt-2 sm:mt-0 inline-flex w-full rounded-md shadow-sm shadow-[#1E222D] sm:w-auto ml-auto text-sm border border-gray-800"
|
||||
class="bg-secondary w-full sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4"
|
||||
>
|
||||
{#each tabs as item, i}
|
||||
{#if data?.user?.tier !== "Pro" && i > 0}
|
||||
<button
|
||||
class="w-full text-sm rounded-none rounded-l-md px-2 bp:px-3 sm:w-auto sm:px-4 py-1.5 bg-secondary text-white"
|
||||
>All Analysts</button
|
||||
on:click={() => goto("/pricing")}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1"
|
||||
>
|
||||
<button
|
||||
class="text-sm w-full rounded-none rounded-r-md px-2 bp:px-3 sm:w-auto sm:px-4 py-1.5 bg-table sm:hover:bg-secondary transition duration-50 ease-out"
|
||||
>Top Analysts
|
||||
<span class="relative text-sm block font-semibold">
|
||||
{item.title}
|
||||
<svg
|
||||
class="w-4 h-4 ml-1 text-icon-faded inline-block"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
style="max-width:40px"
|
||||
class="inline-block ml-0.5 -mt-1 w-3.5 h-3.5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill-rule="evenodd"
|
||||
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
|
||||
clip-rule="evenodd"
|
||||
></path></svg
|
||||
></button
|
||||
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
|
||||
>
|
||||
</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => changeTab(i)}
|
||||
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
|
||||
i
|
||||
? 'z-0'
|
||||
: ''} "
|
||||
>
|
||||
{#if activeIdx === i}
|
||||
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
>
|
||||
{item.title}
|
||||
</span>
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -714,7 +794,7 @@
|
||||
<td
|
||||
class="px-1 py-[3px] text-sm sm:text-[1rem] text-right"
|
||||
>
|
||||
{getTotalForDate(i)}
|
||||
{getTotalForDate(i, recommendationList)}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
@ -134,7 +134,7 @@
|
||||
}
|
||||
|
||||
function getPriceForecastChart() {
|
||||
const historicalData = data?.getAnalystRating?.pastPriceList || [];
|
||||
const historicalData = data?.getAnalystSummary?.pastPriceList || [];
|
||||
const forecastTargets = {
|
||||
low: lowPriceTarget,
|
||||
avg: avgPriceTarget,
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
export let data;
|
||||
|
||||
let analystRating = data?.getAnalystRating ?? {};
|
||||
let analystRating = data?.getAnalystSummary ?? {};
|
||||
|
||||
let rawData = data?.getAnalystTickerHistory ?? [];
|
||||
let historyList = [];
|
||||
@ -126,8 +126,8 @@
|
||||
};
|
||||
|
||||
const totalRatingScore = recentData
|
||||
.map((item) => ratingScores[item.rating_current] || 0)
|
||||
.reduce((sum, score) => sum + score, 0);
|
||||
?.map((item) => ratingScores[item.rating_current] || 0)
|
||||
?.reduce((sum, score) => sum + score, 0);
|
||||
|
||||
const averageRatingScore = filteredAnalystCount
|
||||
? totalRatingScore / filteredAnalystCount
|
||||
@ -262,7 +262,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -659,7 +659,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
@ -398,7 +398,7 @@
|
||||
></div>
|
||||
{/if}
|
||||
<span
|
||||
class="relative text-sm block font-semibold {activeIdx ===
|
||||
class="relative text-sm block font-semibold whitespace-nowrap {activeIdx ===
|
||||
i
|
||||
? 'text-black'
|
||||
: 'text-white'}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user