update screener

This commit is contained in:
MuslemRahimi 2024-09-02 19:01:50 +02:00
parent 2d56d743e0
commit a3f09f25f1
2 changed files with 154 additions and 75 deletions

View File

@ -3,47 +3,48 @@ import type { Button as ButtonPrimitive } from "bits-ui";
import Root from "./button.svelte";
const buttonVariants = tv({
base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
variants: {
variant: {
default: "bg-primary text-primary-foreground sm:hover:bg-[#09090B]",
destructive:
"bg-destructive text-destructive-foreground sm:hover:bg-[#09090B]",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground sm:hover:bg-[#09090B]",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
});
type Variant = VariantProps<typeof buttonVariants>["variant"];
type Size = VariantProps<typeof buttonVariants>["size"];
type Props = ButtonPrimitive.Props & {
variant?: Variant;
size?: Size;
variant?: Variant;
size?: Size;
};
type Events = ButtonPrimitive.Events;
export {
Root,
type Props,
type Events,
//
Root as Button,
type Props as ButtonProps,
type Events as ButtonEvents,
buttonVariants,
};
Root,
type Props,
type Events,
//
Root as Button,
type Props as ButtonProps,
type Events as ButtonEvents,
buttonVariants,
};

View File

@ -4,7 +4,8 @@
import { screenWidth, strategyId, numberOfUnreadNotification, getCache, setCache} from '$lib/store';
import toast from 'svelte-french-toast';
import { abbreviateNumber } from '$lib/utils';
import * as DropdownMenu from "$lib/components/shadcn/dropdown-menu/index.js";
import { Button } from "$lib/components/shadcn/button/index.js";
//const userConfirmation = confirm('Unsaved changes detected. Leaving now will discard your strategy. Continue?');
export let data;
@ -24,6 +25,7 @@
);
const getStockScreenerData = async (rules) => {
const ruleNames = rules?.map(rule => rule?.name)?.sort()?.join(',');
const cachedData = getCache(ruleNames, 'getStockScreenerData');
@ -509,6 +511,9 @@ async function handleRule(newRule) {
}
}
}
async function updateStockScreenerData() {
try {
const newData = await getStockScreenerData(ruleOfList);
@ -519,7 +524,7 @@ async function updateStockScreenerData() {
)
);
displayRules = allRows.filter(row => ruleOfList.some(rule => rule.name === row.rule));
displayRules = allRows?.filter(row => ruleOfList?.some(rule => rule.name === row.rule));
filteredData = filterStockScreenerData();
displayResults = filteredData?.slice(0, 50);
} catch (error) {
@ -529,9 +534,6 @@ async function updateStockScreenerData() {
});
}
}
}
async function handleResetAll() {
ruleOfList = [];
@ -635,14 +637,11 @@ async function handleSave(printToast) {
}
}
async function handleUpdateRule(rule) {
ruleName = rule.name;
}
$: {
if (ruleOfList) {
const ruleToUpdate = ruleOfList.find(rule => rule.name === ruleName);
const ruleToUpdate = ruleOfList?.find(rule => rule.name === ruleName);
if (ruleToUpdate) {
const valueMap = {
payoutRatio: valuePayoutRatio,
@ -714,13 +713,13 @@ $: {
shortOutStandingPercent: valueShortOutStandingPercent,
};
ruleToUpdate.value = valueMap[ruleToUpdate.name] ?? ruleToUpdate.value;
ruleToUpdate.condition = ruleCondition[ruleToUpdate.name];
ruleOfList = [...ruleOfList];
}
displayRules = allRows.filter(row => ruleOfList.some(rule => rule.name === row.rule));
console.log('yes here')
displayRules = allRows?.filter(row => ruleOfList.some(rule => rule.name === row.rule));
filteredData = filterStockScreenerData();
if (ruleOfList?.some(item => item?.name === 'ratingRecommendation')) {
@ -1074,6 +1073,43 @@ function handleChangeValue(value) {
}
async function preSelectStrategy(state:string) {
//To-do: Piece of shit code needs to be optimized better
if(state === 'dividendGrowth') {
ruleOfList = [
{
"condition": "over",
"name": "dividendGrowth",
"value": 5
},
{
"condition": "over",
"name": "dividendYield",
"value": 1
},
{
"condition": "under",
"name": "payoutRatio",
"value": 60
},
{
"condition": "over",
"name": "growthRevenue",
"value": 5
}
];
ruleOfList?.forEach(row => {
ruleName = row?.name
ruleCondition[ruleName] = row?.condition;
handleChangeValue(row?.value);
})
await updateStockScreenerData();
}
}
</script>
@ -1121,13 +1157,49 @@ function handleChangeValue(value) {
<!--Start Build Strategy-->
<div class="mt-5 sm:rounded-lg">
<div class="flex flex-row items-center mb-5">
<div class="flex flex-col sm:flex-row items-start sm:items-center mb-5">
<div class="w-full flex flex-row items-center sm:mt-4">
<h1 class="text-white text-3xl font-semibold">
Stock Screener
</h1>
<span class="text-sm font-semibold text-white ml-2 mt-3">
<span class="inline-block text-xs sm:text-sm font-semibold text-white ml-2 mt-3">
{ruleOfList?.length !== 0 ? filteredData?.length : 0} Matches Found
</span>
</div>
<div class="flex w-[50%] md:block md:w-auto mt-5 sm:ml-auto">
<div class="hidden text-sm sm:text-[1rem] font-semibold sm:font-normal text-white sm:block sm:mb-1">
Popular Screens
</div>
<div class="relative inline-block text-left grow">
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button builders={[builder]} class="border-gray-600 border bg-[#09090B] flex flex-row justify-between items-center px-3 py-2 text-white rounded-lg truncate">
<span class="truncate text-white">Select popular</span>
<svg class="-mr-1 ml-1 h-5 w-5 xs:ml-2 inline-block" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px" aria-hidden="true">
<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>
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content class="w-56">
<DropdownMenu.Label class="text-gray-400">
Popular Strategies
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.Item on:click={() => preSelectStrategy('dividendGrowth')} class="cursor-pointer">
Dividend Growth
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
</div>
</div>
@ -1135,10 +1207,12 @@ function handleChangeValue(value) {
<div class="items-end border-b border-gray-400">
<div class="mr-1 flex items-center justify-between lg:mr-2 mb-1.5">
<button class="flex cursor-pointer items-center text-lg sm:text-xl font-semibold text-gray-200" title="Hide Filter Area">
<svg class="-mb-0.5 h-6 w-6" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px">
<!--
<svg class="-mb-0.5 h-6 w-6" 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>
Filters
-->
{ruleOfList?.length} Filters
</button>
</div>
</div>
@ -1192,49 +1266,53 @@ function handleChangeValue(value) {
</svg>
</button>
<div class="relative inline-block text-left">
<div on:click={() => ruleName = row?.rule} class="dropdown dropdown-end">
<button tabindex="0" class="bg-[#000] h-[33px] flex flex-row justify-between items-center w-[150px] xs:w-[140px] sm:w-[150px] px-3 text-white rounded-lg truncate">
<span class="truncate ml-2">
{#if valueMappings[row?.rule] === 'any'}
Any
{:else}
{conditions[row?.rule]} {valueMappings[row?.rule]}{row?.unit}
{/if}
</span>
<svg class=" ml-1 h-6 w-6 xs:ml-2 inline-block" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px" aria-hidden="true">
<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>
</button>
<div class="dropdown-content absolute z-40 mt-2 rounded-md bg-[#181C1F] py-1 shadow-lg border border-gray-600 focus:outline-none" tabindex="0" role="menu">
<div class="select-none space-y-1 p-1 pb-2 pr-2 text-sm">
<div on:click={() => ruleName = row?.rule}>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button builders={[builder]} class="bg-[#000] h-[33px] flex flex-row justify-between items-center w-[150px] xs:w-[140px] sm:w-[150px] px-3 text-white rounded-lg truncate">
<span class="truncate ml-2 text-sm sm:text-[1rem]">
{#if valueMappings[row?.rule] === 'any'}
Any
{:else}
{ruleCondition[row?.rule]} {valueMappings[row?.rule]}{row?.unit}
{/if}
</span>
<svg class=" ml-1 h-6 w-6 xs:ml-2 inline-block" viewBox="0 0 20 20" fill="currentColor" style="max-width:40px" aria-hidden="true">
<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>
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content class="w-56">
<DropdownMenu.Label>
<div class="flex items-center justify-start gap-x-1">
<div class="relative inline-block flex flex-row items-center justify-center m-auto">
<div class="relative inline-block flex flex-row items-center justify-center">
<label on:click={() => changeRuleCondition(row?.rule, 'under')} class="cursor-pointer flex flex-row mr-2 justify-center items-center">
<input type="radio" class="radio checked:bg-purple-600 bg-[#09090B] border border-slate-800 mr-2"
checked={conditions[row?.rule] === 'under'} name={row?.rule} />
checked={ruleCondition[row?.rule] === 'under'} name={row?.rule} />
<span class="label-text text-white">Under</span>
</label>
<label on:click={() => changeRuleCondition(row?.rule, 'over')} class="cursor-pointer flex flex-row ml-2 justify-center items-center">
<input type="radio" class="radio checked:bg-purple-600 bg-[#09090B] border border-slate-800 mr-2"
checked={conditions[row?.rule] === 'over'} name={row?.rule} />
checked={ruleCondition[row?.rule] === 'over'} name={row?.rule} />
<span class="label-text text-white">Over</span>
</label>
</div>
</div>
</div>
<div class="thin-scrollbar dark:styled-scrollbar dark:right-scrollbar max-h-[250px] overflow-y-auto overflow-x-hidden overscroll-contain border-t border-gray-600
dark:border-dark-500 xl:max-h-[297px]">
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
{#each row?.step as newValue}
<DropdownMenu.Item>
<button on:click={() => {handleChangeValue(newValue)}} class="block w-full border-b border-gray-600 px-4 py-2 text-left text-sm text-white last:border-0 sm:hover:bg-gray-100 sm:hover:text-gray-900
focus:bg-blue-100 focus:text-gray-900 focus:outline-none">
{ruleCondition[row?.rule]} {newValue}{row?.unit}
</button>
{/each}
</div>
</div>
</DropdownMenu.Item>
{/each}
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
</div>
</div>