frontend/src/lib/components/WatchListCard.svelte
2024-10-10 22:11:14 +02:00

223 lines
6.8 KiB
Svelte

<script lang='ts'>
import { onMount } from 'svelte';
import { switchWatchList, screenWidth } from '$lib/store';
import { formatDate, abbreviateNumber } from '$lib/utils';
export let watchListId;
export let indicatorList;
let isLoaded = false;
let watchList: any[] = [];
let news = [];
async function getWatchlistData()
{
const postData = {'watchListId': watchListId}
const response = await fetch('/api/get-watchlist', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(postData)
});
const output = await response?.json();
watchList = output?.at(0);
news = output[1];
}
onMount( async () => {
await getWatchlistData()
isLoaded = true;
});
$: charNumber = $screenWidth < 640 ? 15 : 20;
$: {
if($switchWatchList && typeof window !== 'undefined')
{
isLoaded = false
getWatchlistData()
isLoaded = true;
$switchWatchList = false;
}
}
</script>
<section class="w-full overflow-hidden m-auto min-h-screen pt-10 mb-40 px-1 sm:px-0">
{#if isLoaded}
<!--Start Tickersinfo Length-->
{#if watchList.length !== 0}
<div class="w-screen sm:w-full">
<div class="w-full overflow-x-scroll">
<table class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto mt-4 ">
<!-- head -->
<thead>
<tr class="border-b-[#09090B]">
<th class="text-white font-semibold text-sm">Symbol</th>
<th class="text-white font-semibold text-sm">Company</th>
{#each indicatorList as item}
<th class="text-white font-semibold text-end text-sm">{item}</th>
{/each}
</tr>
</thead>
<tbody class="p-0">
{#each watchList as item}
<!-- row -->
<tr class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B]">
<td class="text-sm sm:text-[1rem] text-start border-b-[#09090B]">
<a href={`/${item?.type === 'stock' ? 'stocks' : item?.type === 'etf' ? 'etf' : 'crypto'}/${item?.symbol}`} class="text-blue-400 sm:hover:text-white">
{item?.symbol}
</a>
</td>
<td class="text-white text-sm sm:text-[1rem] border-b-[#09090B] whitespace-nowrap">
{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
</td>
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
{item?.eps !== null ? item?.eps?.toFixed(2) : '-'}
</td>
<td class="text-white text-sm sm:text-[1rem] text-end border-b-[#09090B]">
{item?.pe !== null ? item?.pe?.toFixed(2) : '-'}
</td>
<td class="text-white text-sm sm:text-[1rem] whitespace-nowrap text-end border-b-[#09090B]">
{abbreviateNumber(item?.volume)}
</td>
<td class="text-white text-sm sm:text-[1rem] whitespace-nowrap text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)}
</td>
<td class="border-b-[#09090B] text-sm sm:text-[1rem] text-end text-white whitespace-nowrap">
${item.price?.toFixed(2)}
</td>
<td class="border-b-[#09090B] text-end text-sm sm:text-[1rem] whitespace-nowrap">
{#if item?.changesPercentage >=0}
<span class="text-[#37C97D]">+{item?.changesPercentage?.toFixed(2)}%</span>
{:else}
<span class="text-[#FF2F1F]">{item?.changesPercentage?.toFixed(2)}% </span>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="w-full m-auto border-b border-slate-800 mt-16 mb-16"></div>
<h2 class="text-start text-white ml-2 text-xl font-bold text-black mb-3 ">Latest News</h2>
<div class="relative text-gray-800 m-auto">
<div class="flex flex-wrap md:flex-row">
{#each news as item}
<a href={item.url} target="_blank" class="cursor-pointer mb-10 w-full">
<div class="flex-shrink-0 float-left">
<img src={item?.image} class="float-left w-36 sm:w-40 rounded-xl ml-2 mr-4 mb-2" alt="news image" loading="lazy">
<div class="absolute w-36 sm:w-40 ml-2 mr-4 mb-2 h-6 bg-[#0C0F17] bg-opacity-80 flex justify-center items-center">
<p class="text-white italic text-xs">{(new URL(item?.url)).hostname.replace('www.','')}</p>
</div>
</div>
<div class="flex-grow">
<div class="text-sm text-white flex flex-row">
<div class="rounded-full w-6 h-6 relative bg-gray-800 mr-1.5 mb-0.5">
<img class="rounded-full w-4 h-4 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2" src={`https://financialmodelingprep.com/image-stock/${item.symbol}.png`} loading="lazy"/>
</div>
{item?.symbol} &centerdot; {formatDate(item?.publishedDate)} ago
</div>
<h2 class="text-start text-sm sm:text-md font-medium mb-2 flex-shrink text-white">{item.title}</h2>
<p class="text-white text-sm sm:text-md p-2">
{item?.text?.length > 250 ? item?.text?.slice(0,250) + "..." : item?.text}
</p>
</div>
</a>
{/each}
</div>
</div>
</div>
{:else}
<div class="flex flex-col justify-center items-center m-auto pt-5">
<span class="text-white font-bold text-white text-xl sm:text-3xl">
Empty Watchlist
</span>
<span class="text-white text-sm sm:text-lg pt-5 m-auto p-4 text-center">
Fill it up with your favorite stocks and get realtime data and the latest news in one place!
</span>
</div>
{/if}
<!--End Tickersinfo Length-->
{: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"></span>
</label>
</div>
</div>
{/if}
</section>