|
@@ -2,6 +2,7 @@
|
|
|
import { onMount } from 'svelte';
|
|
import { onMount } from 'svelte';
|
|
|
import { Chart, registerables } from 'chart.js';
|
|
import { Chart, registerables } from 'chart.js';
|
|
|
import { getRequest } from '../utils/api.js';
|
|
import { getRequest } from '../utils/api.js';
|
|
|
|
|
+ import { fade } from 'svelte/transition';
|
|
|
|
|
|
|
|
Chart.register(...registerables);
|
|
Chart.register(...registerables);
|
|
|
|
|
|
|
@@ -9,7 +10,8 @@
|
|
|
|
|
|
|
|
let chartCanvas;
|
|
let chartCanvas;
|
|
|
let chartInstance;
|
|
let chartInstance;
|
|
|
- let selectedRange = '5d'; // default range
|
|
|
|
|
|
|
+ let selectedRange = '5d';
|
|
|
|
|
+ let isLoading = true;
|
|
|
|
|
|
|
|
const ranges = ['5d', '30d', '6m', '1y'];
|
|
const ranges = ['5d', '30d', '6m', '1y'];
|
|
|
|
|
|
|
@@ -25,6 +27,8 @@
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
console.error('Error fetching stock history:', err);
|
|
console.error('Error fetching stock history:', err);
|
|
|
return [];
|
|
return [];
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ isLoading = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -93,22 +97,36 @@
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
|
|
+{#if isLoading}
|
|
|
|
|
+ <div in:fade class="flex justify-center items-center py-10">
|
|
|
|
|
+ <svg
|
|
|
|
|
+ class="animate-spin h-8 w-8 text-blue-500 dark:text-blue-300"
|
|
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
+ fill="none"
|
|
|
|
|
+ viewBox="0 0 24 24"
|
|
|
|
|
+ >
|
|
|
|
|
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
|
|
|
|
+ ></circle>
|
|
|
|
|
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"></path>
|
|
|
|
|
+ </svg>
|
|
|
|
|
+ </div>
|
|
|
|
|
+{:else}
|
|
|
|
|
+ <div class="w-full mt-10 max-w-6xl mx-auto bg-white dark:bg-gray-900 p-6 rounded-xl shadow-md">
|
|
|
|
|
+ <h3 class="text-xl font-semibold text-gray-800 dark:text-gray-100 mb-4">Price History</h3>
|
|
|
|
|
+ <canvas bind:this={chartCanvas}></canvas>
|
|
|
|
|
|
|
|
-<div class="w-full mt-10 max-w-6xl mx-auto bg-white dark:bg-gray-900 p-6 rounded-xl shadow-md">
|
|
|
|
|
- <h3 class="text-xl font-semibold text-gray-800 dark:text-gray-100 mb-4">Price History</h3>
|
|
|
|
|
- <canvas bind:this={chartCanvas}></canvas>
|
|
|
|
|
-
|
|
|
|
|
- <div class="flex justify-center gap-4 mt-6">
|
|
|
|
|
- {#each ranges as range}
|
|
|
|
|
- <button
|
|
|
|
|
- class="px-4 py-2 rounded-md text-sm font-medium transition cursor-pointer
|
|
|
|
|
|
|
+ <div class="flex justify-center gap-4 mt-6">
|
|
|
|
|
+ {#each ranges as range}
|
|
|
|
|
+ <button
|
|
|
|
|
+ class="px-4 py-2 rounded-md text-sm font-medium transition cursor-pointer
|
|
|
{selectedRange === range
|
|
{selectedRange === range
|
|
|
? 'bg-blue-500 text-white'
|
|
? 'bg-blue-500 text-white'
|
|
|
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-100'}"
|
|
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-100'}"
|
|
|
- on:click={() => updateChart(range)}
|
|
|
|
|
- >
|
|
|
|
|
- {range.toUpperCase()}
|
|
|
|
|
- </button>
|
|
|
|
|
- {/each}
|
|
|
|
|
|
|
+ on:click={() => updateChart(range)}
|
|
|
|
|
+ >
|
|
|
|
|
+ {range.toUpperCase()}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ {/each}
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
-</div>
|
|
|
|
|
|
|
+{/if}
|