update sentiment tracker page

This commit is contained in:
MuslemRahimi 2024-10-18 09:01:40 +02:00
parent 278b87b974
commit 4f5e366373
7 changed files with 735 additions and 544 deletions

View File

@ -0,0 +1,7 @@
import Root from "./label.svelte";
export {
Root,
//
Root as Label,
};

View File

@ -0,0 +1,21 @@
<script lang="ts">
import { Label as LabelPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = LabelPrimitive.Props;
type $$Events = LabelPrimitive.Events;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<LabelPrimitive.Root
class={cn(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
className
)}
{...$$restProps}
on:mousedown
>
<slot />
</LabelPrimitive.Root>

View File

@ -0,0 +1,7 @@
import Root from "./switch.svelte";
export {
Root,
//
Root as Switch,
};

View File

@ -0,0 +1,28 @@
<script lang="ts">
import { Switch as SwitchPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = SwitchPrimitive.Props;
type $$Events = SwitchPrimitive.Events;
let className: $$Props["class"] = undefined;
export let checked: $$Props["checked"] = undefined;
export { className as class };
</script>
<SwitchPrimitive.Root
bind:checked
class={cn(
"focus-visible:ring-ring border border-gray-500 focus-visible:ring-offset-background data-[state=checked]:bg-purple-500 data-[state=unchecked]:bg-[#1D232A] peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...$$restProps}
on:click
on:keydown
>
<SwitchPrimitive.Thumb
class={cn(
"bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitive.Root>

View File

@ -1,51 +1,52 @@
<script lang='ts'> <script lang="ts">
import { goto } from '$app/navigation'; import { goto } from "$app/navigation";
import { numberOfUnreadNotification, screenWidth } from '$lib/store'; import { numberOfUnreadNotification, screenWidth } from "$lib/store";
import { abbreviateNumber } from '$lib/utils'; import { abbreviateNumber } from "$lib/utils";
import { onMount } from 'svelte'; import { onMount } from "svelte";
import UpgradeToPro from '$lib/components/UpgradeToPro.svelte'; import UpgradeToPro from "$lib/components/UpgradeToPro.svelte";
import ArrowLogo from "lucide-svelte/icons/move-up-right"; import ArrowLogo from "lucide-svelte/icons/move-up-right";
import TableHeader from "$lib/components/Table/TableHeader.svelte"; import TableHeader from "$lib/components/Table/TableHeader.svelte";
export let data;
let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL;
export let data; let isLoaded = false;
let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL; let rawData = [];
let stockList = [];
let isLoaded = false; async function handleScroll() {
let rawData = []
let stockList = [];
async function handleScroll() {
const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold; const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (isBottom && stockList?.length !== rawData?.length) { if (isBottom && stockList?.length !== rawData?.length) {
const nextIndex = stockList?.length; const nextIndex = stockList?.length;
const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 25); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 25);
stockList = [...stockList, ...filteredNewResults]; stockList = [...stockList, ...filteredNewResults];
} }
} }
onMount(() => { onMount(() => {
rawData = data?.getMostShortedStocks ?? []; rawData = data?.getMostShortedStocks ?? [];
stockList = rawData?.slice(0,50) ?? [] stockList = rawData?.slice(0, 50) ?? [];
isLoaded = true; isLoaded = true;
window.addEventListener('scroll', handleScroll); window.addEventListener("scroll", handleScroll);
return () => { return () => {
window.removeEventListener('scroll', handleScroll); window.removeEventListener("scroll", handleScroll);
}; };
}) });
let columns = [ let columns = [
{key: "rank", label: "#", align: "right"}, { key: "rank", label: "#", align: "right" },
{ key: "symbol", label: "Symbol", align: "left" }, { key: "symbol", label: "Symbol", align: "left" },
{ key: "name", label: "Name", align: "left" }, { key: "name", label: "Name", align: "left" },
{ key: "shortRatio", label: "Short Ratio", align: "right" }, { key: "shortRatio", label: "Short Ratio", align: "right" },
{ key: "sharesShort", label: "Short Interest", align: "right" }, { key: "sharesShort", label: "Short Interest", align: "right" },
{ key: "shortFloatPercent", label: "Short % Float", align: "right" }, { key: "shortFloatPercent", label: "Short % Float", align: "right" },
{ key: "shortOutStandingPercent", label: "Short % of Shares Out", align: "right" }, {
key: "shortOutStandingPercent",
label: "Short % of Shares Out",
align: "right",
},
]; ];
let sortOrders = { let sortOrders = {
@ -58,8 +59,7 @@ async function handleScroll() {
shortOutStandingPercent: { order: "none", type: "number" }, shortOutStandingPercent: { order: "none", type: "number" },
}; };
const sortData = (key) => {
const sortData = (key) => {
// Reset all other keys to 'none' except the current key // Reset all other keys to 'none' except the current key
for (const k in sortOrders) { for (const k in sortOrders) {
if (k !== key) { if (k !== key) {
@ -118,219 +118,272 @@ async function handleScroll() {
}; };
$: charNumber = $screenWidth < 640 ? 15 : 20; $: charNumber = $screenWidth < 640 ? 15 : 20;
</script>
<svelte:head>
</script>
<svelte:head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title> <title>
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} High Short Interest Stocks · stocknear {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""} High
Short Interest Stocks · stocknear
</title> </title>
<meta name="description" content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`} /> <meta
name="description"
content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`}
/>
<!-- Other meta tags --> <!-- Other meta tags -->
<meta property="og:title" content={`High Short Interest Stocks · stocknear`}/> <meta
<meta property="og:description" content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`} /> property="og:title"
<meta property="og:type" content="website"/> content={`High Short Interest Stocks · stocknear`}
/>
<meta
property="og:description"
content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`}
/>
<meta property="og:type" content="website" />
<!-- Add more Open Graph meta tags as needed --> <!-- Add more Open Graph meta tags as needed -->
<!-- Twitter specific meta tags --> <!-- Twitter specific meta tags -->
<meta name="twitter:card" content="summary_large_image"/> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`High Short Interest Stocks · stocknear`}/> <meta
<meta name="twitter:description" content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`} /> name="twitter:title"
content={`High Short Interest Stocks · stocknear`}
/>
<meta
name="twitter:description"
content={`Short interest, stock short squeeze, short interest ratio & short selling data positions for NASDAQ, NYSE & AMEX stocks to find shorts in the stock market.`}
/>
<!-- Add more Twitter meta tags as needed --> <!-- Add more Twitter meta tags as needed -->
</svelte:head>
</svelte:head> <section
class="w-full max-w-3xl sm:max-w-screen-2xl overflow-hidden min-h-screen pt-5 pb-40 lg:px-3"
>
<div class="text-sm sm:text-[1rem] breadcrumbs ml-4">
<section class="w-full max-w-3xl sm:max-w-screen-2xl overflow-hidden min-h-screen pt-5 pb-40 lg:px-3"> <ul>
<li><a href="/" class="text-gray-300">Home</a></li>
<div class="text-sm sm:text-[1rem] breadcrumbs ml-4"> <li class="text-gray-300">Top Shorted Stocks</li>
<ul> </ul>
<li><a href="/" class="text-gray-300">Home</a></li> </div>
<li class="text-gray-300">Top Shorted Stocks</li>
</ul>
</div>
<div class="w-full overflow-hidden m-auto mt-5">
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden ">
<div class="relative flex justify-center items-start overflow-hidden w-full">
<main class="w-full lg:w-3/4 lg:pr-5">
<div class="w-full m-auto sm:bg-[#27272A] sm:rounded-xl h-auto pl-10 pr-10 pt-5 sm:pb-10 sm:pt-10 mt-3 mb-8">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-10">
<!-- Start Column -->
<div>
<div class="flex flex-row justify-center items-center">
<h1 class="text-3xl sm:text-4xl text-white text-center font-bold mb-5">
Shorted Stocks
</h1>
</div>
<span class="text-white text-md font-medium text-center flex justify-center items-center ">
High short interest stocks are often volatile, known for sudden price surges called short squeezes.
</span>
</div>
<!-- End Column -->
<!-- Start Column -->
<div class="hidden sm:block relative m-auto mb-5 mt-5 sm:mb-0 sm:mt-0">
<svg class="w-40 -my-5" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="5" result="glow"/>
<feMerge>
<feMergeNode in="glow"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path fill="#1E40AF" d="M57.6,-58.7C72.7,-42.6,81.5,-21.3,82,0.5C82.5,22.3,74.7,44.6,59.7,60.1C44.6,75.6,22.3,84.3,0,84.3C-22.3,84.2,-44.6,75.5,-61.1,60.1C-77.6,44.6,-88.3,22.3,-87.6,0.7C-86.9,-20.8,-74.7,-41.6,-58.2,-57.7C-41.6,-73.8,-20.8,-85.2,0.2,-85.4C21.3,-85.6,42.6,-74.7,57.6,-58.7Z" transform="translate(100 100)" filter="url(#glow)" />
</svg>
<div class="z-1 absolute -top-3">
<img class="w-28 ml-6" src={cloudFrontUrl+'/assets/short_logo.png'} alt="logo" loading="lazy">
</div>
</div>
<!-- End Column -->
</div>
<div class="w-full overflow-hidden m-auto mt-5">
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden">
<div
class="relative flex justify-center items-start overflow-hidden w-full"
>
<main class="w-full lg:w-3/4 lg:pr-5">
<div
class="w-full m-auto sm:bg-[#27272A] sm:rounded-xl h-auto pl-10 pr-10 pt-5 sm:pb-10 sm:pt-10 mt-3 mb-8"
>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-10">
<!-- Start Column -->
<div>
<div class="flex flex-row justify-center items-center">
<h1
class="text-3xl sm:text-4xl text-white text-center font-bold mb-5"
>
Shorted Stocks
</h1>
</div> </div>
{#if isLoaded} <span
<div class="w-screen sm:w-full m-auto mt-20 sm:mt-10"> class="text-white text-md font-medium text-center flex justify-center items-center"
>
High short interest stocks are often volatile, known for
sudden price surges called short squeezes.
</span>
</div>
<!-- End Column -->
<div class="w-screen sm:w-full m-auto rounded-none sm:rounded-lg mb-4 overflow-x-scroll sm:overflow-hidden"> <!-- Start Column -->
<table class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto"> <div
<thead> class="hidden sm:block relative m-auto mb-5 mt-5 sm:mb-0 sm:mt-0"
<TableHeader {columns} {sortOrders} {sortData} /> >
</thead> <svg
<tbody> class="w-40 -my-5"
{#each stockList as item, index} viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg"
<tr on:click={() => goto(`/stocks/${item?.symbol}`)} class="border-b border-[#27272A] sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index+1 === stockList?.length && data?.user?.tier !== 'Pro' ? 'opacity-[0.1]' : ''}"> >
<td class="text-white text-sm sm:text-[1rem] font-medium text-white text-end"> <defs>
{item?.rank} <filter id="glow">
</td> <feGaussianBlur stdDeviation="5" result="glow" />
<feMerge>
<td class="text-sm sm:text-[1rem] whitespace-nowrap text-start"> <feMergeNode in="glow" />
<a href={"/stocks/"+item?.symbol} class="sm:hover:text-white text-blue-400"> <feMergeNode in="SourceGraphic" />
{item?.symbol} </feMerge>
</a> </filter>
</defs>
</td> <path
fill="#1E40AF"
<td class="text-white text-sm sm:text-[1rem] whitespace-nowrap text-white text-start"> d="M57.6,-58.7C72.7,-42.6,81.5,-21.3,82,0.5C82.5,22.3,74.7,44.6,59.7,60.1C44.6,75.6,22.3,84.3,0,84.3C-22.3,84.2,-44.6,75.5,-61.1,60.1C-77.6,44.6,-88.3,22.3,-87.6,0.7C-86.9,-20.8,-74.7,-41.6,-58.2,-57.7C-41.6,-73.8,-20.8,-85.2,0.2,-85.4C21.3,-85.6,42.6,-74.7,57.6,-58.7Z"
{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name} transform="translate(100 100)"
</td> filter="url(#glow)"
/>
<td class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"> </svg>
{item?.shortRatio}
</td>
<td class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white">
{abbreviateNumber(item?.sharesShort)}
</td>
<td class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white">
{item?.shortFloatPercent}%
</td>
<td class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white">
{item?.shortOutStandingPercent}%
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<UpgradeToPro data={data} title="Get the most shorted stocks on the market to never miss out the next short squeeze"/>
<div class="z-1 absolute -top-3">
<img
class="w-28 ml-6"
src={cloudFrontUrl + "/assets/short_logo.png"}
alt="logo"
loading="lazy"
/>
</div> </div>
</div>
<!-- End Column -->
</div>
</div>
{:else} {#if isLoaded}
<div class="flex justify-center items-center h-80"> <div class="w-screen sm:w-full m-auto mt-20 sm:mt-10">
<div class="relative"> <div
<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"> class="w-screen sm:w-full m-auto rounded-none sm:rounded-lg mb-4 overflow-x-scroll sm:overflow-hidden"
<span class="loading loading-spinner loading-md text-gray-400"></span> >
</label> <table
</div> class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto"
>
<thead>
<TableHeader {columns} {sortOrders} {sortData} />
</thead>
<tbody>
{#each stockList as item, index}
<tr
on:click={() => goto(`/stocks/${item?.symbol}`)}
class="border-b border-[#27272A] sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index +
1 ===
stockList?.length && data?.user?.tier !== 'Pro'
? 'opacity-[0.1]'
: ''}"
>
<td
class="text-white text-sm sm:text-[1rem] font-medium text-white text-end"
>
{item?.rank}
</td>
<td
class="text-sm sm:text-[1rem] whitespace-nowrap text-start"
>
<a
href={"/stocks/" + item?.symbol}
class="sm:hover:text-white text-blue-400"
>
{item?.symbol}
</a>
</td>
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap text-white text-start"
>
{item?.name?.length > charNumber
? item?.name?.slice(0, charNumber) + "..."
: item?.name}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"
>
{item?.shortRatio}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"
>
{abbreviateNumber(item?.sharesShort)}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"
>
{item?.shortFloatPercent}%
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"
>
{item?.shortOutStandingPercent}%
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<UpgradeToPro
{data}
title="Get the most shorted stocks on the market to never miss out the next short squeeze"
/>
</div>
{: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}
</main>
<aside class="hidden lg:block relative fixed w-1/4 ml-4">
{#if data?.user?.tier !== "Pro" || data?.user?.freeTrial}
<div
on:click={() => goto("/pricing")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
>
<div
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
>
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Pro Subscription 🔥
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
</div> </div>
{/if} <span class="text-white p-3 ml-3 mr-3">
Upgrade now for unlimited access to all data and tools
</span>
</div>
</div>
{/if}
<div
on:click={() => goto("/analysts")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
>
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Top Analyst 📊
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
</div>
<span class="text-white p-3 ml-3 mr-3">
Get the latest top Wall Street analyst ratings
</span>
</div>
</div>
</main> <div
<aside class="hidden lg:block relative fixed w-1/4 ml-4"> on:click={() => goto("/analysts/top-stocks")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
{#if data?.user?.tier !== 'Pro' || data?.user?.freeTrial} >
<div on:click={() => goto('/pricing')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"> <div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"> <div class="w-full flex justify-between items-center p-3 mt-3">
<div class="w-full flex justify-between items-center p-3 mt-3"> <h2 class="text-start text-xl font-semibold text-white ml-3">
<h2 class="text-start text-xl font-semibold text-white ml-3"> Top Stocks Picks ⭐
Pro Subscription 🔥 </h2>
</h2> <ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/> </div>
</div> <span class="text-white p-3 ml-3 mr-3">
<span class="text-white p-3 ml-3 mr-3"> Get the latest top Wall Street analyst ratings.
Upgrade now for unlimited access to all data and tools </span>
</span> </div>
</div> </div>
</div> </aside>
{/if}
<div on:click={() => goto('/analysts')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer">
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Top Analyst 📊
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/>
</div>
<span class="text-white p-3 ml-3 mr-3">
Get the latest top Wall Street analyst ratings
</span>
</div>
</div>
<div on:click={() => goto('/analysts/top-stocks')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer">
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Top Stocks Picks ⭐
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/>
</div>
<span class="text-white p-3 ml-3 mr-3">
Get the latest top Wall Street analyst ratings.
</span>
</div>
</div>
</aside>
</div>
</div> </div>
</div> </div>
</div>
</section>
</section>

View File

@ -1005,8 +1005,16 @@ function sortData(key) {
{$isOpen ? 'Paused' : 'Market Closed'} {$isOpen ? 'Paused' : 'Market Closed'}
</span> </span>
<label class="inline-flex cursor-pointer relative focus-none"> <label class="inline-flex items-center cursor-pointer focus-none focus:outline-none">
<input on:click={toggleMode} type="checkbox" class="toggle toggle-success" checked={mode} value={mode} disabled={!$isOpen ? true : false} /> <input
on:click={toggleMode}
type="checkbox"
checked={mode}
value={mode}
disabled={!$isOpen}
class="sr-only peer"/>
<div class="relative w-11 h-6 bg-gray-600 focus:outline-none peer-focus:outline-none peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#00A96E]"></div>
</label> </label>

View File

@ -1,352 +1,419 @@
<script lang='ts'> <script lang="ts">
import { goto } from '$app/navigation'; import { goto } from "$app/navigation";
import { numberOfUnreadNotification, screenWidth } from '$lib/store'; import { numberOfUnreadNotification, screenWidth } from "$lib/store";
import { abbreviateNumber } from '$lib/utils'; import { abbreviateNumber } from "$lib/utils";
import { onMount } from 'svelte'; import { onMount } from "svelte";
import UpgradeToPro from '$lib/components/UpgradeToPro.svelte'; import UpgradeToPro from "$lib/components/UpgradeToPro.svelte";
import ArrowLogo from "lucide-svelte/icons/move-up-right"; import ArrowLogo from "lucide-svelte/icons/move-up-right";
import TableHeader from "$lib/components/Table/TableHeader.svelte";
export let data;
let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL;
export let data; let isLoaded = false;
let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL; let rawData = [];
let stockList = [];
let isLoaded = false; async function handleScroll() {
let rawData = []
let stockList = [];
function handleMode(i) {
activeIdx = i;
if(activeIdx === 0) {
rawData = data?.getSentimentTracker?.twitter;
} else if (activeIdx === 1) {
rawData = data?.getSentimentTracker?.stocktwits;
}
stockList = rawData?.slice(0,50)
}
const tabs = [
{
title: "Twitter",
},
{
title: "Stocktwits",
},
];
let activeIdx = 0;
async function handleScroll() {
const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold; const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (isBottom && stockList?.length !== rawData?.length) { if (isBottom && stockList?.length !== rawData?.length) {
const nextIndex = stockList?.length; const nextIndex = stockList?.length;
const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 25); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 25);
stockList = [...stockList, ...filteredNewResults]; stockList = [...stockList, ...filteredNewResults];
} }
} }
onMount(() => { onMount(() => {
rawData = data?.getSentimentTracker?.twitter ?? []; rawData = data?.getSentimentTracker ?? [];
stockList = rawData?.slice(0,50) ?? [] stockList = rawData?.slice(0, 50) ?? [];
isLoaded = true; isLoaded = true;
if (data?.user?.tier === "Pro") {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}
});
if(data?.user?.tier === 'Pro') { let columns = [
window.addEventListener('scroll', handleScroll); { key: "rank", label: "#", align: "right" },
return () => { { key: "symbol", label: "Symbol", align: "left" },
window.removeEventListener('scroll', handleScroll); { key: "name", label: "Name", align: "left" },
}; { key: "marketCap", label: "Market Cap", align: "right" },
{ key: "price", label: "Price", align: "right" },
{ key: "changesPercentage", label: "% Change", align: "right" },
{ key: "sentiment", label: "Sentiment", align: "right" },
];
let sortOrders = {
rank: { order: "none", type: "number" },
symbol: { order: "none", type: "string" },
name: { order: "none", type: "string" },
marketCap: { order: "none", type: "number" },
price: { order: "none", type: "number" },
changesPercentage: { order: "none", type: "number" },
sentiment: { order: "none", type: "number" },
};
const sortData = (key) => {
// Reset all other keys to 'none' except the current key
for (const k in sortOrders) {
if (k !== key) {
sortOrders[k].order = "none";
}
}
// Cycle through 'none', 'asc', 'desc' for the clicked key
const orderCycle = ["none", "asc", "desc"];
let originalData = rawData;
const currentOrderIndex = orderCycle.indexOf(sortOrders[key].order);
sortOrders[key].order =
orderCycle[(currentOrderIndex + 1) % orderCycle.length];
const sortOrder = sortOrders[key].order;
// Reset to original data when 'none' and stop further sorting
if (sortOrder === "none") {
stockList = [...originalData]; // Reset to original data (spread to avoid mutation)
return;
}
// Define a generic comparison function
const compareValues = (a, b) => {
const { type } = sortOrders[key];
let valueA, valueB;
switch (type) {
case "date":
valueA = new Date(a[key]);
valueB = new Date(b[key]);
break;
case "string":
valueA = a[key].toUpperCase();
valueB = b[key].toUpperCase();
return sortOrder === "asc"
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
case "number":
default:
valueA = parseFloat(a[key]);
valueB = parseFloat(b[key]);
break;
} }
}) if (sortOrder === "asc") {
return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
} else {
return valueA > valueB ? -1 : valueA < valueB ? 1 : 0;
}
};
// Sort using the generic comparison function
stockList = [...originalData].sort(compareValues);
};
$: charNumber = $screenWidth < 640 ? 15 : 40; $: charNumber = $screenWidth < 640 ? 15 : 40;
</script>
<svelte:head>
</script>
<svelte:head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title> <title>
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} Sentiment Tracker · stocknear {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""} Sentiment
Tracker · stocknear
</title> </title>
<meta name="description" content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`} /> <meta
name="description"
content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`}
/>
<!-- Other meta tags --> <!-- Other meta tags -->
<meta property="og:title" content={`Sentiment Tracker · stocknear`}/> <meta property="og:title" content={`Sentiment Tracker · stocknear`} />
<meta property="og:description" content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`} /> <meta
<meta property="og:type" content="website"/> property="og:description"
content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`}
/>
<meta property="og:type" content="website" />
<!-- Add more Open Graph meta tags as needed --> <!-- Add more Open Graph meta tags as needed -->
<!-- Twitter specific meta tags --> <!-- Twitter specific meta tags -->
<meta name="twitter:card" content="summary_large_image"/> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`Sentiment Tracker · stocknear`}/> <meta name="twitter:title" content={`Sentiment Tracker · stocknear`} />
<meta name="twitter:description" content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`} /> <meta
name="twitter:description"
content={`Stay ahead of the market with our real-time filtering of the most discussed and bullish stocks on social media. Discover trending stocks and make informed investment decisions today!`}
/>
<!-- Add more Twitter meta tags as needed --> <!-- Add more Twitter meta tags as needed -->
</svelte:head>
</svelte:head> <section
class="w-full max-w-3xl sm:max-w-screen-2xl overflow-hidden min-h-screen pt-5 pb-40"
>
<div class="text-sm sm:text-[1rem] breadcrumbs ml-4">
<section class="w-full max-w-3xl sm:max-w-screen-2xl overflow-hidden min-h-screen pt-5 pb-40"> <ul>
<li><a href="/" class="text-gray-300">Home</a></li>
<div class="text-sm sm:text-[1rem] breadcrumbs ml-4"> <li class="text-gray-300">Sentiment Tracker</li>
<ul> </ul>
<li><a href="/" class="text-gray-300">Home</a></li> </div>
<li class="text-gray-300">Sentiment Tracker</li>
</ul>
</div>
<div class="w-full overflow-hidden m-auto mt-5">
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden ">
<div class="relative flex justify-center items-start overflow-hidden w-full">
<main class="w-full lg:w-3/4 lg:pr-5">
<div class="w-full m-auto sm:bg-[#27272A] sm:rounded-xl h-auto pl-10 pr-10 pt-5 sm:pb-10 sm:pt-10 mt-3 mb-8">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-10">
<!-- Start Column -->
<div>
<div class="flex flex-row justify-center items-center">
<h1 class="text-3xl sm:text-4xl text-white text-center font-bold mb-5">
Sentiment Tracker
</h1>
</div>
<span class="text-white text-md font-medium text-center flex justify-center items-center ">
Find out the top stocks discussed in social media.
</span>
</div>
<!-- End Column -->
<!-- Start Column -->
<div class="hidden sm:block relative m-auto mb-5 mt-5 sm:mb-0 sm:mt-0">
<svg class="w-40 -my-5" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="5" result="glow"/>
<feMerge>
<feMergeNode in="glow"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path fill="#1E40AF" d="M57.6,-58.7C72.7,-42.6,81.5,-21.3,82,0.5C82.5,22.3,74.7,44.6,59.7,60.1C44.6,75.6,22.3,84.3,0,84.3C-22.3,84.2,-44.6,75.5,-61.1,60.1C-77.6,44.6,-88.3,22.3,-87.6,0.7C-86.9,-20.8,-74.7,-41.6,-58.2,-57.7C-41.6,-73.8,-20.8,-85.2,0.2,-85.4C21.3,-85.6,42.6,-74.7,57.6,-58.7Z" transform="translate(100 100)" filter="url(#glow)" />
</svg>
<div class="z-1 absolute -top-3">
<img class="w-36 " src={cloudFrontUrl+'/assets/sentiment_tracker_logo.png'} alt="logo" loading="lazy">
</div>
</div>
<!-- End Column -->
</div>
<div class="w-full overflow-hidden m-auto mt-5">
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden">
<div
class="relative flex justify-center items-start overflow-hidden w-full"
>
<main class="w-full lg:w-3/4 lg:pr-5">
<div
class="w-full m-auto sm:bg-[#27272A] sm:rounded-xl h-auto pl-10 pr-10 pt-5 sm:pb-10 sm:pt-10 mt-3 mb-8"
>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-10">
<!-- Start Column -->
<div>
<div class="flex flex-row justify-center items-center">
<h1
class="text-3xl sm:text-4xl text-white text-center font-bold mb-5"
>
Sentiment Tracker
</h1>
</div> </div>
{#if isLoaded} <span
class="text-white text-md font-medium text-center flex justify-center items-center"
<div class="mb-8 w-full text-center sm:text-start sm:flex sm:flex-row sm:items-center m-auto text-gray-100 border border-gray-800 sm:rounded-lg h-auto p-5 "> >
<svg class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path fill="#a474f6" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"/></svg> Find out the top stocks discussed in social media.
We update our data in realtime to provide you with the latest trends and the most bullish stocks being discussed on Twitter and StockTwits </span>
</div>
<div class="bg-[#313131] w-fit relative m-auto sm:m-0 sm:mr-auto flex sm:flex-wrap items-center justify-center rounded-lg p-1">
{#each tabs as item, i}
<button
on:click={() => handleMode(i)}
class="group relative z-[1] rounded-full px-6 py-1 {activeIdx === i
? 'z-0'
: ''} "
>
{#if activeIdx === i}
<div
class="absolute inset-0 rounded-lg bg-purple-600"
></div>
{/if}
<span class="relative text-[1rem] sm:text-[1rem] block font-semibold duration-200 text-white">
{#if i === 0}
<svg class="inline-block w-4 h-4 -mt-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#fff" d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334q.002-.211-.006-.422A6.7 6.7 0 0 0 16 3.542a6.7 6.7 0 0 1-1.889.518a3.3 3.3 0 0 0 1.447-1.817a6.5 6.5 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.32 9.32 0 0 1-6.767-3.429a3.29 3.29 0 0 0 1.018 4.382A3.3 3.3 0 0 1 .64 6.575v.045a3.29 3.29 0 0 0 2.632 3.218a3.2 3.2 0 0 1-.865.115a3 3 0 0 1-.614-.057a3.28 3.28 0 0 0 3.067 2.277A6.6 6.6 0 0 1 .78 13.58a6 6 0 0 1-.78-.045A9.34 9.34 0 0 0 5.026 15"/></svg>
{:else}
<svg class="inline-block w-6 h-6 -mt-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 3L8 7.5l8 4.5m-8 0l8 4.5L8 21"/></svg>
{/if}
{item.title}
</span>
</button>
{/each}
</div>
<div class="w-screen sm:w-full m-auto mt-20 sm:mt-10">
<div class="w-screen sm:w-full m-auto rounded-none sm:rounded-lg mb-4 overflow-x-scroll sm:overflow-hidden">
<table class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto">
<thead>
<tr class="bg-[#09090B] border-b border-[#27272A]">
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
#
</th>
<th class="text-start bg-[#09090B] text-white text-[1rem] font-semibold">
Symbol
</th>
<th class=" text-start bg-[#09090B] text-white text-[1rem] font-semibold">
Name
</th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Market Cap
</th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Price
</th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
% Change
</th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Sentiment
</th>
</tr>
</thead>
<tbody>
{#each stockList as item, index}
<tr class="sm:hover:bg-[#245073] border-b border-[#27272A] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index+1 === stockList?.length && data?.user?.tier !== 'Pro' ? 'opacity-[0.1]' : ''}">
<td class="text-white text-sm sm:text-[1rem] font-medium text-white text-end">
{item?.rank}
</td>
<td class="text-sm sm:text-[1rem] text-start">
<a href={"/stocks/"+item?.symbol} class="sm:hover:text-white text-blue-400">
{item?.symbol}
</a>
</td>
<td class="whitespace-nowrap text-white text-sm sm:text-[1rem] text-white text-start">
{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
</td>
<td class="text-end text-sm sm:text-[1rem] font-medium text-white whitespace-nowrap">
{abbreviateNumber(item?.marketCap)}
</td>
<td class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white">
{item?.price}
</td>
<td class="text-sm sm:text-[1rem] whitespace-nowrap {item?.changesPercentage >= 0 ? 'text-[#37C97D]' : 'text-[#FF2F1F]'} text-end">
{item?.changesPercentage > 0 ? '+' : ''}{item?.changesPercentage}%
</td>
<td class="text-end text-sm sm:text-[1rem] font-medium whitespace-nowrap {item?.sentiment >= 55 ? 'text-[#37C97D]' : item?.sentiment >= 50 ? 'text-[#E57C34]' : 'text-[#FF2F1F]'}">
<div class="flex flex-row items-center justify-end">
<div class="">{item?.sentiment >= 80 ? 'Very Bullish' : item?.sentiment >= 55 ? 'Bullish' : item?.sentiment > 50 ? 'Mixed' : 'Bearish'}</div>
<div class="ml-2 px-1.5 py-1.5 border text-center rounded-lg text-xs font-semibold">
{item?.sentiment}
</div>
</div>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<UpgradeToPro data={data} title="Get the latest stock trends from social media to never miss out the next hype"/>
</div>
{: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}
</main>
<aside class="hidden lg:block relative fixed w-1/4 ml-4">
{#if data?.user?.tier !== 'Pro' || data?.user?.freeTrial}
<div on:click={() => goto('/pricing')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer">
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Pro Subscription 🔥
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/>
</div>
<span class="text-white p-3 ml-3 mr-3">
Upgrade now for unlimited access to all data and tools.
</span>
</div>
</div> </div>
{/if} <!-- End Column -->
<div on:click={() => goto('/cramer-tracker')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"> <!-- Start Column -->
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"> <div
<div class="w-full flex justify-between items-center p-3 mt-3"> class="hidden sm:block relative m-auto mb-5 mt-5 sm:mb-0 sm:mt-0"
<h2 class="text-start text-xl font-semibold text-white ml-3"> >
Cramer Tracker 📉 <svg
</h2> class="w-40 -my-5"
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/> viewBox="0 0 200 200"
</div> xmlns="http://www.w3.org/2000/svg"
<span class="text-white p-3 ml-3 mr-3"> >
Follow Jim Cramer latest stock picks <defs>
</span> <filter id="glow">
</div> <feGaussianBlur stdDeviation="5" result="glow" />
<feMerge>
<feMergeNode in="glow" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<path
fill="#1E40AF"
d="M57.6,-58.7C72.7,-42.6,81.5,-21.3,82,0.5C82.5,22.3,74.7,44.6,59.7,60.1C44.6,75.6,22.3,84.3,0,84.3C-22.3,84.2,-44.6,75.5,-61.1,60.1C-77.6,44.6,-88.3,22.3,-87.6,0.7C-86.9,-20.8,-74.7,-41.6,-58.2,-57.7C-41.6,-73.8,-20.8,-85.2,0.2,-85.4C21.3,-85.6,42.6,-74.7,57.6,-58.7Z"
transform="translate(100 100)"
filter="url(#glow)"
/>
</svg>
<div class="z-1 absolute -top-3">
<img
class="w-36"
src={cloudFrontUrl + "/assets/sentiment_tracker_logo.png"}
alt="logo"
loading="lazy"
/>
</div>
</div> </div>
<!-- End Column -->
<div on:click={() => goto('/reddit-tracker')} class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"> </div>
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Reddit Tracker 🚀
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0"/>
</div>
<span class="text-white p-3 ml-3 mr-3">
Get the latest trends of r/Wallstreetbets
</span>
</div>
</div>
</aside>
</div> </div>
{#if isLoaded}
<div
class="mb-8 w-full text-center sm:text-start sm:flex sm:flex-row sm:items-center m-auto text-gray-100 border border-gray-800 sm:rounded-lg h-auto p-5"
>
<svg
class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 256 256"
><path
fill="#a474f6"
d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"
/></svg
>
We update our data in realtime to provide you with the latest trends
and the most bullish stocks being discussed on Twitter and StockTwits
</div>
<div class="w-screen sm:w-full m-auto mt-20 sm:mt-10">
<div
class="w-screen sm:w-full m-auto rounded-none sm:rounded-lg mb-4 overflow-x-scroll sm:overflow-hidden"
>
<table
class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto"
>
<thead>
<TableHeader {columns} {sortOrders} {sortData} />
</thead>
<tbody>
{#each stockList as item, index}
<tr
class="sm:hover:bg-[#245073] border-b border-[#27272A] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index +
1 ===
stockList?.length && data?.user?.tier !== 'Pro'
? 'opacity-[0.1]'
: ''}"
>
<td
class="text-white text-sm sm:text-[1rem] font-medium text-white text-end"
>
{item?.rank}
</td>
<td class="text-sm sm:text-[1rem] text-start">
<a
href={"/stocks/" + item?.symbol}
class="sm:hover:text-white text-blue-400"
>
{item?.symbol}
</a>
</td>
<td
class="whitespace-nowrap text-white text-sm sm:text-[1rem] text-white text-start"
>
{item?.name?.length > charNumber
? item?.name?.slice(0, charNumber) + "..."
: item?.name}
</td>
<td
class="text-end text-sm sm:text-[1rem] font-medium text-white whitespace-nowrap"
>
{abbreviateNumber(item?.marketCap)}
</td>
<td
class="text-end text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white"
>
{item?.price}
</td>
<td
class="text-sm sm:text-[1rem] whitespace-nowrap {item?.changesPercentage >=
0
? 'text-[#37C97D]'
: 'text-[#FF2F1F]'} text-end"
>
{item?.changesPercentage > 0
? "+"
: ""}{item?.changesPercentage}%
</td>
<td
class="text-end text-sm sm:text-[1rem] font-medium whitespace-nowrap {item?.sentiment >=
55
? 'text-[#37C97D]'
: item?.sentiment >= 50
? 'text-[#E57C34]'
: 'text-[#FF2F1F]'}"
>
<div class="flex flex-row items-center justify-end">
<div class="">
{item?.sentiment >= 80
? "Very Bullish"
: item?.sentiment >= 55
? "Bullish"
: item?.sentiment > 50
? "Mixed"
: "Bearish"}
</div>
<div
class="ml-2 px-1.5 py-1.5 border text-center rounded-lg text-xs font-semibold"
>
{item?.sentiment}
</div>
</div>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<UpgradeToPro
{data}
title="Get the latest stock trends from social media to never miss out the next hype"
/>
</div>
{: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}
</main>
<aside class="hidden lg:block relative fixed w-1/4 ml-4">
{#if data?.user?.tier !== "Pro" || data?.user?.freeTrial}
<div
on:click={() => goto("/pricing")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
>
<div
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
>
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Pro Subscription 🔥
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
</div>
<span class="text-white p-3 ml-3 mr-3">
Upgrade now for unlimited access to all data and tools.
</span>
</div>
</div>
{/if}
<div
on:click={() => goto("/cramer-tracker")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
>
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Cramer Tracker 📉
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
</div>
<span class="text-white p-3 ml-3 mr-3">
Follow Jim Cramer latest stock picks
</span>
</div>
</div>
<div
on:click={() => goto("/reddit-tracker")}
class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer"
>
<div class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0">
<div class="w-full flex justify-between items-center p-3 mt-3">
<h2 class="text-start text-xl font-semibold text-white ml-3">
Reddit Tracker 🚀
</h2>
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
</div>
<span class="text-white p-3 ml-3 mr-3">
Get the latest trends of r/Wallstreetbets
</span>
</div>
</div>
</aside>
</div> </div>
</div> </div>
</div>
</section>
</section>