Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mod/reopen-virtual-portfolio #279

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e3481b1
mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
083b837
merge main
binhnguyen2501 May 22, 2024
c4d8efd
update input networth
binhnguyen2501 May 22, 2024
cb8b220
update networth
binhnguyen2501 May 22, 2024
287a835
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
358e5c6
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
dd17f81
update token list
binhnguyen2501 May 22, 2024
a144bdc
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
3a05992
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
0801c58
render allocation and holidng
binhnguyen2501 May 22, 2024
e8d6e0a
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 22, 2024
8bd94df
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
06c35e0
hotfix toast
binhnguyen2501 May 23, 2024
b6cc0f7
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
12debb2
merge main
binhnguyen2501 May 23, 2024
ccaaaa9
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
e7564a9
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
e1ea4a2
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
7729a0a
fix import
binhnguyen2501 May 23, 2024
cb933f7
update calculate
binhnguyen2501 May 23, 2024
87f9ddb
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
f472584
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 23, 2024
fc7d1ce
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
52a159d
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
a9badd8
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
7044e74
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
8c2fb79
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
6c069d4
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
a68d2e6
update edit
binhnguyen2501 May 24, 2024
6bc667f
update flow edit
binhnguyen2501 May 24, 2024
0fedd53
update render
binhnguyen2501 May 24, 2024
262a64c
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 24, 2024
a4ec04c
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 25, 2024
0f81f57
update more virtual
binhnguyen2501 May 25, 2024
7327a1b
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 25, 2024
534f5a5
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 25, 2024
0e8d537
Merge branch 'main' into mod/reopen-virtual-portfolio
binhnguyen2501 May 25, 2024
90d31ee
performance chart
binhnguyen2501 May 25, 2024
ee2a72c
merge main
binhnguyen2501 May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions src/UI/VirtualPortfolio/Allocation.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
<script lang="ts">
import { isDarkMode } from "~/store";
import { formatPercent, formatValue, formatCurrency } from "~/utils/index";
import { i18n } from "~/lib/i18n";

import EChart from "~/components/EChart.svelte";
import Loading from "~/components/Loading.svelte";

import defaultToken from "~/assets/defaultToken.png";

export let isLoading;
export let listTokenHolding;

const MultipleLang = {
token_allocation: i18n("newtabPage.token-allocation", "Token Allocation"),
nft_allocation: i18n("newtabPage.nft-allocation", "NFT Allocation"),
performance: i18n("newtabPage.performance", "Performance"),
Balance: i18n("newtabPage.Balance", "Balance"),
Ratio: i18n("newtabPage.Ratio", "Ratio"),
Value: i18n("newtabPage.Value", "Value"),
};

let optionPie = {
title: {
text: "",
},
tooltip: {
trigger: "item",
extraCssText: "z-index: 9997",
formatter: function (params) {
return `
<div style="display: flex; flex-direction: column; gap: 12px; min-width: 220px;">
<div style="display: flex; align-items: centers; gap: 4px">
<img src=${params?.data?.logo || defaultToken}
onerror="this.onerror=null;this.src='${defaultToken}';"
alt="" width=20 height=20 style="border-radius: 100%" />
<div style="font-weight: 500; font-size: 16px; line-height: 19px; color: ${
$isDarkMode ? "white" : "black"
}">
${params?.name} ${
params?.data?.symbol ? `(${params?.data?.symbol})` : ""
}
</div>
</div>

${
params?.data?.name_balance.length !== 0
? `
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); color: ${
$isDarkMode ? "white" : "black"
}">
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${MultipleLang[params?.data?.name_balance]}
</div>
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${formatCurrency(params?.data?.value_balance)}
</div>
</div>
`
: ""
}

<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); color: ${
$isDarkMode ? "white" : "black"
}">
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${MultipleLang[params?.data?.name_value]}
</div>
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${formatValue(params?.data?.value_value)}
</div>
</div>

<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); color: ${
$isDarkMode ? "white" : "black"
}">
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${MultipleLang[params?.data?.name_ratio]}
</div>
<div style="grid-template-columns: repeat(1, minmax(0, 1fr)); font-weight: 500; font-size: 14px; line-height: 17px;">
${formatPercent(params?.value)}%
</div>
</div>
</div>`;
},
},
legend: {
type: "scroll",
top: "0%",
left: "center",
},
series: [
{
type: "pie",
radius: ["40%", "60%"],
left: 0,
avoidLabelOverlap: false,
label: {
show: false,
position: "center",
},
emphasis: {
label: {
show: false,
fontSize: 40,
fontWeight: "bold",
},
},
labelLine: {
show: false,
},
data: [],
},
],
};

