frontend/src/lib/components/SellTrade.svelte
2024-09-19 22:52:02 +02:00

492 lines
20 KiB
Svelte

<script lang='ts'>
import toast from 'svelte-french-toast';
import {currentPortfolioPrice, displayCompanyName, screenWidth, traded, stockTicker, etfTicker, cryptoTicker, assetType} from '$lib/store';
export let data;
export let availableCash;
export let holdingShares;
let fastifyURL = import.meta.env.VITE_USEAST_FASTIFY_URL;
let estimatedTotal = 0;
let numberOfShares = 0;
let commissionPrice = 0;
let displayTab = 'changeOrder';
function handleMaxOrder()
{
numberOfShares = holdingShares;
estimatedTotal = (numberOfShares * $currentPortfolioPrice);
}
function handleInputChange(event) {
const inputValue = event.target.value;
if (!isNaN(inputValue) && Number(inputValue) >= 0) {
numberOfShares = Number(inputValue);
} else {
numberOfShares = 0;
}
estimatedTotal = numberOfShares * $currentPortfolioPrice;
}
function handleAppendNumber(num) {
// Append the clicked number to the current numberOfShares
numberOfShares = numberOfShares * 10 + num;
}
function handleRemoveNumber() {
// Remove the last digit from numberOfShares or set to zero if NaN
const numStr = numberOfShares.toString();
numberOfShares = numStr.length > 1 ? parseInt(numStr.slice(0, -1), 10) : 0;
}
function changeTab() {
if(displayTab === 'changeOrder' && numberOfShares > 0 && numberOfShares <= holdingShares)
{
displayTab = 'sellOrder';
}
else if (displayTab === 'sellOrder')
{
displayTab = 'changeOrder';
}
else {
toast.error('Please check your Input values again.', {
style: 'border-radius: 200px; background: #333; color: #fff;'
});
}
}
async function handleSellOrder()
{
const postData = {
'userId': data?.user?.id,
'symbol': $assetType === 'stock' ? $stockTicker : $assetType === 'etf' ? $etfTicker : $cryptoTicker,
'assetType': $assetType,
'name': $displayCompanyName,
'numberOfShares': numberOfShares,
'estimatedTotal': estimatedTotal,
'soldPrice': $currentPortfolioPrice,
}
// Make the POST request to the endpoint
const response = await fetch(fastifyURL+'/sell-stock', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(postData)
});
const output = (await response.json())?.message;
if (output === 'success')
{
toast.success(`Successfully sold ${numberOfShares} ${$stockTicker} shares`, {
style: 'border-radius: 200px; background: #333; color: #fff;'
});
numberOfShares = 0;
estimatedTotal = 0;
displayTab = 'changeOrder';
$traded = true;
const closePopup = document.getElementById("sellTradeModal");
closePopup?.dispatchEvent(new MouseEvent('click'))
}
else if (output === 'failure')
{
toast.error(`Something went wrong. Please try again.`, {
style: 'border-radius: 200px; background: #333; color: #fff;'
});
}
else if (output === 'marketClosed')
{
toast.error(`The market is closed. Please try again later.`, {
style: 'border-radius: 200px; background: #333; color: #fff;'
});
}
}
$: {
if(numberOfShares)
{
estimatedTotal = (numberOfShares * $currentPortfolioPrice);
}
}
</script>
<svelte:head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
</svelte:head>
{#if $screenWidth >=640}
<!--Start Trade Modal-->
<input type="checkbox" id="sellTradeModal" class="modal-toggle" />
<dialog id="sellTradeModal" class="modal modal-bottom sm:modal-middle">
<label for="sellTradeModal" class="cursor-pointer modal-backdrop bg-[#fff] bg-opacity-[0.08]"></label>
<div class="modal-box w-full bg-[#000] border border-slate-600 h-[500px]" >
<!--Start Trade Modal-->
<div class="flex flex-col w-full">
{#if displayTab === 'changeOrder'}
<div class="text-white text-md flex flex-col flex-shrink-0">
<div class="rounded-full w-10 h-10 relative bg-gray-900 mb-2">
<img class="rounded-full w-6 h-6 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2" src={`https://financialmodelingprep.com/image-stock/${$assetType === 'stock' ? $stockTicker : $assetType === 'etf' ? $etfTicker : $cryptoTicker}.png`} />
</div>
<span class="mb-1">
{$displayCompanyName?.length > 30 ? $displayCompanyName?.slice(0, 30) + "..." : $displayCompanyName}
</span>
<span class="mb-1 text-sm font-medium">
Current Price: ${$currentPortfolioPrice}
</span>
</div>
<div class="flex justify-between items-center mt-2">
<div class="flex flex-col sm:w-64">
<label class="label font-medium">
<span class="text-white label-text">Number of Shares</span>
</label>
<input bind:value={numberOfShares} on:input={handleInputChange} type="text" placeholder="Number of Shares" class="text-slate-200 input {numberOfShares > holdingShares ? 'input-error' : ''} bg-gray-900 input-md w-54 sm:w-full max-w-xs" />
</div>
<label on:click={handleMaxOrder} class="mt-9 btn bg-[#000] hover:bg-[#fff] hover:text-black text-white cursor-pointer sm:px-5 border rounded-lg">
Show Max
</label>
</div>
<span class="{numberOfShares <= holdingShares ? 'hidden' : ''} label-text-alt text-error mt-1">
Not enough shares to sell the amount
</span>
<div class="flex justify-between items-center mt-8 w-full">
<div class="flex flex-col sm:flex-row text-blue-400 text-sm font-medium">
<span class="mr-0 sm:mr-1">
Holding Shares:
</span>
<span>
{holdingShares}
</span>
</div>
<div class="flex flex-col sm:flex-row text-blue-400 text-sm">
<span class="mr-0 sm:mr-1">
Estimated Total:
</span>
<span>
{estimatedTotal?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</span>
</div>
</div>
<div class="w-5/6 max-w-lg pt-10 m-auto pb-20">
<button on:click={changeTab} class="btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md w-full rounded-lg m-auto text-white font-bold text-md">
Preview Sell Order
</button>
</div>
{:else if displayTab === 'sellOrder'}
<label on:click={changeTab} class="{$screenWidth > 640 ? 'hidden' : ''} rounded-full left-0 -top-4 relative flex justify-center items-center w-10 h-10 hover:bg-gray-600 hover:bg-opacity-[0.4]">
<svg class="w-7 h-7" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g transform="rotate(-90 12 12)"><path fill="white" d="M13 7.828V20h-2V7.828l-5.364 5.364l-1.414-1.414L12 4l7.778 7.778l-1.414 1.414L13 7.828Z"/></g></svg>
</label>
<div class="text-white text-md flex flex-col flex-shrink-0">
<div class="rounded-full w-10 h-10 relative bg-gray-900 mb-2">
<img class="rounded-full w-6 h-6 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2" src={`https://financialmodelingprep.com/image-stock/${$assetType === 'stock' ? $stockTicker : $etfTicker}.png`} />
</div>
<span class="mb-1 font-medium text-xl">
Selling {numberOfShares} shares of {$displayCompanyName?.length > 30 ? $displayCompanyName?.slice(0, 30) + "..." : $displayCompanyName}
</span>
</div>
<table class="table table-sm table-compact mt-3 text-start flex justify-start items-center w-full px-3 m-auto">
<tbody>
<!-- row 1 -->
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Price per Share</td>
<td class="bg-[#000] whitespace-normal">${$currentPortfolioPrice}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Number of Shares</td>
<td class="bg-[#000] whitespace-normal">{numberOfShares}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Commission</td>
<td class="bg-[#000] whitespace-normal">${commissionPrice}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Estimated Total</td>
<td class="bg-[#000] whitespace-normal">{estimatedTotal?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Available Cash After</td>
<td class="bg-[#000] whitespace-normal">{(availableCash+estimatedTotal-commissionPrice)?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</td>
</tr>
</tbody>
</table>
<div class="max-w-lg pt-10 m-auto pb-5 flex flex-row justify-center items-center">
<button on:click={changeTab} class="w-3/4 mr-8 btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md rounded-lg text-white font-bold text-md">
Change Order
</button>
<button on:click={handleSellOrder} class="w-3/4 btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md rounded-lg text-white font-bold text-md">
Sell
</button>
</div>
{/if}
</div>
<!--End Trade Modal-->
</div>
</dialog>
{:else}
<!--Start Drawer Sidewise for mobile-->
<div class="drawer drawer-end z-40">
<input id="sellTradeModal" type="checkbox" class="drawer-toggle"/>
<div class="drawer-side">
<div class="modal-box overflow-hidden rounded-xl bg-[#000] min-h-screen w-screen">
<div class="flex flex-col w-full mt-14">
{#if displayTab === 'changeOrder'}
<div class="text-white text-md flex flex-col flex-shrink-0">
<div class="rounded-full w-10 h-10 relative bg-gray-900 mb-2">
<img class="rounded-full w-6 h-6 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2" src={`https://financialmodelingprep.com/image-stock/${$assetType === 'stock' ? $stockTicker : $etfTicker}.png`} />
</div>
<span class="mb-1">
{$displayCompanyName?.length > 30 ? $displayCompanyName?.slice(0, 30) + "..." : $displayCompanyName}
</span>
<span class="mb-1 text-sm font-medium">
Current Price: ${$currentPortfolioPrice}
</span>
</div>
<div class="flex justify-between items-center mt-2">
<div class="flex flex-col sm:w-64">
<label class="label font-medium">
<span class="text-white label-text">Number of Shares</span>
</label>
<input inputmode="tel" pattern="[0-9]*" bind:value={numberOfShares} on:input={handleInputChange} type="text" placeholder="Number of Shares" class="text-slate-200 input {numberOfShares > holdingShares ? 'input-error' : ''} bg-gray-900 input-md w-54 sm:w-full max-w-xs" />
</div>
<label on:click={handleMaxOrder} class="mt-9 btn bg-[#000] hover:bg-[#fff] hover:text-black text-white cursor-pointer sm:px-5 border rounded-lg">
Show Max
</label>
</div>
<span class="{numberOfShares <= holdingShares ? 'hidden' : ''} label-text-alt text-error mt-1">
Not enough shares to sell the amount
</span>
<div class="flex justify-between items-center mt-8 w-full">
<div class="flex flex-col sm:flex-row text-blue-400 text-sm font-medium">
<span class="mr-0 sm:mr-1">
Holding Shares:
</span>
<span>
{holdingShares}
</span>
</div>
<div class="flex flex-col sm:flex-row text-blue-400 text-sm">
<span class="mr-0 sm:mr-1">
Estimated Total:
</span>
<span>
{estimatedTotal?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</span>
</div>
</div>
<!--
<div class="grid grid-cols-3 gap-x-6 gap-y-2 text-white font-bold text-lg m-auto mt-14">
{#each Array.from({ length: 10 }, (_, index) => index+1) as num}
{#if num < 10}
<label on:click={() => handleAppendNumber(num)} class="rounded-full flex justify-center items-center w-16 h-16">
{num}
</label>
{/if}
{/each}
<div class="rounded-full flex justify-center items-center w-16 h-16">
</div>
<div class="rounded-full flex justify-center items-center w-16 h-16 hover:bg-gray-600 hover:bg-opacity-[0.4]">
0
</div>
<label on:click={() => handleRemoveNumber()} class="rounded-full flex justify-center items-center w-16 h-16 hover:bg-gray-600 hover:bg-opacity-[0.4]">
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g transform="rotate(-90 12 12)"><path fill="white" d="M13 7.828V20h-2V7.828l-5.364 5.364l-1.414-1.414L12 4l7.778 7.778l-1.414 1.414L13 7.828Z"/></g></svg>
</label>
</div>
-->
<div class="w-5/6 max-w-lg pt-16 m-auto pb-20">
<button on:click={changeTab} class="btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md w-full rounded-lg m-auto text-white font-bold text-md">
Preview Sell Order
</button>
</div>
{:else if displayTab === 'sellOrder'}
<div class="text-white text-md flex flex-col flex-shrink-0">
<div class="rounded-full w-10 h-10 relative bg-gray-900 mb-2">
<img class="rounded-full w-6 h-6 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2" src={`https://financialmodelingprep.com/image-stock/${$assetType === 'stock' ? $stockTicker : $etfTicker}.png`} />
</div>
<span class="mb-1 font-medium text-xl">
Selling {numberOfShares} shares of {$displayCompanyName?.length > 30 ? $displayCompanyName?.slice(0, 30) + "..." : $displayCompanyName}
</span>
</div>
<table class="table table-sm table-compact mt-3 text-start flex justify-start items-center w-full px-3 m-auto">
<tbody>
<!-- row 1 -->
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Price per Share</td>
<td class="bg-[#000] whitespace-normal">${$currentPortfolioPrice}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Number of Shares</td>
<td class="bg-[#000] whitespace-normal">{numberOfShares}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Commission</td>
<td class="bg-[#000] whitespace-normal">${commissionPrice}</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Estimated Total</td>
<td class="bg-[#000] whitespace-normal">{estimatedTotal?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</td>
</tr>
<tr class="text-white" style="font-size: 0.8rem">
<td class="text-start bg-[#000] text-white font-medium">Available Cash After</td>
<td class="bg-[#000] whitespace-normal">{(availableCash+estimatedTotal-commissionPrice)?.toLocaleString(undefined, {
style: 'currency',
currency: 'USD',
})}
</td>
</tr>
</tbody>
</table>
<div class="w-5/6 max-w-lg pt-10 m-auto pb-5 flex flex-col items-center">
<button on:click={changeTab} class="btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md w-full rounded-lg m-auto text-white font-bold text-md">
Change Order
</button>
<button on:click={handleSellOrder} class="mt-6 btn bg-[#000] hover:bg-[#fff] hover:text-black border border-slate-500 btn-md w-full rounded-lg m-auto text-white font-bold text-md">
Sell Order
</button>
</div>
{/if}
</div>
<label for="sellTradeModal" class="absolute left-6 top-4 sm:hidden">
<svg class="w-6 h-6 inline-block mb-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#fff" d="M9.125 21.1L.7 12.7q-.15-.15-.213-.325T.425 12q0-.2.063-.375T.7 11.3l8.425-8.425q.35-.35.875-.35t.9.375q.375.375.375.875t-.375.875L3.55 12l7.35 7.35q.35.35.35.863t-.375.887q-.375.375-.875.375t-.875-.375Z"/></svg>
<span class="text-white text-md font-medium">
Return
</span>
</label>
</div>
</div>
</div>
{/if}