+page.svelte 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <script>
  2. import CurrentPositionChart from '../../components/CurrentPositionChart.svelte';
  3. import { onMount } from 'svelte';
  4. import { authentication } from '../store.js';
  5. import { fade } from 'svelte/transition';
  6. import { goto } from '$app/navigation';
  7. import { getRequest } from '../../utils/api.js';
  8. import MarketDistributionChart from '../../components/MarketDistributionChart.svelte';
  9. let authToken;
  10. let data = {};
  11. let isLoading = true;
  12. let currency;
  13. let total = 0;
  14. let chartView = 'positions';
  15. onMount(() => {
  16. return authentication.subscribe(async (auth) => {
  17. if (new Date(auth?.expirationDate) < new Date()) {
  18. await goto('/logout');
  19. }
  20. if (!auth || !auth.token) {
  21. await goto('/logout');
  22. } else {
  23. const defaultCurrency = localStorage.getItem('defaultCurrency');
  24. currency = defaultCurrency || 'USD';
  25. authToken = auth.token;
  26. await fetchPortfolio(currency);
  27. }
  28. });
  29. });
  30. async function fetchPortfolio(currency) {
  31. try {
  32. const response = await getRequest(
  33. `${import.meta.env.VITE_STOCKS_HOST}/api/portfolios?currency=${currency}`,
  34. {},
  35. authToken
  36. );
  37. if (response.ok) {
  38. const portfolio = await response.json();
  39. if (portfolio?.length) {
  40. data = {
  41. ...portfolio[0],
  42. stocks: [...portfolio[0].stocks].sort((a, b) => a.total - b.total)
  43. };
  44. total = portfolio[0].totalValue;
  45. } else {
  46. data = {};
  47. total = 0;
  48. }
  49. } else {
  50. const error = await response.json();
  51. console.error('Failed to find portfolio info:', error);
  52. data = {};
  53. total = 0;
  54. }
  55. } catch (error) {
  56. console.error('Failed to fetch insights:', error);
  57. await goto('/logout');
  58. } finally {
  59. isLoading = false;
  60. }
  61. }
  62. function updateCurrency(event) {
  63. currency = event.target.value;
  64. isLoading = true;
  65. fetchPortfolio(currency);
  66. }
  67. </script>
  68. <svelte:head>
  69. <title>Insights</title>
  70. <meta name="description" content="Insights" />
  71. </svelte:head>
  72. {#if isLoading}
  73. <div in:fade class="text-center py-6 text-gray-500 dark:text-gray-300">Loading...</div>
  74. {:else}
  75. <div in:fade class="space-y-6">
  76. <div class="flex justify-end mb-4">
  77. <select
  78. class="w-52 px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-400"
  79. on:change={updateCurrency}
  80. bind:value={currency}
  81. >
  82. <option value="BRL">BRL</option>
  83. <option value="EUR">EUR</option>
  84. <option value="USD">USD</option>
  85. </select>
  86. </div>
  87. <!-- Chart View Selector -->
  88. <div class="flex justify-center gap-4 mb-4">
  89. <button
  90. class="px-4 py-2 rounded-md text-sm font-medium transition
  91. {chartView === 'positions'
  92. ? 'bg-blue-500 text-white'
  93. : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-100'}"
  94. on:click={() => chartView = 'positions'}
  95. >
  96. By Position
  97. </button>
  98. <button
  99. class="px-4 py-2 rounded-md text-sm font-medium transition
  100. {chartView === 'markets'
  101. ? 'bg-blue-500 text-white'
  102. : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-100'}"
  103. on:click={() => chartView = 'markets'}
  104. >
  105. By Market
  106. </button>
  107. </div>
  108. <!-- Chart Display -->
  109. {#if chartView === 'positions'}
  110. <CurrentPositionChart {data} {currency} {total} />
  111. {:else if chartView === 'markets'}
  112. <MarketDistributionChart {data} {currency} {total} />
  113. {/if}
  114. </div>
  115. {/if}