const formatDataPie = (data) => {
return data?.map((item) => {
if (isNaN(item.value)) {
return {
...item,
value: 0,
};
} else {
return item;
}
});
};

const formatTokenBreakdown = (data) => {
const formatData = data.filter((item) => Number(item.value) > 0);

const sumToken = (formatData || []).reduce(
(prev, item) => prev + Number(item?.value),
0
);

const sortBreakdownToken = formatData?.sort((a, b) => {
if (a.value < b.value) {
return 1;
}
if (a.value > b.value) {
return -1;
}
return 0;
});

const topFiveBreakdownToken = sortBreakdownToken
?.slice(0, 5)
.map((item) => {
return {
...item,
id: item.coinId || "N/A",
symbol: item.symbol || "N/A",
name: item.name || "N/A",
};
});

const orderBreakdownToken = sortBreakdownToken?.slice(
5,
sortBreakdownToken.length
);

const sumOrderBreakdownToken = (orderBreakdownToken || []).reduce(
(prev, item) => prev + Number(item.value),
0
);

const dataPieChartOrderBreakdownToken = [
{
logo: defaultToken,
name: "Other tokens",
symbol: "",
name_ratio: "Ratio",
value: (sumOrderBreakdownToken / sumToken) * 100,
name_value: "Value",
value_value: sumOrderBreakdownToken,
name_balance: "",
value_balance: 0,
},
];

const formatDataPieChartTopFiveToken = topFiveBreakdownToken?.map(
(item) => {
return {
logo: item.logo || defaultToken,
name: item.name || item.symbol,
symbol: item.symbol,
name_ratio: "Ratio",
value: Number(item.percent),
name_value: "Value",
value_value: Number(item.value),
name_balance: "Balance",
value_balance: Number(item.amount),
};
}
);

const dataPieChartToken =
sumOrderBreakdownToken > 0
? formatDataPieChartTopFiveToken?.concat(
dataPieChartOrderBreakdownToken
)
: formatDataPieChartTopFiveToken;

optionPie = {
...optionPie,
legend: {
...optionPie.legend,
formatter: function (name) {
const selected = dataPieChartToken.find(
(item) => item.name.toLowerCase() === name.toLowerCase()
);
return selected?.symbol || name;
},
},
series: [
{
...optionPie.series[0],
data: formatDataPie(dataPieChartToken),
},
],
};
};

$: {
if (listTokenHolding.length !== 0) {
formatTokenBreakdown(listTokenHolding);
}
}

$: theme = $isDarkMode ? "dark" : "white";
</script>

<div
class={`rounded-[20px] xl:p-6 py-4 px-3 ${
$isDarkMode ? "bg-[#222222]" : "bg-[#fff] xl:border border_0000001a"
}`}
>
<div class="text-3xl font-medium xl:text-2xl mb-6">Allocation</div>

{#if isLoading}
<div class="flex items-center justify-center h-[465px]">
<Loading />
</div>
{:else}
<div class="h-full">
{#if listTokenHolding.length === 0}
<div
class="flex justify-center items-center h-[465px] text-base text-gray-400"
>
Empty
</div>
{:else}
<EChart
id="pie-chart-token-allocation-virtual"
{theme}
notMerge={true}
option={optionPie}
height={465}
/>
{/if}
</div>
{/if}
</div>

<style windi:preflights:global windi:safelist:global></style>
Loading