update list

This commit is contained in:
MuslemRahimi 2024-08-12 13:05:24 +02:00
parent a622c84616
commit 72855c6d88
15 changed files with 977 additions and 1119 deletions

View File

@ -2,26 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte'; import { onMount } from 'svelte';
export let data; export let data;
let rawData = data?.getAmexStocks; let rawData = data?.getAmexStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -38,11 +42,11 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
A list of all the stocks that are currently listed on the AMEX (American Stock Exchange) stock exchange in the United States. A list of all the stocks that are currently listed on the AMEX (American Stock Exchange) stock exchange in the United States.
</div> </div>
@ -75,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -84,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -137,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -160,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,36 +1,38 @@
<script lang='ts'> <script lang='ts'>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte'; import { onMount } from 'svelte';
export let data; export let data;
let rawData = data?.getDividendAristocrats; let rawData = data?.getDividendAristocrats;
let displayList = rawData?.slice(0,50); let displayList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (displayList?.length === rawData?.length) { if (isBottom && displayList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = displayList?.length; const nextIndex = displayList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
displayList = [...displayList, ...newElements]; displayList = [...displayList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
$: charNumber = $screenWidth < 640 ? 15 : 40; $: charNumber = $screenWidth < 640 ? 15 : 40;
</script> </script>
<section class="w-full max-w-4xl overflow-hidden m-auto"> <section class="w-full overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#27272A] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full sm:flex sm:flex-row sm:items-center m-auto text-gray-100 border border-gray-800 sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
Dividend Aristocrats are companies in the S&P500 index that have been raising their dividends every year for 25 or more years. This is a list of all the dividend aristocrats. Dividend Aristocrats are companies in the S&P500 index that have been raising their dividends every year for 25 or more years. This is a list of all the dividend aristocrats.
@ -38,7 +40,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -121,8 +123,6 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>

View File

@ -1,36 +1,38 @@
<script lang='ts'> <script lang='ts'>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte'; import { onMount } from 'svelte';
export let data; export let data;
let rawData = data?.getDividendKings; let rawData = data?.getDividendKings;
let displayList = rawData?.slice(0,50); let displayList = rawData?.slice(0,50);
async function handleScroll() {
async function infiniteHandler({ detail: { loaded, complete } }) const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
{ const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (isBottom && displayList?.length !== rawData?.length) {
if (displayList?.length === rawData?.length) {
complete();
}
else {
const nextIndex = displayList?.length; const nextIndex = displayList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
displayList = [...displayList, ...newElements]; displayList = [...displayList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
$: charNumber = $screenWidth < 640 ? 15 : 40; $: charNumber = $screenWidth < 640 ? 15 : 40;
</script> </script>
<section class="w-full max-w-4xl overflow-hidden m-auto"> <section class="w-full overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#27272A] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full sm:flex sm:flex-row sm:items-center m-auto text-gray-100 border border-gray-800 sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
Dividend Kings are companies that have been raising their dividend payments every year for 50 or more years. This is a list of all the dividend kings on the US stock market. Dividend Kings are companies that have been raising their dividend payments every year for 50 or more years. This is a list of all the dividend kings on the US stock market.
@ -38,7 +40,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -121,8 +123,6 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>

View File

@ -2,27 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import { onMount } from 'svelte';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte';
export let data; export let data;
let rawData = data?.getDowJonesConstituentStocks; let rawData = data?.getDowJonesConstituentStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -39,14 +42,13 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
A list of the {rawData?.length} stocks in the Dow Jones Industrial Average stock index, which is an index of 30 major companies listed on stock exchanges in the U.S. A list of the 30 stocks in the Dow Jones Industrial Average stock index, which is an index of 30 major companies listed on stock exchanges in the U.S.
</div> </div>
@ -77,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -86,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-center sm:text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -139,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -162,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,23 +1,8 @@
import { userRegion, getCache, setCache } from '$lib/store'; import { getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL; export const load = async ({parent}) => {
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => {
const getDowJonesConstituentStocks = async () => { const getDowJonesConstituentStocks = async () => {
let output; let output;
@ -27,6 +12,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const {apiKey, apiURL} = await parent();
const postData = {'filterList': 'dowjonesConstituent'} const postData = {'filterList': 'dowjonesConstituent'}
const response = await fetch(apiURL + '/exchange-constituents', { const response = await fetch(apiURL + '/exchange-constituents', {

View File

@ -2,27 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import { onMount } from 'svelte';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte';
export let data; export let data;
let rawData = data?.getNasdaqConstituentsStocks; let rawData = data?.getNasdaqConstituentsStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -39,10 +42,11 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
A list of the NASDAQ 100, an index comprising the top 100 non-financial firms on the Nasdaq exchange in the U.S. A list of the NASDAQ 100, an index comprising the top 100 non-financial firms on the Nasdaq exchange in the U.S.
</div> </div>
@ -75,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -84,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-center sm:text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -137,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -160,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,23 +1,7 @@
import { userRegion, getCache, setCache } from '$lib/store'; import { getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1']; export const load = async ({parent}) => {
let apiURL;
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => {
const getNasdaqConstituentsStocks = async () => { const getNasdaqConstituentsStocks = async () => {
let output; let output;
@ -27,6 +11,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const {apiURL, apiKey} = await parent();
const postData = {'filterList': 'nasdaqConstituent'} const postData = {'filterList': 'nasdaqConstituent'}
const response = await fetch(apiURL + '/exchange-constituents', { const response = await fetch(apiURL + '/exchange-constituents', {

View File

@ -2,25 +2,29 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte'; import { onMount } from 'svelte';
export let data; export let data;
let rawData = data?.getNasdaqStocks; let rawData = data?.getNasdaqStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
@ -38,12 +42,11 @@ $: {
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
A list of all the stocks that are currently listed on the NASDAQ stock exchange in the United States. A list of all the stocks that are currently listed on the NASDAQ stock exchange in the United States.
</div> </div>
@ -76,7 +79,7 @@ $: {
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -85,52 +88,46 @@ $: {
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -138,10 +135,10 @@ $: {
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -161,14 +158,8 @@ $: {
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,24 +1,9 @@
import { userRegion, getCache, setCache } from '$lib/store'; import { getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL;
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => {
export const load = async ({parent}) => {
const getNasdaqStocks = async () => { const getNasdaqStocks = async () => {
let output; let output;
@ -28,6 +13,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const { apiKey, apiURL } = await parent();
const postData = {'filterList': 'nasdaq'} const postData = {'filterList': 'nasdaq'}
const response = await fetch(apiURL + '/filter-stock-list', { const response = await fetch(apiURL + '/filter-stock-list', {

View File

@ -2,27 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import { onMount } from 'svelte';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte';
export let data; export let data;
let rawData = data?.getNyseStocks; let rawData = data?.getNyseStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -39,12 +42,11 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
All of the stocks listed on the NYSE (New York Stock Exchange) in the US. All of the stocks listed on the NYSE (New York Stock Exchange) in the US.
</div> </div>
@ -77,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -86,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -139,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -162,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,24 +1,9 @@
import { userRegion, getCache, setCache } from '$lib/store'; import { getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL;
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => {
export const load = async ({parent}) => {
const getNyseStocks = async () => { const getNyseStocks = async () => {
let output; let output;
@ -28,6 +13,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const { apiURL, apiKey} = await parent();
const postData = {'filterList': 'nyse'} const postData = {'filterList': 'nyse'}
const response = await fetch(apiURL + '/filter-stock-list', { const response = await fetch(apiURL + '/filter-stock-list', {

View File

@ -2,27 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import { onMount } from 'svelte';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte';
export let data; export let data;
let rawData = data?.getSPConstituentsStocks; let rawData = data?.getSPConstituentsStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -39,12 +42,11 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
A list of all the stocks in the S&P 500 stock index, which is an index of the top 500 biggest companies listed on stock exchanges in the United States. A list of all the stocks in the S&P 500 stock index, which is an index of the top 500 biggest companies listed on stock exchanges in the United States.
</div> </div>
@ -77,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -86,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-center sm:text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -139,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -162,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,23 +1,10 @@
import { userRegion, getCache, setCache } from '$lib/store'; import { getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL;
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) { export const load = async ({parent}) => {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => {
const getSPConstituentsStocks = async () => { const getSPConstituentsStocks = async () => {
let output; let output;
@ -27,6 +14,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const {apiURL, apiKey} = await parent();
const postData = {'filterList': 'sp500Constituent'} const postData = {'filterList': 'sp500Constituent'}
const response = await fetch(apiURL + '/exchange-constituents', { const response = await fetch(apiURL + '/exchange-constituents', {

View File

@ -2,26 +2,30 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { screenWidth } from '$lib/store'; import { screenWidth } from '$lib/store';
import { abbreviateNumber} from '$lib/utils'; import { abbreviateNumber} from '$lib/utils';
import InfiniteLoading from '$lib/components/InfiniteLoading.svelte'; import { onMount } from 'svelte';
export let data; export let data;
let rawData = data?.getXetraStocks; let rawData = data?.getXetraStocks;
let marketCapList = rawData?.slice(0,50); let marketCapList = rawData?.slice(0,50);
async function infiniteHandler({ detail: { loaded, complete } }) async function handleScroll() {
{ const scrollThreshold = document.body.offsetHeight * 0.8; // 80% of the website height
const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
if (marketCapList?.length === rawData?.length) { if (isBottom && marketCapList?.length !== rawData?.length) {
complete();
}
else {
const nextIndex = marketCapList?.length; const nextIndex = marketCapList?.length;
const newElements= rawData?.slice(nextIndex, nextIndex + 5); const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
marketCapList = [...marketCapList, ...newElements]; marketCapList = [...marketCapList, ...filteredNewResults];
loaded();
} }
} }
onMount(async () => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0); let totalMarketCap = rawData?.reduce((total, stock) => total + stock?.marketCap, 0);
let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0); let totalRevenue = rawData?.reduce((total, stock) => total + stock?.revenue, 0);
let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0; let totalProfits = rawData?.reduce((total, stock) => total + stock?.netIncome, 0) ?? 0;
@ -38,12 +42,11 @@
} }
} }
</script> </script>
<section class="w-full overflow-hidden m-auto">
<section class="w-full max-w-4xl overflow-hidden m-auto">
<div class="w-full max-w-4xl sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4"> <div class="w-full border border-gray-800 sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
<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> <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>
All of the stocks listed on the XETRA (German Electronic Exchange) in Europe. All of the stocks listed on the XETRA (German Electronic Exchange) in Europe.
</div> </div>
@ -76,7 +79,7 @@
<!-- Page wrapper --> <!-- Page wrapper -->
<div class="flex justify-center w-full max-w-5xl m-auto h-full overflow-hidden"> <div class="flex justify-center w-full m-auto h-full overflow-hidden">
@ -85,52 +88,46 @@
<table class="table table-sm sm:table-md table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 "> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4 ">
<thead> <thead>
<tr class="border border-slate-800"> <tr class="border border-slate-800">
<th class="text-slate-200 hidden sm:table-cell sm:font-bold text-[0.95rem]">Symbol</th> <th class="text-white font-semibold text-[1rem]">Symbol</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem]">Company</th> <th class="text-white font-semibold text-[1rem]">Company</th>
<th class="text-slate-200 sm:font-bold text-end text-[0.95rem]">Market Cap</th> <th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Revenue</th> <th class="text-white font-semibold text-center text-[1rem]">Revenue</th>
<th class="text-slate-200 sm:font-bold hidden sm:table-cell text-center text-[0.95rem]">Profits</th> <th class="text-white font-semibold text-center text-[1rem]">Profits</th>
<th class="text-slate-200 sm:font-bold text-[0.95rem] text-end">Price</th> <th class="text-white font-semibold text-[1rem] text-end">Price</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each marketCapList as item,index} {#each marketCapList as item}
<!-- row --> <!-- row -->
<tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"> <tr on:click={() => goto("/stocks/"+item?.symbol)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer">
<td class="hidden sm:table-cell text-blue-400 font-medium border-b-[#09090B]"> <td class="text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
{item?.symbol} {item?.symbol}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<span class="hidden sm:inline-block text-white font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span> {item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}
<div class="sm:hidden flex flex-row">
<div class="flex flex-col">
<span class="text-blue-400 font-medium">{item?.symbol}</span>
<span class="text-gray-200 font-medium">{item?.name?.length > charNumber ? item?.name?.slice(0,charNumber) + "..." : item?.name}</span>
</div>
</div>
</td> </td>
<td class="text-white font-medium text-end border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]">
{abbreviateNumber(item?.marketCap,true)} {abbreviateNumber(item?.marketCap,true)}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'} {item?.revenue !== null ? abbreviateNumber(item?.revenue,true) : '-'}
</td> </td>
<td class="text-white font-medium text-center hidden sm:table-cell border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-center border-b-[#09090B]">
{item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'} {item?.netIncome !== null ? abbreviateNumber(item?.netIncome,true) : '-'}
</td> </td>
<td class="text-gray-200 border-b-[#09090B]"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
<div class="flex flex-row justify-end items-center"> <div class="flex flex-row justify-end items-center">
<div class="flex flex-col"> <div class="flex flex-col">
@ -138,10 +135,10 @@
<div class="flex flex-row mt-0.5 ml-auto"> <div class="flex flex-row mt-0.5 ml-auto">
{#if item.changesPercentage >=0} {#if item.changesPercentage >=0}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#10db06" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#10DB06] text-xs font-medium">+{item.changesPercentage?.toFixed(2)}%</span> <span class="text-[#10DB06]">+{item.changesPercentage?.toFixed(2)}%</span>
{:else} {:else}
<svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg> <svg class="w-5 h-5 -mr-0.5 -mt-0.5 rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g id="evaArrowUpFill0"><g id="evaArrowUpFill1"><path id="evaArrowUpFill2" fill="#FF2F1F" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1Z"/></g></g></svg>
<span class="text-[#FF2F1F] text-xs font-medium">{item.changesPercentage?.toFixed(2)}% </span> <span class="text-[#FF2F1F]">{item.changesPercentage?.toFixed(2)}% </span>
{/if} {/if}
</div> </div>
</div> </div>
@ -161,14 +158,8 @@
</table> </table>
<InfiniteLoading on:infinite={infiniteHandler} />
</div> </div>
</section> </section>

View File

@ -1,24 +1,8 @@
import { userRegion, getCache, setCache } from '$lib/store'; import {getCache, setCache } from '$lib/store';
const usRegion = ['cle1','iad1','pdx1','sfo1'];
let apiURL;
let apiKey = import.meta.env.VITE_STOCKNEAR_API_KEY;
userRegion.subscribe(value => {
if (usRegion.includes(value)) {
apiURL = import.meta.env.VITE_USEAST_API_URL;
} else {
apiURL = import.meta.env.VITE_EU_API_URL;
}
});
export const load = async () => { export const load = async ({parent}) => {
const getXetraStocks = async () => { const getXetraStocks = async () => {
let output; let output;
@ -28,6 +12,8 @@ export const load = async () => {
output = cachedData; output = cachedData;
} else { } else {
const { apiKey, apiURL} = await parent();
const postData = {'filterList': 'xetra'} const postData = {'filterList': 'xetra'}
const response = await fetch(apiURL + '/filter-stock-list', { const response = await fetch(apiURL + '/filter-stock-list', {