update index page

This commit is contained in:
MuslemRahimi 2025-02-09 23:37:44 +01:00
parent 5b500ae3f9
commit 7a2bc1ba47
25 changed files with 114 additions and 418 deletions

View File

@ -1,47 +1,28 @@
<script lang="ts"> <script lang="ts">
import { indexTicker, stockTicker } from "$lib/store"; import { indexTicker } from "$lib/store";
import { import {
formatString,
abbreviateNumber, abbreviateNumber,
sectorNavigation, sectorNavigation,
} from "$lib/utils"; } from "$lib/utils";
import { goto } from "$app/navigation";
export let data; export let data;
let info; let info;
let topHoldingList = [];
let topSectorList = []; let topSectorList = [];
let description = ""; let description = "";
let assetClass = "-";
let totalAssetPercentage = 0;
async function stockSelector(ticker: string) {
if (ticker?.length !== 0 && !["BTCUSD", "USD"]?.includes(ticker)) {
window?.scroll({ top: 0, left: 0, behavior: "smooth" });
stockTicker.update((value) => ticker);
goto("/stocks/" + ticker + "/");
}
}
$: { $: {
if ($indexTicker) { if ($indexTicker) {
info = data?.getIndexProfile?.at(0); info = data?.getIndexProfile?.at(0);
topHoldingList = data?.getIndexHoldings?.holdings || [];
topSectorList = data?.getIndexSectorWeighting || []; topSectorList = data?.getIndexSectorWeighting || [];
assetClass = info?.assetClass;
description = description =
info?.description ?? info?.description ??
"A detailed description of the company is not yet available."; "A detailed description of the company is not yet available.";
totalAssetPercentage = topHoldingList
?.slice(0, 5)
?.reduce((acc, current) => acc + current?.weightPercentage, 0)
?.toFixed(2);
} }
} }
</script> </script>
@ -54,22 +35,7 @@
{description} {description}
</p> </p>
<div
class="mt-3 grid grid-cols-2 gap-3 w-full border-b border-gray-600 lg:border-none pb-8 lg:pb-0"
>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Asset Class</span>
<span class=" text-white">{assetClass}</span>
</div>
<div class="col-span-1 text-gray-200">
<span class="block font-semibold">Ticker Symbol</span>
{$indexTicker}
</div>
</div>
</div> </div>
{#if topSectorList?.length !== 0} {#if topSectorList?.length !== 0}
@ -133,86 +99,5 @@
</div> </div>
{/if} {/if}
{#if topHoldingList?.length !== 0}
<div
class="space-y-3 pt-8 sm:pt-5 {topHoldingList?.length !== 0
? ''
: 'hidden'}"
>
<div class="h-auto w-full">
<!--Start Content-->
<div class="w-auto lg:w-full flex flex-col m-auto">
<h2
class="mb-2 text-2xl text-white font-semibold flex flex-row items-center"
>
<span>Top Holdings</span>
<span class="text-white font-semibold ml-auto text-sm">
{totalAssetPercentage}% of assets
</span>
</h2>
<div class="mt-2 w-full">
<table class="table table-sm table-compact w-full">
<thead>
<tr>
<th
class="text-white font-semibold text-sm text-start bg-default"
>Company</th
>
<th class="text-white font-semibold text-sm text-end bg-default"
>Portfolio</th
>
</tr>
</thead>
<tbody>
{#each topHoldingList?.slice(0, 5) as item}
{#if item?.symbol !== null}
<tr
on:click={() => stockSelector(item?.symbol)}
class="lg:shake-ticker sm:hover:text-white text-blue-400 cursor-pointer lg:hover:bg-[#245073] lg:hover:bg-opacity-[0.2] [#09090B] border-b border-[#27272A]"
>
<td class="">
<div class="flex flex-row items-center">
<div class="flex flex-col w-full">
<span class="text-sm font-medium"
>{item?.symbol ?? "n/a"}</span
>
<span class="text-white text-sm">
{#if typeof item?.name !== "undefined"}
{item?.name?.length > 20
? formatString(item?.name?.slice(0, 20)) + "..."
: formatString(item?.name)?.replace(
"Usd",
"USD",
)}
{:else}
n/a
{/if}
</span>
</div>
</div>
</td>
<td class="text-white font-semibold text-end">
{abbreviateNumber(item?.weightPercentage?.toFixed(2))}%
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
<a
href={`/etf/${$indexTicker}/holdings`}
class="rounded cursor-pointer w-full m-auto py-2 h-full mt-6 text-[1rem] text-center font-semibold text-black sm:hover:hover:bg-gray-300 bg-[#ffff] transition duration-100"
>
All Holdings
</a>
</div>
</div>
</div>
{/if}

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { stockTicker, etfTicker, setCache, getCache } from "$lib/store"; import { stockTicker, etfTicker, indexTicker, setCache, getCache } from "$lib/store";
import { formatDate } from "$lib/utils"; import { formatDate } from "$lib/utils";
import { page } from "$app/stores"; import { page } from "$app/stores";
@ -72,7 +72,7 @@
})(); })();
$: { $: {
if ($stockTicker || $etfTicker) { if ($stockTicker || $etfTicker || $indexTicker) {
rawData = data?.getNews || []; rawData = data?.getNews || [];
rawDataPressRelease = []; rawDataPressRelease = [];
newsList = rawData?.slice(0, 10) ?? []; newsList = rawData?.slice(0, 10) ?? [];
@ -128,7 +128,8 @@
> >
</li> </li>
{/if} {/if}
{#if !$page?.url?.pathname.includes("etf")} {#if !["etf", "index"].some(sub => $page.url.pathname?.includes(sub))}
<li> <li>
<button <button
on:click={() => getPressRelease()} on:click={() => getPressRelease()}

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { stockTicker, etfTicker } from "$lib/store"; import { stockTicker, etfTicker, indexTicker } from "$lib/store";
import InfoModal from "$lib/components/InfoModal.svelte"; import InfoModal from "$lib/components/InfoModal.svelte";
import { get } from "svelte/store"; import { get } from "svelte/store";
import { formatDate } from "$lib/utils"; import { formatDate } from "$lib/utils";
@ -35,7 +35,7 @@
} }
$: { $: {
if (get(stockTicker) || get(etfTicker)) { if (get(stockTicker) || get(etfTicker) || get(indexTicker)) {
showFullHistory = false; showFullHistory = false;
wiim = data?.getWhyPriceMoved || []; wiim = data?.getWhyPriceMoved || [];
} }

View File

@ -34,7 +34,7 @@
let socket; let socket;
$etfTicker = data?.getParams; $etfTicker = data?.getParams;
$assetType = "stock"; $assetType = "etf";
$displayCompanyName = data?.companyName; $displayCompanyName = data?.companyName;
let isScrolled = false; let isScrolled = false;
@ -380,9 +380,7 @@
class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2" class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2"
> >
<a <a
href={/^\/(stocks|etf)/.test($previousPage) href={/^\/(stocks|etf|index)/.test($previousPage || "") ? "/" : $previousPage || "/"}
? "/"
: $previousPage || "/"}
> >
<svg <svg
class="w-5 h-5 inline-block" class="w-5 h-5 inline-block"

View File

@ -71,9 +71,8 @@ export const load = async ({ params, locals }) => {
const promises = endpoints.map((endpoint) => { const promises = endpoints.map((endpoint) => {
// Use SPY for specific endpoints when tickerID is ^SPC or ^spc // Use SPY for specific endpoints when tickerID is ^SPC or ^spc
const useSpyTicker = tickerID?.toLowerCase() === "^spc" && const useSpyTicker = tickerID?.toLowerCase() === "^spx" &&
["/etf-holdings", "/etf-sector-weighting", "/wiim", "/stock-news"].includes(endpoint); ["/etf-holdings", "/etf-sector-weighting", "/wiim", "/stock-news"]?.includes(endpoint);
return fetchData(apiURL, apiKey, endpoint, useSpyTicker ? "SPY" : tickerID); return fetchData(apiURL, apiKey, endpoint, useSpyTicker ? "SPY" : tickerID);
}); });

View File

@ -34,7 +34,7 @@
let socket; let socket;
$indexTicker = data?.getParams; $indexTicker = data?.getParams;
$assetType = "stock"; $assetType = "index";
$displayCompanyName = data?.companyName; $displayCompanyName = data?.companyName;
let isScrolled = false; let isScrolled = false;
@ -68,16 +68,14 @@
function changeSection(state) { function changeSection(state) {
const sectionMap = { const sectionMap = {
options: "/options", options: "/options",
metrics: "metrics", holdings: "holdings",
history: "/history", history: "/history",
}; };
if (state !== "overview" && sectionMap[state]) { if (state !== "overview" && sectionMap[state]) {
displaySection = state; displaySection = state;
//goto(`/etf/${$indexTicker}${sectionMap[state]}`);
} else { } else {
displaySection = "overview"; displaySection = "overview";
//goto(`/etf/${$indexTicker}/`);
} }
} }
@ -325,7 +323,7 @@
$: charNumber = $screenWidth < 640 ? 25 : 40; $: charNumber = $screenWidth < 640 ? 25 : 40;
$: { $: {
if ($indexTicker && $page.url.pathname === `/etf/${$indexTicker}`) { if ($indexTicker && $page.url.pathname === `/index/${$indexTicker}`) {
displaySection = "overview"; displaySection = "overview";
} }
} }
@ -374,10 +372,7 @@
class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2" class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2"
> >
<a <a
href={/^\/(stocks|etf)/.test($previousPage) href={/^\/(stocks|etf|index)/.test($previousPage || "") ? "/" : $previousPage || "/"}>
? "/"
: $previousPage || "/"}
>
<svg <svg
class="w-5 h-5 inline-block" class="w-5 h-5 inline-block"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -430,7 +425,7 @@
<label <label
class="mr-4" class="mr-4"
on:click={() => on:click={() =>
shareContent("https://stocknear.com/etf/" + $indexTicker)} shareContent("https://stocknear.com/index/" + $indexTicker)}
> >
<svg <svg
class="w-6 h-6 inline-block" class="w-6 h-6 inline-block"
@ -854,7 +849,7 @@
class="flex flex-row items-center w-full text-[1rem] text-white" class="flex flex-row items-center w-full text-[1rem] text-white"
> >
<a <a
href={`/etf/${$indexTicker}`} href={`/index/${$indexTicker}`}
on:click={() => changeSection("overview")} on:click={() => changeSection("overview")}
class="p-2 px-5 cursor-pointer {displaySection === class="p-2 px-5 cursor-pointer {displaySection ===
'overview' 'overview'
@ -865,7 +860,7 @@
</a> </a>
<a <a
href={`/etf/${$indexTicker}/holdings`} href={`/index/${$indexTicker}/holdings`}
on:click={() => changeSection("holdings")} on:click={() => changeSection("holdings")}
class="p-2 px-5 cursor-pointer {displaySection === class="p-2 px-5 cursor-pointer {displaySection ===
'holdings' 'holdings'
@ -875,7 +870,7 @@
Holdings Holdings
</a> </a>
<a <a
href={`/etf/${$indexTicker}/options`} href={`/index/${$indexTicker}/options`}
on:click={() => changeSection("options")} on:click={() => changeSection("options")}
class="p-2 px-5 cursor-pointer {displaySection === class="p-2 px-5 cursor-pointer {displaySection ===
'options' 'options'
@ -885,28 +880,10 @@
Options Options
</a> </a>
<a <a
href={`/etf/${$indexTicker}/insider`} href={`/index/${$indexTicker}/history`}
on:click={() => changeSection("insider")}
class="p-2 px-5 cursor-pointer {displaySection ===
'insider'
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Insider
</a>
<a
href={`/etf/${$indexTicker}/dividends`}
on:click={() => changeSection("dividends")}
class="p-2 px-5 cursor-pointer {displaySection ===
'dividends'
? 'text-white bg-secondary sm:hover:bg-opacity-[0.95] font-semibold'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-secondary sm:hover:bg-opacity-[0.95]'}"
>
Dividends
</a>
<a
href={`/etf/${$indexTicker}/history`}
on:click={() => changeSection("history")} on:click={() => changeSection("history")}
class="p-2 px-5 cursor-pointer {displaySection === class="p-2 px-5 cursor-pointer {displaySection ===
'history' 'history'
@ -940,7 +917,7 @@
<!--End Login Modal--> <!--End Login Modal-->
<!--Start SellTrade Modal--> <!--Start SellTrade Modal-->
<PriceAlert {data} ticker={$indexTicker} assetType="etf" /> <PriceAlert {data} ticker={$indexTicker} assetType="index" />
<!--Start Add Watchlist Modal--> <!--Start Add Watchlist Modal-->
<input type="checkbox" id="addWatchListModal" class="modal-toggle" /> <input type="checkbox" id="addWatchListModal" class="modal-toggle" />

View File

@ -965,20 +965,7 @@
></tr ></tr
> >
<tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
><td
class="whitespace-nowrap px-0.5 py-[1px] xs:px-1 sm:py-2 text-sm sm:text-[1rem]"
>Day's Range</td
>
<td
class="whitespace-nowrap px-0.5 py-[1px] text-left text-sm font-semibold xs:px-1 sm:py-2 sm:text-right sm:text-[1rem]"
>{data?.getStockQuote?.dayLow?.toFixed(2)} - {data?.getStockQuote?.dayHigh?.toFixed(
2,
)}</td
></tr
>
<tr <tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0" class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
><td ><td
@ -1002,6 +989,20 @@
>{data?.getStockQuote?.priceAvg50?.toFixed(2)}</td >{data?.getStockQuote?.priceAvg50?.toFixed(2)}</td
></tr ></tr
> >
<tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
><td
class="whitespace-nowrap px-0.5 py-[1px] xs:px-1 sm:py-2 text-sm sm:text-[1rem]"
>Day's Range</td
>
<td
class="whitespace-nowrap px-0.5 py-[1px] text-left text-sm font-semibold xs:px-1 sm:py-2 sm:text-right sm:text-[1rem]"
>{data?.getStockQuote?.dayLow?.toFixed(2)} - {data?.getStockQuote?.dayHigh?.toFixed(
2,
)}</td
></tr
>
</tbody> </tbody>
</table> </table>
@ -1046,19 +1047,7 @@
></tr ></tr
> >
<tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
><td
class="whitespace-nowrap px-0.5 py-[1px] xs:px-1 sm:py-2 text-sm sm:text-[1rem]"
>52-Week Range</td
>
<td
class="whitespace-nowrap px-0.5 py-[1px] text-left text-sm font-semibold xs:px-1 sm:py-2 sm:text-right sm:text-[1rem]"
>{data?.getStockQuote?.yearLow?.toFixed(2)} - {data?.getStockQuote?.yearHigh?.toFixed(
2,
)}</td
></tr
>
<tr <tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0" class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
@ -1086,6 +1075,20 @@
></tr ></tr
> >
<tr
class="flex flex-col border-b border-gray-600 py-1 sm:table-row sm:py-0"
><td
class="whitespace-nowrap px-0.5 py-[1px] xs:px-1 sm:py-2 text-sm sm:text-[1rem]"
>52-Week Range</td
>
<td
class="whitespace-nowrap px-0.5 py-[1px] text-left text-sm font-semibold xs:px-1 sm:py-2 sm:text-right sm:text-[1rem]"
>{data?.getStockQuote?.yearLow?.toFixed(2)} - {data?.getStockQuote?.yearHigh?.toFixed(
2,
)}</td
></tr
>
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import { import {
etfTicker, indexTicker,
numberOfUnreadNotification,
displayCompanyName, displayCompanyName,
} from "$lib/store"; } from "$lib/store";
import TableHeader from "$lib/components/Table/TableHeader.svelte"; import TableHeader from "$lib/components/Table/TableHeader.svelte";
@ -10,6 +9,7 @@
import { Button } from "$lib/components/shadcn/button/index.js"; import { Button } from "$lib/components/shadcn/button/index.js";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import ArrowLogo from "lucide-svelte/icons/move-up-right"; import ArrowLogo from "lucide-svelte/icons/move-up-right";
import SEO from "$lib/components/SEO.svelte";
import { onMount } from "svelte"; import { onMount } from "svelte";
@ -252,7 +252,7 @@
const a = document.createElement("a"); const a = document.createElement("a");
a.setAttribute("hidden", ""); a.setAttribute("hidden", "");
a.setAttribute("href", url); a.setAttribute("href", url);
a.setAttribute("download", `${$etfTicker}_price_history.csv`); a.setAttribute("download", `${$indexTicker}_price_history.csv`);
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
document.body.removeChild(a); document.body.removeChild(a);
@ -272,42 +272,10 @@
} }
</script> </script>
<svelte:head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""}
{$displayCompanyName} ({$etfTicker}) Historical Stock Price Data · Stocknear
</title>
<meta
name="description"
content={`Get a complete stock price history for ${$etfTicker}, starting from its first trading day. Includes open, high, low, close and volume.`}
/>
<!-- Other meta tags --> <SEO title={`${$displayCompanyName} (${$indexTicker}) Historical Stock Price Data`} description={`Get a complete stock price history for ${$displayCompanyName} (${$indexTicker}), starting from its first trading day. Includes open, high, low, close and volume.`} />
<meta
property="og:title"
content={`${$displayCompanyName} (${$etfTicker}) Historical Stock Price Data · Stocknear`}
/>
<meta
property="og:description"
content={`Get a complete stock price history for NVIDIA, starting from its first trading day. Includes open, high, low, close and volume.`}
/>
<meta property="og:type" content="website" />
<!-- Add more Open Graph meta tags as needed -->
<!-- Twitter specific meta tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content={`${$displayCompanyName} (${$etfTicker}) Historical Stock Price Data · Stocknear`}
/>
<meta
name="twitter:description"
content={`Get a complete stock price history for NVIDIA, starting from its first trading day. Includes open, high, low, close and volume.`}
/>
<!-- Add more Twitter meta tags as needed -->
</svelte:head>
<section <section
class="bg-default overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-2 sm:mt-0" class="bg-default overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-2 sm:mt-0"
@ -323,7 +291,7 @@
class="flex flex-col sm:flex-row items-start w-full sm:justify-between md:space-x-4 md:border-0 w-full mb-5" class="flex flex-col sm:flex-row items-start w-full sm:justify-between md:space-x-4 md:border-0 w-full mb-5"
> >
<h1 class="text-xl sm:text-2xl font-bold mb-3 sm:mb-0"> <h1 class="text-xl sm:text-2xl font-bold mb-3 sm:mb-0">
{$etfTicker} Stock Price History {$indexTicker} Stock Price History
</h1> </h1>
<div <div
class="flex flex-row items-center ml-auto w-fit mt-2 sm:mt-0" class="flex flex-row items-center ml-auto w-fit mt-2 sm:mt-0"

View File

@ -1,9 +1,14 @@
export const load = async ({ locals, params }) => { export const load = async ({ locals, params }) => {
const { apiKey, apiURL } = locals; const { apiKey, apiURL } = locals;
const getETFHoldings = async () => { const getETFHoldings = async () => {
const postData = {
ticker: params.tickerID, console.log(params.tickerID?.toLowerCase())
};
let postData = {ticker: params.tickerID,}
if (params.tickerID?.toLowerCase() === '^spx') {
postData['ticker'] = 'spy';
}
// make the POST request to the endpoint // make the POST request to the endpoint
const response = await fetch(apiURL + "/etf-holdings", { const response = await fetch(apiURL + "/etf-holdings", {

View File

@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { import {
etfTicker, indexTicker,
numberOfUnreadNotification,
displayCompanyName, displayCompanyName,
} from "$lib/store"; } from "$lib/store";
import { formatString } from "$lib/utils"; import { formatString } from "$lib/utils";
import Table from "$lib/components/Table/Table.svelte"; import Table from "$lib/components/Table/Table.svelte";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
import SEO from "$lib/components/SEO.svelte";
export let data; export let data;
let rawData = data?.getETFHoldings?.holdings || []; let rawData = data?.getETFHoldings?.holdings || [];
@ -57,42 +57,8 @@
let htmlOutput = generateStatementInfoHTML(); let htmlOutput = generateStatementInfoHTML();
</script> </script>
<svelte:head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""}
{$displayCompanyName} ({$etfTicker}) Holdings List · Stocknear
</title>
<meta
name="description"
content={`Get the Holdings List of ${$displayCompanyName} (${$etfTicker}).`}
/>
<!-- Other meta tags --> <SEO title={`${$displayCompanyName} (${$indexTicker}) Holdings List`} description={`Get the Holdings List of ${$displayCompanyName} (${$indexTicker}).`} />
<meta
property="og:title"
content={`${$displayCompanyName} (${$etfTicker}) Holdings List · Stocknear`}
/>
<meta
property="og:description"
content={`Get the Holdings List of ${$displayCompanyName} (${$etfTicker}).`}
/>
<meta property="og:type" content="website" />
<!-- Add more Open Graph meta tags as needed -->
<!-- Twitter specific meta tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content={`${$displayCompanyName} (${$etfTicker}) Holdings List · Stocknear`}
/>
<meta
name="twitter:description"
content={`Get the Holdings List of ${$displayCompanyName} (${$etfTicker}).`}
/>
<!-- Add more Twitter meta tags as needed -->
</svelte:head>
<section <section
class="bg-default overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-2 sm:mt-0" class="bg-default overflow-hidden text-white h-full min-h-screen mb-20 sm:mb-0 w-full mt-2 sm:mt-0"
@ -104,7 +70,7 @@
<div class="mt-5 sm:mt-0 sm:pl-7 sm:pb-7 sm:pt-7 w-full m-auto"> <div class="mt-5 sm:mt-0 sm:pl-7 sm:pb-7 sm:pt-7 w-full m-auto">
<div class="flex flex-row items-center md:space-x-4 md:border-0"> <div class="flex flex-row items-center md:space-x-4 md:border-0">
<h1 class=" text-xl sm:text-2xl font-bold"> <h1 class=" text-xl sm:text-2xl font-bold">
{$etfTicker} Holdings List {$indexTicker} Holdings List
</h1> </h1>
{#if data?.getETFHoldings?.lastUpdate} {#if data?.getETFHoldings?.lastUpdate}
<div <div

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker } from "$lib/store"; import { indexTicker } from "$lib/store";
import ArrowLogo from "lucide-svelte/icons/move-up-right"; import ArrowLogo from "lucide-svelte/icons/move-up-right";
import { page } from "$app/stores"; import { page } from "$app/stores";
@ -11,7 +11,6 @@
const subSectionMap = { const subSectionMap = {
overview: "/options", overview: "/options",
"hottest-contracts": "/options/hottest-contracts", "hottest-contracts": "/options/hottest-contracts",
"unusual-activity": "/options/unusual-activity",
volatility: "/options/volatility", volatility: "/options/volatility",
gex: "/options/gex", gex: "/options/gex",
dex: "/options/dex", dex: "/options/dex",
@ -20,10 +19,10 @@
if (state !== "overview" && subSectionMap[state]) { if (state !== "overview" && subSectionMap[state]) {
displaySubSection = state; displaySubSection = state;
//goto(`/etf/${$etfTicker}${subSectionMap[state]}`); //goto(`/index/${$indexTicker}${subSectionMap[state]}`);
} else { } else {
displaySubSection = state; displaySubSection = state;
//goto(`/etf/${$etfTicker}/statistics`); //goto(`/index/${$indexTicker}/statistics`);
} }
} }
@ -33,7 +32,6 @@
const sectionMap = { const sectionMap = {
overview: "overview", overview: "overview",
"hottest-contracts": "hottest-contracts", "hottest-contracts": "hottest-contracts",
"unusual-activity": "unusual-activity",
volatility: "volatility", volatility: "volatility",
gex: "gex", gex: "gex",
dex: "dex", dex: "dex",
@ -64,7 +62,7 @@
> >
<ul class="flex flex-row items-center w-full text-white"> <ul class="flex flex-row items-center w-full text-white">
<a <a
href={`/etf/${$etfTicker}/options`} href={`/index/${$indexTicker}/options`}
on:click={() => changeSubSection("overview")} on:click={() => changeSubSection("overview")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'overview' class="p-2 px-5 cursor-pointer {displaySubSection === 'overview'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -73,17 +71,7 @@
Overview Overview
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/unusual-activity`} href={`/index/${$indexTicker}/options/hottest-contracts`}
on:click={() => changeSubSection("unusual-activity")}
class="p-2 px-5 cursor-pointer {displaySubSection ===
'unusual-activity'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
: 'text-gray-400 sm:hover:text-white sm:hover:bg-primary sm:hover:bg-opacity-[0.95]'}"
>
Unusual Activity
</a>
<a
href={`/etf/${$etfTicker}/options/hottest-contracts`}
on:click={() => changeSubSection("hottest-contracts")} on:click={() => changeSubSection("hottest-contracts")}
class="p-2 px-5 cursor-pointer {displaySubSection === class="p-2 px-5 cursor-pointer {displaySubSection ===
'hottest-contracts' 'hottest-contracts'
@ -93,7 +81,7 @@
Hottest Contracts Hottest Contracts
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/volatility`} href={`/index/${$indexTicker}/options/volatility`}
on:click={() => changeSubSection("volatility")} on:click={() => changeSubSection("volatility")}
class="p-2 px-5 cursor-pointer {displaySubSection === class="p-2 px-5 cursor-pointer {displaySubSection ===
'volatility' 'volatility'
@ -103,7 +91,7 @@
Volatility Volatility
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/oi`} href={`/index/${$indexTicker}/options/oi`}
on:click={() => changeSubSection("oi")} on:click={() => changeSubSection("oi")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'oi' class="p-2 px-5 cursor-pointer {displaySubSection === 'oi'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -113,7 +101,7 @@
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/gex`} href={`/index/${$indexTicker}/options/gex`}
on:click={() => changeSubSection("gex")} on:click={() => changeSubSection("gex")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'gex' class="p-2 px-5 cursor-pointer {displaySubSection === 'gex'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -122,7 +110,7 @@
GEX GEX
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/dex`} href={`/index/${$indexTicker}/options/dex`}
on:click={() => changeSubSection("dex")} on:click={() => changeSubSection("dex")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'dex' class="p-2 px-5 cursor-pointer {displaySubSection === 'dex'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -142,7 +130,7 @@
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100" class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100"
> >
<a <a
href={`/options-flow?query=${$etfTicker}`} href={`/options-flow?query=${$indexTicker}`}
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0" class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
> >
<div class="w-full flex justify-between items-center p-3 mt-3"> <div class="w-full flex justify-between items-center p-3 mt-3">

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { displayCompanyName, screenWidth, etfTicker } from "$lib/store"; import { displayCompanyName, screenWidth, indexTicker } from "$lib/store";
import DailyStats from "$lib/components/Options/DailyStats.svelte"; import DailyStats from "$lib/components/Options/DailyStats.svelte";
import { Chart } from "svelte-echarts"; import { Chart } from "svelte-echarts";
import { abbreviateNumberWithColor, monthNames } from "$lib/utils"; import { abbreviateNumberWithColor, monthNames } from "$lib/utils";
@ -286,7 +286,7 @@
<SEO <SEO
title="Options Activity" title="Options Activity"
description={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$etfTicker}).`} description={`Detailed informaton of unusual options activity for ${$displayCompanyName} (${$indexTicker}).`}
/> />
<section class="w-full bg-default overflow-hidden text-white min-h-screen"> <section class="w-full bg-default overflow-hidden text-white min-h-screen">
@ -358,7 +358,7 @@
{#if optionList?.length !== 0} {#if optionList?.length !== 0}
<h3 class="text-xl sm:text-2xl text-white font-bold text-start"> <h3 class="text-xl sm:text-2xl text-white font-bold text-start">
Historical {$etfTicker} Data Historical {$indexTicker} Data
</h3> </h3>
<div class="flex justify-start items-center m-auto overflow-x-auto"> <div class="flex justify-start items-center m-auto overflow-x-auto">

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker } from "$lib/store"; import { indexTicker } from "$lib/store";
import { page } from "$app/stores"; import { page } from "$app/stores";
export let data; export let data;
@ -15,10 +15,8 @@
if (state !== "overview" && subSectionMap[state]) { if (state !== "overview" && subSectionMap[state]) {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}${subSectionMap[state]}`);
} else { } else {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}/statistics`);
} }
} }
@ -55,7 +53,7 @@
> >
<ul class="flex flex-row items-center w-full text-white"> <ul class="flex flex-row items-center w-full text-white">
<a <a
href={`/etf/${$etfTicker}/options/dex`} href={`/index/${$indexTicker}/options/dex`}
on:click={() => changeSubSection("overview")} on:click={() => changeSubSection("overview")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'overview' class="p-2 px-5 cursor-pointer {displaySubSection === 'overview'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -65,7 +63,7 @@
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/dex/strike`} href={`/index/${$indexTicker}/options/dex/strike`}
on:click={() => changeSubSection("strike")} on:click={() => changeSubSection("strike")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'strike' class="p-2 px-5 cursor-pointer {displaySubSection === 'strike'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -74,7 +72,7 @@
By Strike By Strike
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/dex/expiry`} href={`/index/${$indexTicker}/options/dex/expiry`}
on:click={() => changeSubSection("expiry")} on:click={() => changeSubSection("expiry")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry' class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
import GreekExposure from "$lib/components/Options/GreekExposure.svelte"; import GreekExposure from "$lib/components/Options/GreekExposure.svelte";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
@ -9,7 +9,7 @@
<SEO <SEO
title="Daily Gamma Exposure" title="Daily Gamma Exposure"
description={`Analyze daily gamma exposure for ${$displayCompanyName} (${$etfTicker}). Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`} description={`Analyze daily gamma exposure for ${$displayCompanyName} (${$indexTicker}). Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`}
/> />
<section <section

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
import GreekByExpiry from "$lib/components/Options/GreekByExpiry.svelte"; import GreekByExpiry from "$lib/components/Options/GreekByExpiry.svelte";
@ -11,7 +11,7 @@
<SEO <SEO
title="Delta Exposure By Expiry" title="Delta Exposure By Expiry"
description={`Analyze delta exposure for ${$displayCompanyName} (${$etfTicker}) by expiry. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`} description={`Analyze delta exposure for ${$displayCompanyName} (${$indexTicker}) by expiry. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`}
/> />
<section <section

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
@ -11,7 +11,7 @@
<SEO <SEO
title="Delta Exposure By Strike Price" title="Delta Exposure By Strike Price"
description={`Analyze delta exposure for ${$displayCompanyName} (${$etfTicker}) by strike price. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`} description={`Analyze delta exposure for ${$displayCompanyName} (${$indexTicker}) by strike price. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`}
/> />
<section <section

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker } from "$lib/store"; import { indexTicker } from "$lib/store";
import { page } from "$app/stores"; import { page } from "$app/stores";
export let data; export let data;
@ -15,10 +15,8 @@
if (state !== "overview" && subSectionMap[state]) { if (state !== "overview" && subSectionMap[state]) {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}${subSectionMap[state]}`);
} else { } else {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}/statistics`);
} }
} }
@ -55,7 +53,7 @@
> >
<ul class="flex flex-row items-center w-full text-white"> <ul class="flex flex-row items-center w-full text-white">
<a <a
href={`/etf/${$etfTicker}/options/gex`} href={`/index/${$indexTicker}/options/gex`}
on:click={() => changeSubSection("overview")} on:click={() => changeSubSection("overview")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'overview' class="p-2 px-5 cursor-pointer {displaySubSection === 'overview'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -65,7 +63,7 @@
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/gex/strike`} href={`/index/${$indexTicker}/options/gex/strike`}
on:click={() => changeSubSection("strike")} on:click={() => changeSubSection("strike")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'strike' class="p-2 px-5 cursor-pointer {displaySubSection === 'strike'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -74,7 +72,7 @@
By Strike By Strike
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/gex/expiry`} href={`/index/${$indexTicker}/options/gex/expiry`}
on:click={() => changeSubSection("expiry")} on:click={() => changeSubSection("expiry")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry' class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
@ -11,7 +11,7 @@
<SEO <SEO
title="Gamma Exposure By Expiry" title="Gamma Exposure By Expiry"
description={`Analyze gamma exposure for ${$displayCompanyName} (${$etfTicker}) by expiry. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`} description={`Analyze gamma exposure for ${$displayCompanyName} (${$indexTicker}) by expiry. Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`}
/> />
<section <section

View File

@ -7,7 +7,7 @@
import { import {
setCache, setCache,
getCache, getCache,
etfTicker, indexTicker,
screenWidth, screenWidth,
displayCompanyName, displayCompanyName,
} from "$lib/store"; } from "$lib/store";
@ -479,7 +479,7 @@
output = cachedData; output = cachedData;
} else { } else {
const postData = { const postData = {
ticker: $etfTicker, ticker: $indexTicker,
contract: contractId, contract: contractId,
}; };
@ -551,8 +551,8 @@
</script> </script>
<SEO <SEO
title={`${$displayCompanyName} (${$etfTicker}) - Explore the Hottest Options Contracts | Stocknear`} title={`${$displayCompanyName} (${$indexTicker}) - Explore the Hottest Options Contracts | Stocknear`}
description={`Analyze historical volume, open interest, and trends in option chains for ${$displayCompanyName} (${$etfTicker}). Discover actionable insights for trading decisions.`} description={`Analyze historical volume, open interest, and trends in option chains for ${$displayCompanyName} (${$indexTicker}). Discover actionable insights for trading decisions.`}
/> />
<section <section
@ -828,7 +828,7 @@
<p class="text-white text-[1rem] sm:text-xl font-semibold cursor-text"> <p class="text-white text-[1rem] sm:text-xl font-semibold cursor-text">
Contract: <span Contract: <span
class={optionType === "C" ? "text-[#00FC50]" : "text-[#FF2F1F]"} class={optionType === "C" ? "text-[#00FC50]" : "text-[#FF2F1F]"}
>{$etfTicker} >{$indexTicker}
{strikePrice} {strikePrice}
{optionType} {optionType}
{dateExpiration} ({daysLeft(dateExpiration)}) {dateExpiration} ({daysLeft(dateExpiration)})

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker } from "$lib/store"; import { indexTicker } from "$lib/store";
import { page } from "$app/stores"; import { page } from "$app/stores";
export let data; export let data;
@ -14,10 +14,8 @@
if (state !== "overview" && subSectionMap[state]) { if (state !== "overview" && subSectionMap[state]) {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}${subSectionMap[state]}`);
} else { } else {
displaySubSection = state; displaySubSection = state;
//goto(`/stocks/${$etfTicker}/statistics`);
} }
} }
@ -53,7 +51,7 @@
> >
<ul class="flex flex-row items-center w-full text-white"> <ul class="flex flex-row items-center w-full text-white">
<a <a
href={`/etf/${$etfTicker}/options/oi`} href={`/index/${$indexTicker}/options/oi`}
on:click={() => changeSubSection("strike")} on:click={() => changeSubSection("strike")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'strike' class="p-2 px-5 cursor-pointer {displaySubSection === 'strike'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'
@ -63,7 +61,7 @@
</a> </a>
<a <a
href={`/etf/${$etfTicker}/options/oi/expiry`} href={`/index/${$indexTicker}/options/oi/expiry`}
on:click={() => changeSubSection("expiry")} on:click={() => changeSubSection("expiry")}
class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry' class="p-2 px-5 cursor-pointer {displaySubSection === 'expiry'
? 'text-white bg-primary sm:hover:bg-opacity-[0.95]' ? 'text-white bg-primary sm:hover:bg-opacity-[0.95]'

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
@ -11,7 +11,7 @@
<SEO <SEO
title="Open Interest by Expiry" title="Open Interest by Expiry"
description={`Analyze Gamma Exposure by expiry for ${$displayCompanyName} (${$etfTicker}). Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`} description={`Analyze Gamma Exposure by expiry for ${$displayCompanyName} (${$indexTicker}). Access historical volume, open interest trends, and save options contracts for detailed analysis and insights.`}
/> />
<section <section

View File

@ -1,49 +0,0 @@
export const load = async ({ locals, params }) => {
const { apiKey, apiURL, user } = locals;
const getData = async () => {
const postData = {
ticker: params.tickerID,
};
const response = await fetch(apiURL + "/unusual-activity", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey,
},
body: JSON.stringify(postData),
});
let output = await response.json();
return output;
};
const getHistoricalPrice = async () => {
const postData = { ticker: params.tickerID, timePeriod: "max" };
const response = await fetch(apiURL + "/historical-price", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey,
},
body: JSON.stringify(postData),
});
const output = await response.json();
return output;
};
// Make sure to return a promise
return {
getData: await getData(),
getHistoricalPrice: await getHistoricalPrice(),
};
};

View File

@ -1,37 +0,0 @@
<script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store";
import Infobox from "$lib/components/Infobox.svelte";
import SEO from "$lib/components/SEO.svelte";
import UnusualActivity from "$lib/components/Options/UnusualActivity.svelte";
export let data;
</script>
<SEO
title={`${$displayCompanyName} (${$etfTicker}) - Explore Unusual Option Activity | Stocknear`}
description={`Analyze historical unusual option trades with a minimum of 1 million dollar premium for ${$displayCompanyName} (${$etfTicker}).`}
/>
<section
class="w-full bg-default overflow-hidden text-white min-h-screen pb-40"
>
<div class="w-full flex h-full overflow-hidden">
<div
class="w-full relative flex justify-center items-center overflow-hidden"
>
{#if data?.getData?.length > 0}
<UnusualActivity {data} ticker={$etfTicker} />
{:else}
<div class="sm:pl-7 sm:pb-7 sm:pt-7 w-full m-auto mt-2 sm:mt-0">
<div class="mt-2">
<Infobox
text="No unusual options trading activity with a premium of at least $1 million was found."
/>
</div>
</div>
{/if}
</div>
</div>
</section>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { etfTicker, displayCompanyName } from "$lib/store"; import { indexTicker, displayCompanyName } from "$lib/store";
import Infobox from "$lib/components/Infobox.svelte"; import Infobox from "$lib/components/Infobox.svelte";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
@ -10,7 +10,7 @@
</script> </script>
<SEO <SEO
title={`${$displayCompanyName} (${$etfTicker}) Volatility · Stocknear`} title={`${$displayCompanyName} (${$indexTicker}) Volatility · Stocknear`}
description={`Track volatility and implied volatility trends with our interactive chart. Analyze price movements, 30-day implied volatility, and realized volatility to make data-driven trading decisions.`} description={`Track volatility and implied volatility trends with our interactive chart. Analyze price movements, 30-day implied volatility, and realized volatility to make data-driven trading decisions.`}
/> />

View File

@ -389,9 +389,7 @@
class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2" class="flex-1 flex-shrink-0 flex flex-row items-center justify-between -mt-2"
> >
<a <a
href={/^\/(stocks|etf)/.test($previousPage) href={/^\/(stocks|etf|index)/.test($previousPage || "") ? "/" : $previousPage || "/"}
? "/"
: $previousPage || "/"}
> >
<svg <svg
class="w-5 h-5 inline-block" class="w-5 h-5 inline-block"