This commit is contained in:
MuslemRahimi 2025-02-24 19:43:27 +01:00
parent 2dfad5dd84
commit d001f2dac1

View File

@ -4,11 +4,13 @@
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
import { setCache, getCache } from "$lib/store"; import { setCache, getCache } from "$lib/store";
import { onDestroy } from "svelte"; import { onDestroy } from "svelte";
import toast from "svelte-french-toast";
export let data; export let data;
let isLoaded = false;
let rawData = data?.getData; let rawData = data?.getData;
let iframe: HTMLIFrameElement; let iframe: HTMLIFrameElement;
let iframeLoaded = false;
let selectedFormat: "png" | "jpeg" | "svg" = "png"; let selectedFormat: "png" | "jpeg" | "svg" = "png";
let selectedTimePeriod = "1D"; let selectedTimePeriod = "1D";
let iframeUrl: string; let iframeUrl: string;
@ -36,47 +38,51 @@
} }
async function downloadPlot(item) { async function downloadPlot(item) {
if (item === "PNG") { return toast.promise(
selectedFormat = "png"; (async () => {
} else if (item === "JPG") { let selectedFormat;
selectedFormat = "jpeg";
} else {
selectedFormat = "svg";
}
if (!iframe || !iframeLoaded) return; if (item === "PNG") {
selectedFormat = "png";
} else if (item === "JPG") {
selectedFormat = "jpeg";
} else {
selectedFormat = "svg";
}
try { if (!iframe || !isLoaded) throw new Error("Iframe not ready");
const iframeWindow = iframe.contentWindow;
if (!iframeWindow) return;
const Plotly = (iframeWindow as any).Plotly; const iframeWindow = iframe.contentWindow;
if (!Plotly) throw new Error("Plotly not found in iframe"); if (!iframeWindow) throw new Error("Iframe window not available");
const plotDiv = const Plotly = iframeWindow.Plotly;
iframe.contentDocument?.querySelector(".plotly-graph-div"); if (!Plotly) throw new Error("Plotly not found in iframe");
if (!plotDiv) throw new Error("Plotly div not found");
// Configure image options based on format const plotDiv =
const options = { iframe.contentDocument?.querySelector(".plotly-graph-div");
format: selectedFormat, if (!plotDiv) throw new Error("Plotly div not found");
width: 1200,
height: 800,
};
// Get image data URL const options = {
const imageData = await Plotly.toImage(plotDiv, options); format: selectedFormat,
width: 1200,
height: 800,
};
// Create download link const imageData = await Plotly.toImage(plotDiv, options);
const link = document.createElement("a");
link.href = imageData; const link = document.createElement("a");
link.download = `sp500-heatmap-${selectedTimePeriod}`; link.href = imageData;
document.body.appendChild(link); link.download = `sp500-heatmap-${selectedTimePeriod}`;
link.click(); document.body.appendChild(link);
document.body.removeChild(link); link.click();
} catch (error) { document.body.removeChild(link);
console.error("Download failed:", error); })(),
} {
loading: "Downloading heatmap...",
success: "Heatmap downloaded!",
error: "Download failed. Try again.",
},
);
} }
onDestroy(() => { onDestroy(() => {
@ -86,16 +92,14 @@
$: { $: {
if (selectedTimePeriod && typeof window !== "undefined") { if (selectedTimePeriod && typeof window !== "undefined") {
(async () => { (async () => {
await getHeatMap(); isLoaded = false;
getHeatMap();
isLoaded = true;
})(); })();
} }
} }
</script> </script>
<svelte:head>
<script src="https://cdn.plot.ly/plotly-2.18.0.min.js" defer></script>
</svelte:head>
<SEO <SEO
title="S&P 500 Stock Market Heatmap" title="S&P 500 Stock Market Heatmap"
description="A stock market heatmap showing the performance of the individual stocks, sectors and industries in the S&P500." description="A stock market heatmap showing the performance of the individual stocks, sectors and industries in the S&P500."
@ -212,7 +216,7 @@
<div class="flex items-center"> <div class="flex items-center">
<button <button
on:click={() => downloadPlot(item)} on:click={() => downloadPlot(item)}
disabled={!iframeLoaded} disabled={!isLoaded}
class="cursor-pointer text-white" class="cursor-pointer text-white"
> >
<span class="mr-8">Download {item}</span> <span class="mr-8">Download {item}</span>
@ -226,13 +230,26 @@
</div> </div>
</div> </div>
<div class="w-full min-h-screen bg-[#09090B] overflow-hidden"> <div class="w-full min-h-screen bg-[#09090B] overflow-hidden">
{#if rawData} {#if isLoaded}
<iframe {#if rawData}
bind:this={iframe} <iframe
src={iframeUrl} bind:this={iframe}
class="w-full h-screen border-none" src={iframeUrl}
on:load={() => (iframeLoaded = true)} class="w-full h-screen border-none"
/> />
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span
class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if} {/if}
</div> </div>
</main> </main>