BuyPanel.svelte 5.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <script>
  2. import { createEventDispatcher } from 'svelte';
  3. export let referencePrice;
  4. export let tokens = [];
  5. const dispatch = createEventDispatcher();
  6. let tab = 'market';
  7. let amountFiat = '';
  8. let limitPrice = '';
  9. let selectedTokenId = tokens?.[0]?.id ?? null;
  10. function formatBRL(n) {
  11. return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(Number(n || 0));
  12. }
  13. function formatEasyToken(n) {
  14. return new Intl.NumberFormat('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(Math.floor(Number(n || 0)));
  15. }
  16. $: selectedToken = tokens.find(t => t.id === selectedTokenId);
  17. $: refPriceByToken = selectedToken?.price ?? referencePrice;
  18. $: priceUsed = tab === 'limit' ? Number(limitPrice) : Number(refPriceByToken);
  19. $: computedEasyTokenRaw = (Number(amountFiat) && priceUsed) ? Number(amountFiat) / priceUsed : 0;
  20. $: computedEasyToken = Math.floor(computedEasyTokenRaw);
  21. function confirm() {
  22. const price = priceUsed;
  23. const total = Number(amountFiat);
  24. if (!price || !total) return;
  25. const amount = computedEasyToken;
  26. if (!amount) return;
  27. dispatch('confirm', { type: tab, price, amount, total, tokenId: selectedToken?.id });
  28. amountFiat = '';
  29. limitPrice = '';
  30. }
  31. </script>
  32. <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
  33. <div class="px-5 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
  34. <h3 class="text-base font-semibold text-gray-800 dark:text-gray-100">Comprar</h3>
  35. <div class="inline-flex rounded-md border border-gray-200 dark:border-gray-600 overflow-hidden">
  36. <button class={`px-3 py-1.5 text-sm ${tab === 'market' ? 'bg-green-600 text-white' : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300'}`} on:click={() => (tab = 'market')}>Mercado</button>
  37. <button class={`px-3 py-1.5 text-sm border-l border-gray-200 dark:border-gray-600 ${tab === 'limit' ? 'bg-green-600 text-white' : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300'}`} on:click={() => (tab = 'limit')}>Limitada</button>
  38. </div>
  39. </div>
  40. <div class="p-5 space-y-4">
  41. <div>
  42. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Tipo de EasyToken</label>
  43. <select bind:value={selectedTokenId} class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
  44. {#each tokens as t}
  45. <option value={t.id}>{t.label || t.name}</option>
  46. {/each}
  47. </select>
  48. </div>
  49. {#if tab === 'limit'}
  50. <div>
  51. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Preço limite (R$)</label>
  52. <input type="number" min="0" step="0.01" bind:value={limitPrice} class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" />
  53. </div>
  54. {/if}
  55. <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
  56. <div>
  57. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">EasyCoin (R$)</label>
  58. <input type="number" min="0" step="0.01" bind:value={amountFiat} class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" />
  59. </div>
  60. <div>
  61. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">EasyToken (inteiros)</label>
  62. <input value={formatEasyToken(computedEasyToken || 0)} readonly class="mt-1 block w-full rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/40 text-gray-900 dark:text-gray-200 px-3 py-2" />
  63. </div>
  64. </div>
  65. <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
  66. <div>
  67. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">EasyToken a receber</label>
  68. <input value={formatEasyToken(computedEasyToken || 0)} readonly class="mt-1 block w-full rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/40 text-gray-900 dark:text-gray-200 px-3 py-2" />
  69. </div>
  70. <div>
  71. <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Preço de referência</label>
  72. <input value={refPriceByToken ? formatBRL(refPriceByToken) : '—'} readonly class="mt-1 block w-full rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/40 text-gray-900 dark:text-gray-200 px-3 py-2" />
  73. </div>
  74. </div>
  75. <div class="flex justify-end">
  76. <button class="px-4 py-2 rounded bg-green-600 hover:bg-green-700 text-white focus:outline-none focus:ring-2 focus:ring-green-500" on:click={confirm}>Confirmar</button>
  77. </div>
  78. </div>
  79. </div>