add sorting table feature

This commit is contained in:
MuslemRahimi 2024-08-25 23:20:18 +02:00
parent 6d5ecade21
commit ec833cf8b4
2 changed files with 117 additions and 27 deletions

View File

@ -1,7 +1,6 @@
<script lang='ts'> <script lang='ts'>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { numberOfUnreadNotification } from '$lib/store'; import { numberOfUnreadNotification } from '$lib/store';
import InfiniteLoading from '$lib/components/InfiniteLoading.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 { onMount } from 'svelte'; import { onMount } from 'svelte';
@ -36,8 +35,8 @@ window.addEventListener('scroll', handleScroll);
let order = 'highToLow'; let order = '';
let sortBy = 'change'; // Default sorting by change percentage let sortBy = ''; // Default sorting by change percentage
function changeOrder(state:string) { function changeOrder(state:string) {
if (state === 'highToLow') if (state === 'highToLow')

View File

@ -1,40 +1,120 @@
<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 InfiniteLoading from '$lib/components/InfiniteLoading.svelte';
import { abbreviateNumber } from '$lib/utils'; import { abbreviateNumber } from '$lib/utils';
import UpgradeToPro from '$lib/components/UpgradeToPro.svelte'; import UpgradeToPro from '$lib/components/UpgradeToPro.svelte';
import { onMount } from 'svelte';
import ArrowLogo from "lucide-svelte/icons/move-up-right"; import ArrowLogo from "lucide-svelte/icons/move-up-right";
export let data; export let data;
let isLoaded = false;
let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL; let cloudFrontUrl = import.meta.env.VITE_IMAGE_URL;
let rawData = data?.getTopAnalystStocks; let rawData = data?.getTopAnalystStocks;
let analytRatingList = rawData?.slice(0,20) ?? []; let analytRatingList = 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
if (analytRatingList?.length === rawData?.length) { const isBottom = window.innerHeight + window.scrollY >= scrollThreshold;
complete(); if (isBottom && analytRatingList?.length !== rawData?.length) {
} else { const nextIndex = analytRatingList?.length;
const nextIndex = analytRatingList?.length; const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 50);
const newArticles = rawData?.slice(nextIndex, nextIndex + 5); analytRatingList = [...analytRatingList, ...filteredNewResults];
analytRatingList = [...analytRatingList, ...newArticles];
loaded();
} }
} }
onMount(async () => {
isLoaded = true;
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
})
let order = '';
let sortBy = ''; // Default sorting by change percentage
function changeOrder(state:string) {
if (state === 'highToLow')
{
order = 'lowToHigh';
}
else {
order = 'highToLow';
}
}
const sortByRank = (tickerList) => {
return tickerList?.sort(function(a, b) {
if(order === 'highToLow')
{
return b?.rank - a?.rank;
}
else {
return a?.rank - b?.rank;
}
});
}
const sortByRatingCount = (tickerList) => {
return tickerList?.sort(function(a, b) {
if(order === 'highToLow')
{
return b?.counter - a?.counter;
}
else {
return a?.counter - b?.counter;
}
});
}
const sortByUpside = (tickerList) => {
return tickerList?.sort(function(a, b) {
if(order === 'highToLow')
{
return b?.upside - a?.upside;
}
else {
return a?.upside - b?.upside;
}
});
}
$: {
if(order)
{
if(sortBy === 'rank')
{
analytRatingList = sortByRank(rawData)?.slice(0,50);
}
else if(sortBy === 'ratingCount')
{
analytRatingList = sortByRatingCount(rawData)?.slice(0,50);
}
else if(sortBy === 'upside')
{
analytRatingList = sortByUpside(rawData)?.slice(0,50);
}
}
}
$: charNumber = $screenWidth < 640 ? 15 : 40;
$: charNumber = $screenWidth < 640 ? 15 : 20;
</script> </script>
<svelte:head> <svelte:head>
@ -134,13 +214,14 @@
<div class="w-screen sm:w-full m-auto mt-10"> <div class="w-screen sm:w-full m-auto mt-10">
{#if isLoaded}
<div class="w-screen sm:w-full m-auto rounded-none sm:rounded-lg mb-4 overflow-x-scroll sm:overflow-hidden"> <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"> <table class="table table-sm table-compact rounded-none sm:rounded-md w-full bg-[#09090B] border-bg-[#09090B] m-auto">
<thead> <thead>
<tr class="bg-[#09090B]"> <tr class="bg-[#09090B]">
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold"> <th on:click={() => { sortBy = 'rank'; changeOrder(order); }} class="cursor-pointer text-center bg-[#09090B] text-white text-[1rem] font-semibold">
# Rank
<svg class="w-5 h-5 inline-block {order === 'highToLow' && sortBy === 'rank' ? 'rotate-180' : ''}" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</th> </th>
<th class="text-start bg-[#09090B] text-white text-[1rem] font-semibold"> <th class="text-start bg-[#09090B] text-white text-[1rem] font-semibold">
Symbol Symbol
@ -150,8 +231,9 @@
Name Name
</th> </th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold"> <th on:click={() => { sortBy = 'ratingCount'; changeOrder(order); }} class="cursor-pointer text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Ratings Count Ratings Count
<svg class="w-5 h-5 inline-block {order === 'highToLow' && sortBy === 'ratingCount' ? 'rotate-180' : ''}" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</th> </th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold"> <th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Price Target Price Target
@ -159,8 +241,9 @@
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold"> <th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Current Price Current Price
</th> </th>
<th class="text-end bg-[#09090B] text-white text-[1rem] font-semibold"> <th on:click={() => { sortBy = 'upside'; changeOrder(order); }} class="cursor-pointer text-end bg-[#09090B] text-white text-[1rem] font-semibold">
Upside Upside
<svg class="w-5 h-5 inline-block {order === 'highToLow' && sortBy === 'upside' ? 'rotate-180' : ''}" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</th> </th>
<th class="sm:hidden text-white font-semibold text-end text-[1rem]"> <th class="sm:hidden text-white font-semibold text-end text-[1rem]">
Market Cap Market Cap
@ -171,7 +254,7 @@
{#each analytRatingList as item, index} {#each analytRatingList as item, index}
<tr on:click={() => goto(`/stocks/${item?.ticker}`)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index+1 === rawData?.length && data?.user?.tier !== 'Pro' ? 'opacity-[0.1]' : ''} cursor-pointer"> <tr on:click={() => goto(`/stocks/${item?.ticker}`)} class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] {index+1 === rawData?.length && data?.user?.tier !== 'Pro' ? 'opacity-[0.1]' : ''} cursor-pointer">
<td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white text-end"> <td class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-white text-center">
{item?.rank} {item?.rank}
</td> </td>
@ -212,10 +295,18 @@
{/each} {/each}
</tbody> </tbody>
</table> </table>
</div> </div>
<InfiniteLoading on:infinite={infiniteHandler} />
<UpgradeToPro data={data} title="Get stock forecasts from Wall Street's highest rated professionals"/> <UpgradeToPro data={data} title="Get stock forecasts from Wall Street's highest rated professionals"/>
{: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}
</div> </div>