refactor code

This commit is contained in:
MuslemRahimi 2024-12-01 19:55:22 +01:00
parent 85ba1761ec
commit 3dd2276996
6 changed files with 996 additions and 1747 deletions

View File

@ -1,38 +1,8 @@
<script lang="ts"> <script lang="ts">
import { abbreviateNumber } from "$lib/utils"; import { abbreviateNumber } from "$lib/utils";
export let data; export let data;
export let fields;
const fields = [ export let filterRule = null;
{ label: "Revenue", key: "revenue" },
{ label: "Cost of Revenue", key: "costOfRevenue" },
{ label: "Gross Profit", key: "grossProfit" },
{ label: "Net Income", key: "netIncome" },
{ label: "Operating Income", key: "operatingIncome" },
{
label: "Selling, General & Admin",
key: "sellingGeneralAndAdministrativeExpenses",
},
{
label: "Selling & Marketing Expenses",
key: "sellingAndMarketingExpenses",
},
{ label: "Research & Development", key: "researchAndDevelopmentExpenses" },
{ label: "Other Expenses", key: "otherExpenses" },
{ label: "Operating Expenses", key: "operatingExpenses" },
{ label: "Cost & Expenses", key: "costAndExpenses" },
{ label: "Interest Expense", key: "interestExpense" },
{ label: "Pretax Income", key: "incomeBeforeTax" },
{ label: "Income Tax", key: "incomeTaxExpense" },
{ label: "Interest Income", key: "interestIncome" },
{ label: "Interest Expense", key: "interestExpense" },
{ label: "Shares Outstanding (Basic)", key: "weightedAverageShsOut" },
{ label: "Shares Outstanding (Diluted)", key: "weightedAverageShsOutDil" },
{ label: "EPS (Basic)", key: "eps" },
{ label: "EPS (Diluted)", key: "epsdiluted" },
{ label: "EBITDA", key: "ebitda" },
{ label: "Depreciation & Amortization", key: "depreciation" },
];
</script> </script>
{#each fields as { label, key }} {#each fields as { label, key }}
@ -44,9 +14,15 @@
</td> </td>
{#each data as item} {#each data as item}
<td class="text-sm sm:text-[1rem] text-end"> <td class="text-sm sm:text-[1rem] text-end">
{item[key] !== null && item[key] !== 0 {#if filterRule === "annual"}
? abbreviateNumber(item[key]) {item[key] !== null && item[key] !== 0
: "-"} ? abbreviateNumber((item[key] / 4).toFixed(2))
: "-"}
{:else}
{item[key] !== null && item[key] !== 0
? abbreviateNumber(item[key]?.toFixed(2))
: "-"}
{/if}
</td> </td>
{/each} {/each}
</tr> </tr>

View File

@ -45,7 +45,7 @@
} }
</script> </script>
<section class="w-full overflow-hidden"> <section class="w-full overflow-hidden min-h-screen">
<div class="w-full overflow-hidden m-auto"> <div class="w-full overflow-hidden m-auto">
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden"> <div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden">
<div <div

View File

@ -60,6 +60,30 @@
label: "Gross Profit", label: "Gross Profit",
text: "Gross profit is a companys profit after subtracting the costs directly linked to making and delivering its products and services.", text: "Gross profit is a companys profit after subtracting the costs directly linked to making and delivering its products and services.",
}, },
{
propertyName: "operatingIncome",
growthPropertyName: "growthOperatingIncome",
label: "Operating Income",
text: "Gross profit is a companys profit after subtracting the costs directly linked to making and delivering its products and services.",
},
{
propertyName: "interestIncome",
growthPropertyName: "growthInterestIncome",
label: "Interest Income",
text: "Gross profit is a companys profit after subtracting the costs directly linked to making and delivering its products and services.",
},
{
propertyName: "incomeBeforeTax",
growthPropertyName: "growthIncomeBeforeTax",
label: "Pretax Income",
text: "Pretax income is a company's profits before accounting for income taxes.",
},
{
propertyName: "netIncome",
growthPropertyName: "growthNetIncome",
label: "Net Income",
text: `Net income is a company's accounting profits after subtracting all costs and expenses from the revenue. It is also called earnings, profits or "the bottom line."`,
},
{ {
propertyName: "sellingGeneralAndAdministrativeExpenses", propertyName: "sellingGeneralAndAdministrativeExpenses",
growthPropertyName: "growthSellingGeneralAndAdministrativeExpenses", growthPropertyName: "growthSellingGeneralAndAdministrativeExpenses",
@ -91,10 +115,16 @@
text: "Interest expense is the amount that the company paid or received in interest. A positive number indicates a net expense, while a negative number implies that the company had more interest income from its cash reserves than it paid for interest on debt.", text: "Interest expense is the amount that the company paid or received in interest. A positive number indicates a net expense, while a negative number implies that the company had more interest income from its cash reserves than it paid for interest on debt.",
}, },
{ {
propertyName: "incomeBeforeTax", propertyName: "sellingAndMarketingExpenses",
growthPropertyName: "growthIncomeBeforeTax", growthPropertyName: "growthSellingAndMarketingExpenses",
label: "Pretax Income", label: "Selling & Marketing Expenses",
text: "Pretax income is a company's profits before accounting for income taxes.", text: "Revenue, also called sales, is the amount of money a company receives from its business activities, such as sales of products or services. Revenue does not take any expenses into account and is therefore different from profits.",
},
{
propertyName: "costAndExpenses",
growthPropertyName: "growthCostAndExpensess",
label: "Cost & Expenses",
text: "Revenue, also called sales, is the amount of money a company receives from its business activities, such as sales of products or services. Revenue does not take any expenses into account and is therefore different from profits.",
}, },
{ {
propertyName: "incomeTaxExpense", propertyName: "incomeTaxExpense",
@ -102,12 +132,6 @@
label: "Income Tax", label: "Income Tax",
text: "Income tax is the amount of corporate income tax that the company has incurred during the fiscal period.", text: "Income tax is the amount of corporate income tax that the company has incurred during the fiscal period.",
}, },
{
propertyName: "netIncome",
growthPropertyName: "growthNetIncome",
label: "Net Income",
text: `Net income is a company's accounting profits after subtracting all costs and expenses from the revenue. It is also called earnings, profits or "the bottom line."`,
},
{ {
propertyName: "weightedAverageShsOut", propertyName: "weightedAverageShsOut",
growthPropertyName: "growthWeightedAverageShsOut", growthPropertyName: "growthWeightedAverageShsOut",
@ -146,6 +170,10 @@
}, },
]; ];
const fields = statementConfig.map((item) => ({
label: item.label,
key: item.propertyName,
}));
function toggleMode() { function toggleMode() {
$coolMode = !$coolMode; $coolMode = !$coolMode;
} }
@ -746,7 +774,7 @@
</thead> </thead>
<tbody> <tbody>
<!-- row --> <!-- row -->
<FinancialTable data={income} /> <FinancialTable data={income} {fields} />
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -15,6 +15,8 @@
import { LineChart, BarChart } from "echarts/charts"; import { LineChart, BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components"; import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers"; import { CanvasRenderer } from "echarts/renderers";
import FinancialTable from "$lib/components/FinancialTable.svelte";
use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]); use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
export let data; export let data;
@ -168,6 +170,11 @@
}, },
]; ];
const fields = statementConfig.map((item) => ({
label: item.label,
key: item.propertyName,
}));
function toggleMode() { function toggleMode() {
$coolMode = !$coolMode; $coolMode = !$coolMode;
} }
@ -447,586 +454,347 @@
{statementConfig?.find( {statementConfig?.find(
(item) => item?.propertyName === displayStatement, (item) => item?.propertyName === displayStatement,
)?.text} )?.text}
<!--<Katex formula={true} math={"\\textrm{Revenue}=\\textrm{Revenue} - \\textrm{All Expenses}"}/>--> {:else if cashFlow?.length > 0}
{:else}
Get detailed ratio statement breakdowns, uncovering price to Get detailed ratio statement breakdowns, uncovering price to
free cash flow ratio, price per earnings, and much more. free cash flow ratio, price per earnings, and much more.
{:else}
No financial data available for {$displayCompanyName}
{/if} {/if}
</div> </div>
{#if cashFlow?.length > 0}
<div
class="inline-flex justify-center w-full rounded-md sm:w-auto sm:ml-auto mt-3 mb-6"
>
<div <div
class="bg-[#313131] w-full min-w-24 sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4" class="inline-flex justify-center w-full rounded-md sm:w-auto sm:ml-auto mt-3 mb-6"
> >
{#each tabs as item, i}
<button
on:click={() => (activeIdx = i)}
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
i
? 'z-0'
: ''} "
>
{#if activeIdx === i}
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
{/if}
<span
class="relative text-sm block font-semibold {activeIdx ===
i
? 'text-black'
: 'text-white'}"
>
{item.title}
</span>
</button>
{/each}
</div>
</div>
<div
class="mb-2 flex flex-row items-center w-full justify-end sm:justify-center"
>
<label
class="inline-flex mt-2 sm:mt-0 cursor-pointer relative mr-auto"
>
<input
on:click={toggleMode}
type="checkbox"
checked={$coolMode}
value={$coolMode}
class="sr-only peer"
/>
<div <div
class="w-11 h-6 bg-gray-400 rounded-full peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#1563F9]" class="bg-[#313131] w-full min-w-24 sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4"
></div> >
{#if $coolMode} {#each tabs as item, i}
<span class="ml-2 text-sm font-medium text-white"> <button
Cool Mode on:click={() => (activeIdx = i)}
</span> class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
{:else} i
<span class="ml-2 text-sm font-medium text-white"> ? 'z-0'
Boring Mode : ''} "
</span> >
{/if} {#if activeIdx === i}
</label> <div
class="absolute inset-0 rounded-md bg-[#fff]"
></div>
{/if}
<span
class="relative text-sm block font-semibold {activeIdx ===
i
? 'text-black'
: 'text-white'}"
>
{item.title}
</span>
</button>
{/each}
</div>
</div>
<div <div
class="flex flex-row items-center w-fit sm:w-[50%] md:w-auto sm:ml-auto" class="mb-2 flex flex-row items-center w-full justify-end sm:justify-center"
> >
<div class="relative inline-block text-left grow"> <label
<DropdownMenu.Root> class="inline-flex mt-2 sm:mt-0 cursor-pointer relative mr-auto"
<DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
>
<span class="truncate text-white">{timeFrame}</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 h-fit max-h-72 overflow-y-auto scroller"
>
<DropdownMenu.Label class="text-gray-400">
Select time frame
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() => (timeFrame = "5Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
5 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "10Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
10 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "MAX")}
class="cursor-pointer hover:bg-[#27272A]"
>
Max
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
<Button
on:click={() => exportFundamentalData("csv")}
class="ml-2 w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
> >
<span class="truncate text-white">Download</span> <input
<svg on:click={toggleMode}
class="{data?.user?.tier === 'Pro' type="checkbox"
? 'hidden' checked={$coolMode}
: ''} ml-1 -mt-0.5 w-3.5 h-3.5" value={$coolMode}
xmlns="http://www.w3.org/2000/svg" class="sr-only peer"
viewBox="0 0 24 24" />
><path <div
fill="#A3A3A3" class="w-11 h-6 bg-gray-400 rounded-full peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#1563F9]"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z" ></div>
/></svg {#if $coolMode}
> <span class="ml-2 text-sm font-medium text-white">
</Button> Cool Mode
</div> </span>
</div> {:else}
<span class="ml-2 text-sm font-medium text-white">
Boring Mode
</span>
{/if}
</label>
{#if $coolMode} <div
<div class="sm:w-full"> class="flex flex-row items-center w-fit sm:w-[50%] md:w-auto sm:ml-auto"
<div class="relative"> >
<select <div class="relative inline-block text-left grow">
class="w-36 select select-bordered select-sm p-0 pl-5 overflow-y-auto bg-[#313131]" <DropdownMenu.Root>
on:change={changeStatement} <DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
>
<span class="truncate text-white">{timeFrame}</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 h-fit max-h-72 overflow-y-auto scroller"
>
<DropdownMenu.Label class="text-gray-400">
Select time frame
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() => (timeFrame = "5Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
5 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "10Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
10 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "MAX")}
class="cursor-pointer hover:bg-[#27272A]"
>
Max
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
<Button
on:click={() => exportFundamentalData("csv")}
class="ml-2 w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
> >
<option disabled>Choose an Cash Flow Variable</option> <span class="truncate text-white">Download</span>
<option value="netIncome" selected>Net Income</option> <svg
<option value="depreciationAndAmortization" class="{data?.user?.tier === 'Pro'
>Depreciation & Amortization</option ? 'hidden'
: ''} ml-1 -mt-0.5 w-3.5 h-3.5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#A3A3A3"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
/></svg
> >
<option value="stockBasedCompensation" </Button>
>Stock-Based Compensation</option
>
<option value="otherWorkingCapital"
>Other Working Capital</option
>
<option value="otherNonCashItems"
>Other Non-Cash Items</option
>
<option value="deferredIncomeTax"
>Deferred Income Tax</option
>
<option value="changeInWorkingCapital"
>Change in Working Capital</option
>
<option value="netCashProvidedByOperatingActivities"
>Operating Cash Flow</option
>
<option value="capitalExpenditure"
>Capital Expenditures</option
>
<option value="acquisitionsNet">Acquisitions</option>
<option value="purchasesOfInvestments"
>Purchase of Investments</option
>
<option value="salesMaturitiesOfInvestments"
>Sales Maturities Of Investments</option
>
<option value="otherInvestingActivites"
>Other Investing Acitivies</option
>
<option value="netCashUsedForInvestingActivites"
>Investing Cash Flow</option
>
<option value="debtRepayment">Debt Repayment</option>
<option value="commonStockRepurchased"
>Common Stock Repurchased</option
>
<option value="dividendsPaid">Dividend Paid</option>
<option value="otherFinancingActivites"
>Other Financial Acitivies</option
>
<option value="netCashUsedProvidedByFinancingActivities"
>Financial Cash Flow</option
>
<option value="netChangeInCash">Net Cash Flow</option>
<option value="freeCashFlow">Free Cash Flow</option>
</select>
</div> </div>
</div> </div>
<div class="app w-full"> {#if $coolMode}
<Chart {init} options={optionsData} class="chart" /> <div class="sm:w-full">
</div> <div class="relative">
<select
class="w-36 select select-bordered select-sm p-0 pl-5 overflow-y-auto bg-[#313131]"
on:change={changeStatement}
>
<option disabled>Choose an Cash Flow Variable</option>
<option value="netIncome" selected>Net Income</option>
<option value="depreciationAndAmortization"
>Depreciation & Amortization</option
>
<option value="stockBasedCompensation"
>Stock-Based Compensation</option
>
<option value="otherWorkingCapital"
>Other Working Capital</option
>
<option value="otherNonCashItems"
>Other Non-Cash Items</option
>
<option value="deferredIncomeTax"
>Deferred Income Tax</option
>
<option value="changeInWorkingCapital"
>Change in Working Capital</option
>
<option value="netCashProvidedByOperatingActivities"
>Operating Cash Flow</option
>
<option value="capitalExpenditure"
>Capital Expenditures</option
>
<option value="acquisitionsNet">Acquisitions</option>
<option value="purchasesOfInvestments"
>Purchase of Investments</option
>
<option value="salesMaturitiesOfInvestments"
>Sales Maturities Of Investments</option
>
<option value="otherInvestingActivites"
>Other Investing Acitivies</option
>
<option value="netCashUsedForInvestingActivites"
>Investing Cash Flow</option
>
<option value="debtRepayment">Debt Repayment</option>
<option value="commonStockRepurchased"
>Common Stock Repurchased</option
>
<option value="dividendsPaid">Dividend Paid</option>
<option value="otherFinancingActivites"
>Other Financial Acitivies</option
>
<option value="netCashUsedProvidedByFinancingActivities"
>Financial Cash Flow</option
>
<option value="netChangeInCash">Net Cash Flow</option>
<option value="freeCashFlow">Free Cash Flow</option>
</select>
</div>
</div>
<div class="w-full overflow-x-scroll"> <div class="app w-full">
<table <Chart {init} options={optionsData} class="chart" />
class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4" </div>
>
<thead>
<tr class="border border-gray-600">
<th
class="text-white font-semibold text-start text-sm sm:text-[1rem]"
>{filterRule === "annual"
? "Fiscal Year End"
: "Quarter Ends"}</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>{statementConfig?.find(
(item) => item?.propertyName === displayStatement,
)?.label}</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>Change</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>Growth</th
>
</tr>
</thead>
<tbody>
{#each tableList as item, index}
<!-- row -->
<tr
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"
>
<td
class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]"
>
{item?.date}
</td>
<td <div class="w-full overflow-x-scroll">
class="text-white text-sm sm:text-[1rem] text-right whitespace-nowrap border-b-[#09090B]" <table
class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4"
>
<thead>
<tr class="border border-gray-600">
<th
class="text-white font-semibold text-start text-sm sm:text-[1rem]"
>{filterRule === "annual"
? "Fiscal Year End"
: "Quarter Ends"}</th
> >
{abbreviateNumber(item?.value)} <th
</td> class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>{statementConfig?.find(
<td (item) => item?.propertyName === displayStatement,
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]" )?.label}</th
> >
{item?.value - tableList[index + 1]?.value !== 0 <th
? abbreviateNumber( class="text-white font-semibold text-end text-sm sm:text-[1rem]"
( >Change</th
item?.value - tableList[index + 1]?.value >
)?.toFixed(2), <th
) class="text-white font-semibold text-end text-sm sm:text-[1rem]"
: "-"} >Growth</th
</td>
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
> >
{#if index + 1 - tableList?.length === 0}
-
{:else if item?.value === 0 && tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">-100.00%</span>
{:else if item?.value === 0 && tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">100.00%</span>
{:else if item?.value - tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">
{(
((item?.value - tableList[index + 1]?.value) /
Math.abs(item?.value)) *
100
)?.toFixed(2)}%
</span>
{:else if item?.value - tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">
-{(
Math?.abs(
(tableList[index + 1]?.value - item?.value) /
Math.abs(item?.value),
) * 100
)?.toFixed(2)}%
</span>
{:else}
-
{/if}
</td>
</tr> </tr>
{/each} </thead>
</tbody> <tbody>
</table> {#each tableList as item, index}
</div> <!-- row -->
{:else} <tr
<div class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"
class="w-full rounded-none sm:rounded-md m-auto overflow-x-auto" >
>
<table class="table table-sm table-compact w-full">
<thead>
<tr class="text-white">
<td class="text-start text-white text-sm font-semibold"
>Year</td
>
{#each cashFlow as cash}
{#if filterRule === "annual"}
<td <td
class="bg-[#09090B] font-semibold text-end text-sm" class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]"
> >
{"FY" + cash?.calendarYear?.slice(-2)} {item?.date}
</td> </td>
{:else}
<td <td
class="bg-[#09090B] font-semibold text-end text-sm" class="text-white text-sm sm:text-[1rem] text-right whitespace-nowrap border-b-[#09090B]"
> >
{"FY" + {abbreviateNumber(item?.value)}
cash?.calendarYear?.slice(-2) +
" " +
cash?.period}
</td> </td>
{/if}
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
>
{item?.value - tableList[index + 1]?.value !== 0
? abbreviateNumber(
(
item?.value - tableList[index + 1]?.value
)?.toFixed(2),
)
: "-"}
</td>
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
>
{#if index + 1 - tableList?.length === 0}
-
{:else if item?.value === 0 && tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">-100.00%</span>
{:else if item?.value === 0 && tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">100.00%</span>
{:else if item?.value - tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">
{(
((item?.value - tableList[index + 1]?.value) /
Math.abs(item?.value)) *
100
)?.toFixed(2)}%
</span>
{:else if item?.value - tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">
-{(
Math?.abs(
(tableList[index + 1]?.value -
item?.value) /
Math.abs(item?.value),
) * 100
)?.toFixed(2)}%
</span>
{:else}
-
{/if}
</td>
</tr>
{/each} {/each}
</tr> </tbody>
</thead> </table>
<tbody> </div>
<!-- row --> {:else}
<tr class="text-white odd:bg-[#27272A]"> <div
<td class="w-full rounded-none sm:rounded-md m-auto overflow-x-auto"
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]" >
>Net Income</td <table class="table table-sm table-compact w-full">
> <thead>
{#each cashFlow as cash} <tr class="text-white">
<td class="text-end text-sm sm:text-[1rem]"> <td class="text-start text-white text-sm font-semibold"
{abbreviateNumber(cash?.netIncome)}</td >Year</td
> >
{/each} {#each cashFlow as cash}
</tr> {#if filterRule === "annual"}
<tr class="text-white odd:bg-[#27272A]"> <td
<td class="bg-[#09090B] font-semibold text-end text-sm"
class="text-start whitespace-nowrap border-r border-gray-700 text-sm sm:text-[1rem]" >
>Depreciation & Amortization</td {"FY" + cash?.calendarYear?.slice(-2)}
> </td>
{#each cashFlow as cash} {:else}
<td class="text-end text-sm sm:text-[1rem]"> <td
{abbreviateNumber( class="bg-[#09090B] font-semibold text-end text-sm"
cash?.depreciationAndAmortization, >
)}</td {"FY" +
> cash?.calendarYear?.slice(-2) +
{/each} " " +
</tr> cash?.period}
<!-- row --> </td>
<tr class="text-white odd:bg-[#27272A]"> {/if}
<td {/each}
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]" </tr>
>Stock-Based Compensation</td </thead>
> <tbody>
{#each cashFlow as cash} <!-- row -->
<td class="text-end text-sm sm:text-[1rem]"> <FinancialTable data={cashFlow} {fields} />
{abbreviateNumber(cash?.stockBasedCompensation)}</td </tbody>
> </table>
{/each} </div>
</tr> {/if}
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Other Working Capital</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.otherWorkingCapital)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Other Non-Cash Items</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.otherNonCashItems)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Deferred Income Tax</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.deferredIncomeTax)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Change in Working Capital</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.changeInWorkingCapital)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Operating Cash Flow</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(
cash?.netCashProvidedByOperatingActivities,
)}</td
>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Capital Expenditures</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.capitalExpenditure)}</td
>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Acquisitions</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.acquisitionsNet)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Purchase of Investments</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.purchasesOfInvestments)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start whitespace-nowrap border-r border-gray-700 text-sm sm:text-[1rem]"
>Sales Maturities Of Investments</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(
cash?.salesMaturitiesOfInvestments,
)}</td
>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Other Investing Acitivies</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.otherInvestingActivites)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Investing Cash Flow</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(
cash?.netCashUsedForInvestingActivites,
)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Debt Repayment</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.debtRepayment)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start whitespace-nowrap border-r border-gray-700 text-sm sm:text-[1rem]"
>Common Stock Repurchased</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.commonStockRepurchased)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Dividend Paid</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.dividendsPaid)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Other Financial Acitivies</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.otherFinancingActivites)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Financial Cash Flow</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(
cash?.netCashUsedProvidedByFinancingActivities,
)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Net Cash Flow</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.netChangeInCash)}</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Free Cash Flow</td
>
{#each cashFlow as cash}
<td class="text-end text-sm sm:text-[1rem]">
{abbreviateNumber(cash?.freeCashFlow)}</td
>
{/each}
</tr>
</tbody>
</table>
</div>
{/if} {/if}
</div> </div>
</div> </div>

View File

@ -15,6 +15,8 @@
import { LineChart, BarChart } from "echarts/charts"; import { LineChart, BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components"; import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers"; import { CanvasRenderer } from "echarts/renderers";
import FinancialTable from "$lib/components/FinancialTable.svelte";
use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]); use([LineChart, BarChart, GridComponent, TooltipComponent, CanvasRenderer]);
export let data; export let data;
@ -132,6 +134,11 @@
}, },
]; ];
const fields = statementConfig.map((item) => ({
label: item.label,
key: item.propertyName,
}));
function toggleMode() { function toggleMode() {
$coolMode = !$coolMode; $coolMode = !$coolMode;
} }
@ -411,555 +418,331 @@
{statementConfig?.find( {statementConfig?.find(
(item) => item?.propertyName === displayStatement, (item) => item?.propertyName === displayStatement,
)?.text} )?.text}
<!--<Katex formula={true} math={"\\textrm{Revenue}=\\textrm{Revenue} - \\textrm{All Expenses}"}/>--> {:else if ratios?.length > 0}
{:else}
Get detailed income statement breakdowns, uncovering revenue, Get detailed income statement breakdowns, uncovering revenue,
expenses, and much more. expenses, and much more.
{:else}
No financial data available for {$displayCompanyName}
{/if} {/if}
</div> </div>
{#if ratios?.length > 0}
<div
class="inline-flex justify-center w-full rounded-md sm:w-auto sm:ml-auto mt-3 mb-6"
>
<div <div
class="bg-[#313131] w-full min-w-24 sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4" class="inline-flex justify-center w-full rounded-md sm:w-auto sm:ml-auto mt-3 mb-6"
> >
{#each tabs as item, i}
<button
on:click={() => (activeIdx = i)}
class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
i
? 'z-0'
: ''} "
>
{#if activeIdx === i}
<div class="absolute inset-0 rounded-md bg-[#fff]"></div>
{/if}
<span
class="relative text-sm block font-semibold {activeIdx ===
i
? 'text-black'
: 'text-white'}"
>
{item.title}
</span>
</button>
{/each}
</div>
</div>
<div
class="mb-2 flex flex-row items-center w-full justify-end sm:justify-center"
>
<label
class="inline-flex mt-2 sm:mt-0 cursor-pointer relative mr-auto"
>
<input
on:click={toggleMode}
type="checkbox"
checked={$coolMode}
value={$coolMode}
class="sr-only peer"
/>
<div <div
class="w-11 h-6 bg-gray-400 rounded-full peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#1563F9]" class="bg-[#313131] w-full min-w-24 sm:w-fit relative flex flex-wrap items-center justify-center rounded-md p-1 mt-4"
></div> >
{#if $coolMode} {#each tabs as item, i}
<span class="ml-2 text-sm font-medium text-white"> <button
Cool Mode on:click={() => (activeIdx = i)}
</span> class="group relative z-[1] rounded-full w-1/2 min-w-24 md:w-auto px-5 py-1 {activeIdx ===
{:else} i
<span class="ml-2 text-sm font-medium text-white"> ? 'z-0'
Boring Mode : ''} "
</span> >
{/if} {#if activeIdx === i}
</label> <div
class="absolute inset-0 rounded-md bg-[#fff]"
></div>
{/if}
<span
class="relative text-sm block font-semibold {activeIdx ===
i
? 'text-black'
: 'text-white'}"
>
{item.title}
</span>
</button>
{/each}
</div>
</div>
<div <div
class="flex flex-row items-center w-fit sm:w-[50%] md:w-auto sm:ml-auto" class="mb-2 flex flex-row items-center w-full justify-end sm:justify-center"
> >
<div class="relative inline-block text-left grow"> <label
<DropdownMenu.Root> class="inline-flex mt-2 sm:mt-0 cursor-pointer relative mr-auto"
<DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
>
<span class="truncate text-white">{timeFrame}</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 h-fit max-h-72 overflow-y-auto scroller"
>
<DropdownMenu.Label class="text-gray-400">
Select time frame
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() => (timeFrame = "5Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
5 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "10Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
10 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "MAX")}
class="cursor-pointer hover:bg-[#27272A]"
>
Max
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
<Button
on:click={() => exportFundamentalData("csv")}
class="ml-2 w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
> >
<span class="truncate text-white">Download</span> <input
<svg on:click={toggleMode}
class="{data?.user?.tier === 'Pro' type="checkbox"
? 'hidden' checked={$coolMode}
: ''} ml-1 -mt-0.5 w-3.5 h-3.5" value={$coolMode}
xmlns="http://www.w3.org/2000/svg" class="sr-only peer"
viewBox="0 0 24 24" />
><path <div
fill="#A3A3A3" class="w-11 h-6 bg-gray-400 rounded-full peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#1563F9]"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z" ></div>
/></svg {#if $coolMode}
> <span class="ml-2 text-sm font-medium text-white">
</Button> Cool Mode
</div> </span>
</div> {:else}
<span class="ml-2 text-sm font-medium text-white">
Boring Mode
</span>
{/if}
</label>
{#if $coolMode} <div
<div class="sm:w-full"> class="flex flex-row items-center w-fit sm:w-[50%] md:w-auto sm:ml-auto"
<div class="relative"> >
<select <div class="relative inline-block text-left grow">
class="w-36 select select-bordered select-sm p-0 pl-5 overflow-y-auto bg-[#313131]" <DropdownMenu.Root>
on:change={changeStatement} <DropdownMenu.Trigger asChild let:builder>
<Button
builders={[builder]}
class="w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
>
<span class="truncate text-white">{timeFrame}</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 h-fit max-h-72 overflow-y-auto scroller"
>
<DropdownMenu.Label class="text-gray-400">
Select time frame
</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.Item
on:click={() => (timeFrame = "5Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
5 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "10Y")}
class="cursor-pointer hover:bg-[#27272A]"
>
10 years
</DropdownMenu.Item>
<DropdownMenu.Item
on:click={() => (timeFrame = "MAX")}
class="cursor-pointer hover:bg-[#27272A]"
>
Max
</DropdownMenu.Item>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
<Button
on:click={() => exportFundamentalData("csv")}
class="ml-2 w-full border-gray-600 border bg-[#09090B] sm:hover:bg-[#27272A] ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
> >
<option disabled>Choose an Income Variable</option> <span class="truncate text-white">Download</span>
<option value="priceEarningsRatio" selected>PE Ratio</option <svg
class="{data?.user?.tier === 'Pro'
? 'hidden'
: ''} ml-1 -mt-0.5 w-3.5 h-3.5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#A3A3A3"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
/></svg
> >
<option value="priceToSalesRatio">PS Ratio</option> </Button>
<option value="priceToBookRatio">PB Ratio</option>
<option value="priceToFreeCashFlowsRatio"
>P/FCF Ratio</option
>
<option value="priceToOperatingCashFlowsRatio"
>P/OCF Ratio</option
>
<option value="operatingCashFlowSalesRatio"
>OCF/S Ratio</option
>
<option value="debtEquityRatio">Debt / Equity Ratio</option>
<option value="quickRatio">Quick Ratio</option>
<option value="currentRatio">Current Ratio</option>
<option value="assetTurnover">Asset Turnover</option>
<option value="interestCoverage">Interest Coverage</option>
<option value="returnOnEquity"
>Return on Equity (ROE)</option
>
<option value="returnOnAssets"
>Return on Assets (ROA)</option
>
<option value="returnOnCapitalEmployed"
>Return on Capital (ROIC)</option
>
<option value="dividendYield">Dividend Yield</option>
<option value="payoutRatio">Payout Ratio</option>
<option value="grossProfitMargin"
>Gross Profit Margin</option
>
<option value="netProfitMargin">Net Profit Margin</option>
</select>
</div> </div>
</div> </div>
<div class="app w-full"> {#if $coolMode}
<Chart {init} options={optionsData} class="chart" /> <div class="sm:w-full">
</div> <div class="relative">
<select
class="w-36 select select-bordered select-sm p-0 pl-5 overflow-y-auto bg-[#313131]"
on:change={changeStatement}
>
<option disabled>Choose an Income Variable</option>
<option value="priceEarningsRatio" selected
>PE Ratio</option
>
<option value="priceToSalesRatio">PS Ratio</option>
<option value="priceToBookRatio">PB Ratio</option>
<option value="priceToFreeCashFlowsRatio"
>P/FCF Ratio</option
>
<option value="priceToOperatingCashFlowsRatio"
>P/OCF Ratio</option
>
<option value="operatingCashFlowSalesRatio"
>OCF/S Ratio</option
>
<option value="debtEquityRatio"
>Debt / Equity Ratio</option
>
<option value="quickRatio">Quick Ratio</option>
<option value="currentRatio">Current Ratio</option>
<option value="assetTurnover">Asset Turnover</option>
<option value="interestCoverage">Interest Coverage</option
>
<option value="returnOnEquity"
>Return on Equity (ROE)</option
>
<option value="returnOnAssets"
>Return on Assets (ROA)</option
>
<option value="returnOnCapitalEmployed"
>Return on Capital (ROIC)</option
>
<option value="dividendYield">Dividend Yield</option>
<option value="payoutRatio">Payout Ratio</option>
<option value="grossProfitMargin"
>Gross Profit Margin</option
>
<option value="netProfitMargin">Net Profit Margin</option>
</select>
</div>
</div>
<div class="w-full overflow-x-scroll"> <div class="app w-full">
<table <Chart {init} options={optionsData} class="chart" />
class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4" </div>
>
<thead>
<tr class="border border-gray-600">
<th
class="text-white font-semibold text-start text-sm sm:text-[1rem]"
>{filterRule === "annual"
? "Fiscal Year End"
: "Quarter Ends"}</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>{statementConfig?.find(
(item) => item?.propertyName === displayStatement,
)?.label}</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>Change</th
>
<th
class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>Growth</th
>
</tr>
</thead>
<tbody>
{#each tableList as item, index}
<!-- row -->
<tr
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"
>
<td
class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]"
>
{item?.date}
</td>
<td <div class="w-full overflow-x-scroll">
class="text-white text-sm sm:text-[1rem] text-right whitespace-nowrap border-b-[#09090B]" <table
class="table table-sm table-compact rounded-none sm:rounded-md w-full border-bg-[#09090B] m-auto mt-4"
>
<thead>
<tr class="border border-gray-600">
<th
class="text-white font-semibold text-start text-sm sm:text-[1rem]"
>{filterRule === "annual"
? "Fiscal Year End"
: "Quarter Ends"}</th
> >
{abbreviateNumber(item?.value)} <th
</td> class="text-white font-semibold text-end text-sm sm:text-[1rem]"
>{statementConfig?.find(
<td (item) => item?.propertyName === displayStatement,
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]" )?.label}</th
> >
{item?.value - tableList[index + 1]?.value !== 0 <th
? abbreviateNumber( class="text-white font-semibold text-end text-sm sm:text-[1rem]"
( >Change</th
item?.value - tableList[index + 1]?.value >
)?.toFixed(2), <th
) class="text-white font-semibold text-end text-sm sm:text-[1rem]"
: "-"} >Growth</th
</td>
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
> >
{#if index + 1 - tableList?.length === 0}
-
{:else if item?.value === 0 && tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">-100.00%</span>
{:else if item?.value === 0 && tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">100.00%</span>
{:else if item?.value - tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">
{(
((item?.value - tableList[index + 1]?.value) /
Math.abs(item?.value)) *
100
)?.toFixed(2)}%
</span>
{:else if item?.value - tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">
-{(
Math?.abs(
(tableList[index + 1]?.value - item?.value) /
Math.abs(item?.value),
) * 100
)?.toFixed(2)}%
</span>
{:else}
-
{/if}
</td>
</tr> </tr>
{/each} </thead>
</tbody> <tbody>
</table> {#each tableList as item, index}
</div> <!-- row -->
{:else} <tr
<div class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B] shake-ticker cursor-pointer"
class="w-full rounded-none sm:rounded-md m-auto overflow-x-auto" >
>
<table class="table table-sm table-compact w-full">
<thead>
<tr class="text-white">
<td class="text-start text-sm font-semibold">Year</td>
{#each ratios as item}
{#if filterRule === "annual"}
<td <td
class="bg-[#09090B] font-semibold text-end text-sm" class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]"
> >
{"FY" + item?.calendarYear?.slice(-2)} {item?.date}
</td> </td>
{:else}
<td <td
class="bg-[#09090B] font-semibold text-end text-sm" class="text-white text-sm sm:text-[1rem] text-right whitespace-nowrap border-b-[#09090B]"
> >
{"FY" + {abbreviateNumber(item?.value)}
item?.calendarYear?.slice(-2) +
" " +
item?.period}
</td> </td>
{/if}
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
>
{item?.value - tableList[index + 1]?.value !== 0
? abbreviateNumber(
(
item?.value - tableList[index + 1]?.value
)?.toFixed(2),
)
: "-"}
</td>
<td
class="text-white text-sm sm:text-[1rem] whitespace-nowrap font-medium text-end border-b-[#09090B]"
>
{#if index + 1 - tableList?.length === 0}
-
{:else if item?.value === 0 && tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">-100.00%</span>
{:else if item?.value === 0 && tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">100.00%</span>
{:else if item?.value - tableList[index + 1]?.value > 0}
<span class="text-[#00FC50]">
{(
((item?.value - tableList[index + 1]?.value) /
Math.abs(item?.value)) *
100
)?.toFixed(2)}%
</span>
{:else if item?.value - tableList[index + 1]?.value < 0}
<span class="text-[#FF2F1F]">
-{(
Math?.abs(
(tableList[index + 1]?.value -
item?.value) /
Math.abs(item?.value),
) * 100
)?.toFixed(2)}%
</span>
{:else}
-
{/if}
</td>
</tr>
{/each} {/each}
</tr> </tbody>
</thead> </table>
<tbody> </div>
<!-- row --> {:else}
<tr class="text-white odd:bg-[#27272A] whitespace-nowrap"> <div
<td class="w-full rounded-none sm:rounded-md m-auto overflow-x-auto"
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]" >
>PE Ratio</td <table class="table table-sm table-compact w-full">
> <thead>
{#each ratios as item} <tr class="text-white">
<td class="text-sm sm:text-[1rem] text-end"> <td class="text-start text-sm font-semibold">Year</td>
{filterRule === "annual" {#each ratios as item}
? (item?.priceEarningsRatio / 4)?.toFixed(2) {#if filterRule === "annual"}
: item?.priceEarningsRatio?.toFixed(2)} <td
</td> class="bg-[#09090B] font-semibold text-end text-sm"
{/each} >
</tr> {"FY" + item?.calendarYear?.slice(-2)}
<tr class="text-white odd:bg-[#27272A]"> </td>
<td {:else}
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]" <td
>PS Ratio</td class="bg-[#09090B] font-semibold text-end text-sm"
> >
{#each ratios as item} {"FY" +
<td class="text-sm sm:text-[1rem] text-end"> item?.calendarYear?.slice(-2) +
{filterRule === "annual" " " +
? (item?.priceToSalesRatio / 4)?.toFixed(2) item?.period}
: item?.priceToSalesRatio?.toFixed(2)} </td>
</td> {/if}
{/each} {/each}
</tr> </tr>
<!-- row --> </thead>
<tr class="text-white odd:bg-[#27272A]"> <tbody>
<td <!-- row -->
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]" <FinancialTable data={ratios} {fields} {filterRule} />
>PB Ratio</td </tbody>
> </table>
{#each ratios as item} </div>
<td class="text-sm sm:text-[1rem] text-end"> {/if}
{filterRule === "annual"
? (item?.priceToBookRatio / 4)?.toFixed(2)
: item?.priceToBookRatio?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A] whitespace-nowrap">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>P/FCF Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.priceToFreeCashFlowsRatio / 4)?.toFixed(2)
: item?.priceToFreeCashFlowsRatio?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>P/OCF Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (
item?.priceToOperatingCashFlowsRatio / 4
)?.toFixed(2)
: item?.priceToOperatingCashFlowsRatio?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>OCF/S Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.operatingCashFlowSalesRatio / 4)?.toFixed(
2,
)
: item?.operatingCashFlowSalesRatio?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start whitespace-nowrap border-r border-gray-700 text-sm sm:text-[1rem]"
>Debt / Equity Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.debtEquityRatio / 4)?.toFixed(2)
: item?.debtEquityRatio?.toFixed(2)}
</td>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Quick Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.quickRatio / 4)?.toFixed(2)
: item?.quickRatio?.toFixed(2)}
</td>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Current Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.currentRatio / 4)?.toFixed(2)
: item?.currentRatio?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem] whitespace-nowrap"
>Asset Turnover</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{item?.assetTurnover?.toFixed(2)}
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Interest Coverage</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? (item?.interestCoverage / 4)?.toFixed(2)
: item?.interestCoverage?.toFixed(2)}
</td>
{/each}
</tr>
<!-- row -->
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Return on Equity (ROE)</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{(item?.returnOnEquity * 100)?.toFixed(2)}%
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start whitespace-nowrap border-r border-gray-700 text-sm sm:text-[1rem]"
>Return on Assets (ROA)</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end"
>{(item?.returnOnAssets * 100)?.toFixed(2)}%</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Return on Capital (ROIC)</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{(item?.returnOnCapitalEmployed * 100)?.toFixed(
2,
)}%</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Dividend Yield</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{(item?.dividendYield * 100)?.toFixed(2)}%</td
>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Payout Ratio</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? ((item?.payoutRatio / 4) * 100)?.toFixed(2)
: (item?.payoutRatio * 100)?.toFixed(2)}%
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Gross Profit Margin</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? ((item?.grossProfitMargin / 4) * 100)?.toFixed(2)
: (item?.grossProfitMargin * 100)?.toFixed(2)}%
</td>
{/each}
</tr>
<tr class="text-white odd:bg-[#27272A]">
<td
class="text-start border-r border-gray-700 text-sm sm:text-[1rem]"
>Net Profit Margin</td
>
{#each ratios as item}
<td class="text-sm sm:text-[1rem] text-end">
{filterRule === "annual"
? ((item?.netProfitMargin / 4) * 100)?.toFixed(2)
: (item?.netProfitMargin * 100)?.toFixed(2)}%
</td>
{/each}
</tr>
</tbody>
</table>
</div>
{/if} {/if}
</div> </div>
</div> </div>