update redesign layout

This commit is contained in:
liangping 2023-06-15 11:06:30 +08:00
parent 18ce47b823
commit 4fdafa3131
3 changed files with 151 additions and 196 deletions

View File

@ -18,7 +18,7 @@
> >
</div> </div>
<div <div
class="hidden md:block" class="hidden md:!block"
> >
<a <a
class="link link-primary no-underline mr-4" class="link link-primary no-underline mr-4"

View File

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { CosmosRestClient } from '@/libs/client'; import { CosmosRestClient } from '@/libs/client';
import { useDashboard, useFormatter } from '@/stores'; import { useBlockchain, useDashboard, useFormatter } from '@/stores';
import type { Coin, CoinWithPrice, Delegation } from '@/types'; import type { Coin, CoinWithPrice, Delegation } from '@/types';
import { fromBech32, toBase64, toBech32, toHex } from '@cosmjs/encoding'; import { fromBech32, toBase64, toBech32, toHex } from '@cosmjs/encoding';
import { Icon } from '@iconify/vue'; import { Icon } from '@iconify/vue';
@ -14,6 +14,7 @@ import {
} from './utils'; } from './utils';
const dashboard = useDashboard(); const dashboard = useDashboard();
const chainStore = useBlockchain()
const format = useFormatter(); const format = useFormatter();
const editable = ref(false); // to edit addresses const editable = ref(false); // to edit addresses
const sourceAddress = ref(''); // const sourceAddress = ref(''); //
@ -55,17 +56,20 @@ Object.values(conf.value).forEach((imported) => {
const accounts = computed(() => { const accounts = computed(() => {
let a = [] as { let a = [] as {
account: AccountEntry; key: string,
delegation: CoinWithPrice; subaccounts: {
balances: CoinWithPrice[]; account: AccountEntry;
delegation: CoinWithPrice;
balances: CoinWithPrice[];
}[]
}[]; }[];
Object.values(conf.value).forEach((x) => { Object.values(conf.value).forEach((x) => {
const composition = x.map((entry) => { const composition = x.map((entry) => {
const d = delegations.value[entry.address]; const d = delegations.value[entry.address];
let delegation = { } as CoinWithPrice let delegation = {} as CoinWithPrice
if (d && d.length > 0) { if (d && d.length > 0) {
d.forEach((b) => { d.forEach((b) => {
delegation.amount = (Number(b.balance.amount) + Number( delegation.amount || 0)).toFixed() delegation.amount = (Number(b.balance.amount) + Number(delegation.amount || 0)).toFixed()
delegation.denom = b.balance.denom; delegation.denom = b.balance.denom;
}); });
delegation.value = format.tokenValueNumber(delegation) delegation.value = format.tokenValueNumber(delegation)
@ -75,29 +79,34 @@ const accounts = computed(() => {
account: entry, account: entry,
delegation, delegation,
balances: balances.value[entry.address] balances: balances.value[entry.address]
? balances.value[entry.address].map(x => { ? balances.value[entry.address].map(x => {
const value = format.tokenValueNumber(x) const value = format.tokenValueNumber(x)
return { return {
amount: x.amount, amount: x.amount,
denom: x.denom, denom: x.denom,
value, value,
change24h: format.priceChanges(x.denom) change24h: format.priceChanges(x.denom)
} }
}) })
: [] : []
} }
}); });
a = a.concat(composition); if (x.at(0)) a.push({ key: x.at(0)?.address || " ", subaccounts: composition });
}); });
return a; return a;
}); });
const addresses = computed(() => { const addresses = computed(() => {
return accounts.value.map((x) => x.account.address); return accounts.value.flatMap(x => x.subaccounts.map(a => a.account.address))
// const temp = [] as string[]
// accounts.value.forEach((x) => x.accounts.forEach(a => {
// temp.push(a.account.address)
// }));
// return temp
}); });
const totalValue = computed(() => { const totalValue = computed(() => {
return accounts.value.reduce((s, e) => { return accounts.value.flatMap(x => x.subaccounts).reduce((s, e) => {
s += e.delegation.value || 0 s += e.delegation.value || 0
e.balances.forEach(b => { e.balances.forEach(b => {
s += b.value || 0 s += b.value || 0
@ -106,8 +115,8 @@ const totalValue = computed(() => {
}, 0) }, 0)
}) })
const totalChange= computed(() => { const totalChange = computed(() => {
return accounts.value.reduce((s, e) => { return accounts.value.flatMap(x => x.subaccounts).reduce((s, e) => {
s += (e.delegation.change24h || 0) * (e.delegation.value || 0) / 100 s += (e.delegation.change24h || 0) * (e.delegation.value || 0) / 100
e.balances.forEach(b => { e.balances.forEach(b => {
s += (b.change24h || 0) * (b.value || 0) / 100 s += (b.change24h || 0) * (b.value || 0) / 100
@ -223,33 +232,20 @@ async function loadBalances(endpoint: string, address: string) {
<template> <template>
<div> <div>
<div class="overflow-x-auto w-full card"> <div class="overflow-x-auto w-full card">
<div <div class="lg:!flex lg:!items-center lg:!justify-between bg-base-100 p-5">
class="lg:!flex lg:!items-center lg:!justify-between bg-base-100 p-5"
>
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<h2 <h2 class="text-2xl font-bold leading-7 sm:!truncate sm:!text-3xl sm:!tracking-tight">
class="text-2xl font-bold leading-7 sm:!truncate sm:!text-3xl sm:!tracking-tight"
>
Accounts Accounts
</h2> </h2>
<div <div class="mt-1 flex flex-col sm:!mt-0 sm:!flex-row sm:!flex-wrap sm:!space-x-6">
class="mt-1 flex flex-col sm:!mt-0 sm:!flex-row sm:!flex-wrap sm:!space-x-6"
>
<div class="mt-2 flex items-center text-sm text-gray-500"> <div class="mt-2 flex items-center text-sm text-gray-500">
<svg <svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor"
class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" aria-hidden="true">
viewBox="0 0 20 20" <path fill-rule="evenodd"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M6 3.75A2.75 2.75 0 018.75 1h2.5A2.75 2.75 0 0114 3.75v.443c.572.055 1.14.122 1.706.2C17.053 4.582 18 5.75 18 7.07v3.469c0 1.126-.694 2.191-1.83 2.54-1.952.599-4.024.921-6.17.921s-4.219-.322-6.17-.921C2.694 12.73 2 11.665 2 10.539V7.07c0-1.321.947-2.489 2.294-2.676A41.047 41.047 0 016 4.193V3.75zm6.5 0v.325a41.622 41.622 0 00-5 0V3.75c0-.69.56-1.25 1.25-1.25h2.5c.69 0 1.25.56 1.25 1.25zM10 10a1 1 0 00-1 1v.01a1 1 0 001 1h.01a1 1 0 001-1V11a1 1 0 00-1-1H10z" d="M6 3.75A2.75 2.75 0 018.75 1h2.5A2.75 2.75 0 0114 3.75v.443c.572.055 1.14.122 1.706.2C17.053 4.582 18 5.75 18 7.07v3.469c0 1.126-.694 2.191-1.83 2.54-1.952.599-4.024.921-6.17.921s-4.219-.322-6.17-.921C2.694 12.73 2 11.665 2 10.539V7.07c0-1.321.947-2.489 2.294-2.676A41.047 41.047 0 016 4.193V3.75zm6.5 0v.325a41.622 41.622 0 00-5 0V3.75c0-.69.56-1.25 1.25-1.25h2.5c.69 0 1.25.56 1.25 1.25zM10 10a1 1 0 00-1 1v.01a1 1 0 001 1h.01a1 1 0 001-1V11a1 1 0 00-1-1H10z"
clip-rule="evenodd" clip-rule="evenodd" />
/>
<path <path
d="M3 15.055v-.684c.126.053.255.1.39.142 2.092.642 4.313.987 6.61.987 2.297 0 4.518-.345 6.61-.987.135-.041.264-.089.39-.142v.684c0 1.347-.985 2.53-2.363 2.686a41.454 41.454 0 01-9.274 0C3.985 17.585 3 16.402 3 15.055z" d="M3 15.055v-.684c.126.053.255.1.39.142 2.092.642 4.313.987 6.61.987 2.297 0 4.518-.345 6.61-.987.135-.041.264-.089.39-.142v.684c0 1.347-.985 2.53-2.363 2.686a41.454 41.454 0 01-9.274 0C3.985 17.585 3 16.402 3 15.055z" />
/>
</svg> </svg>
Manage all your assets in one page Manage all your assets in one page
</div> </div>
@ -258,133 +254,110 @@ async function loadBalances(endpoint: string, address: string) {
<div class="mt-5 flex flex-col lg:!ml-4 lg:!mt-0 text-right"> <div class="mt-5 flex flex-col lg:!ml-4 lg:!mt-0 text-right">
<span>Total Value</span> <span>Total Value</span>
<span class="text-xl text-success font-bold">${{ format.formatNumber(totalValue, '0,0.[00]') }}</span> <span class="text-xl text-success font-bold">${{ format.formatNumber(totalValue, '0,0.[00]') }}</span>
<span class="text-sm" :class="format.color(totalChange)">{{ format.formatNumber(totalChange, '+0,0.[00]') }}</span> <span class="text-sm" :class="format.color(totalChange)">{{ format.formatNumber(totalChange, '+0,0.[00]')
}}</span>
</div> </div>
</div> </div>
<div class="overflow-x-auto"> </div>
<table class="table table-compact w-full">
<!-- head --> <div class="overflow-x-auto">
<thead class="rounded-none"> <div v-for="{ key, subaccounts } in accounts" class="bg-base-100 rounded-xl my-5 p-5">
<tr> <div class="flex justify-self-center">
<th v-if="editable"></th> <div class="mr-2 p-2">
<th class="hidden md:block">Account</th> <svg :fill="chainStore.current?.themeColor || '#666CFF'" height="28px" width="28px" version="1.1" id="Capa_1"
<th>Delegation</th> xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 487.5 487.5"
<th>Balance</th> xml:space="preserve">
<th></th> <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
</tr> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
</thead> <g id="SVGRepo_iconCarrier">
<tbody> <g>
<!-- row 1 --> <g>
<tr v-for="{account, balances, delegation} in accounts"> <path
<td v-if="editable"> d="M437,12.3C437,5.5,431.5,0,424.7,0H126.3C84.4,0,50.4,34.1,50.4,75.9v335.7c0,41.9,34.1,75.9,75.9,75.9h298.5 c6.8,0,12.3-5.5,12.3-12.3V139.6c0-6.8-5.5-12.3-12.3-12.3H126.3c-28.3,0-51.4-23.1-51.4-51.4S98,24.5,126.3,24.5h298.5 C431.5,24.5,437,19,437,12.3z M126.3,151.8h286.2V463H126.3c-28.3,0-51.4-23.1-51.4-51.4V131.7 C88.4,144.2,106.5,151.8,126.3,151.8z">
<Icon </path>
icon="mdi:close-box" <path
class="text-error" d="M130.5,64.8c-6.8,0-12.3,5.5-12.3,12.3s5.5,12.3,12.3,12.3h280.1c6.8,0,12.3-5.5,12.3-12.3s-5.5-12.3-12.3-12.3H130.5z">
@click="removeAddress(account.address)" </path>
></Icon> <path
</td> d="M178,397.7c6.3,2.4,13.4-0.7,15.8-7.1l17.9-46.8h62.7c0.5,0,0.9-0.1,1.3-0.1l17.9,46.9c1.9,4.9,6.5,7.9,11.4,7.9 c1.5,0,2.9-0.3,4.4-0.8c6.3-2.4,9.5-9.5,7.1-15.8l-54-141.2c-3-7.9-10.4-13-18.8-13c-8.4,0-15.8,5.1-18.8,13l-54,141.2 C168.5,388.2,171.7,395.2,178,397.7z M243.7,260l22.7,59.3h-45.3L243.7,260z">
<td class="px-4 hidden md:block"> </path>
<RouterLink :to="`/${account.chainName}/account/${account.address}`"> </g>
<div class="flex items-center space-x-2"> </g>
<div class="avatar"> </g>
<div class="mask mask-squircle w-8 h-8"> </svg>
<img :src="account.logo" :alt="account.address" /> </div>
</div> <div>
</div> <div class=" font-bold">{{ key }}</div>
<div> <div class="dropdown">
<div class="font-bold capitalize"> <label tabindex="0" class="">{{ subaccounts.length }} addresses</label>
{{ account.chainName }} <ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-200 rounded-box z-50">
</div> <li v-for="x in subaccounts">
<div class="text-sm opacity-50 hidden md:!block"> <a>
{{ account.address }} <img :src="x.account.logo" class="w-8 h-8 mr-2" />
</div> <span class="font-bold capitalize">{{ x.account.chainName }} <br>
</div> <span class="text-xs font-normal">{{ x.account.address }}</span>
</div> </span>
</RouterLink> <label class="btn btn-error btn-xs" @click="removeAddress(x.account.address)">Remove</label>
</td> </a>
<td> </li>
<div v-if="delegation"> </ul>
{{ </div>
format.formatToken( </div>
delegation, </div>
true, <div class="divider"></div>
'0,0.[0000]', <div>
'all' <div class="my-4 ml-6">Delegations</div>
) <ul class="!menu bg-base-200 w-full rounded-box ">
}} <div v-for="x in subaccounts">
<div <li v-if="x.delegation.amount">
class="text-xs" <a>
:class="format.priceColor(delegation.denom)" <img :src="x.account.logo" class="w-8 h-8 mr-2" />
> <span class="font-bold">{{ format.formatToken(x.delegation, true, '0,0.[000000]', 'all') }} <br><span
${{ format.formatNumber(delegation.value, '0,0.[00]') }} class="text-xs" :class="format.color(x.delegation.change24h)">{{
</div> format.formatNumber(x.delegation.change24h, '+0.[00]') }}%</span></span>
</div> <span class="float-right text-right">${{ format.formatNumber(x.delegation.value, '0,0.[00]') }}<br><span
</td> class="text-xs" :class="format.color(x.delegation.change24h)">{{
<td> format.formatNumber((x.delegation.change24h || 0) * (x.delegation.value || 0) / 100, '+0,0.[00]')
<ul tabindex="0" > }}</span></span>
<li v-for="b in balances"> </a>
{{ format.formatToken(b, true, '0,0.[0000]', 'all') }} </li>
<div class="text-xs" :class="format.priceColor(b.denom)"> </div>
${{ format.formatNumber(b.value, '0,0.[00]') }} ({{ </ul>
format.formatNumber(b.change24h, '+0.[0]') </div>
}}%) <div>
</div> <div class="my-4 ml-6">Balances</div>
</li> <ul class="!menu bg-base-200 w-full rounded-box ">
</ul> <div v-for="s in subaccounts">
</td> <li v-for="x in s.balances">
<th> <a>
<button class="btn btn-ghost btn-xs hidden">details</button> <img :src="s.account.logo" class="w-8 h-8 mr-2" />
</th> <span class="font-bold">{{ format.formatToken(x, true, '0,0.[000000]', 'all') }} <br><span
</tr> class="text-xs" :class="format.color(x.change24h)">{{ format.formatNumber(x.change24h, '+0.[00]')
</tbody> }}%</span></span>
<tfoot> <span class="float-right text-right">${{ format.formatNumber(x.value, '0,0.[00]') }}<br><span
<th colspan="10"> class="text-xs" :class="format.color(x.change24h)">{{ format.formatNumber((x.change24h || 0) *
<div class="flex justify-between"> (x.value || 0) / 100, '+0,0.[00]') }}</span></span>
<span> </a>
<button </li>
type="button" </div>
class="inline-flex items-center rounded-md bg-primary px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm" </ul>
@click="toggleEdit" </div>
> </div>
<svg
class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" <div class=" text-center bg-base-100 rounded-xl p-4">
viewBox="0 0 20 20" <a href="#address-modal"
fill="currentColor" class="inline-flex items-center ml-3 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
aria-hidden="true" <svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
> <path
<path d="M12.232 4.232a2.5 2.5 0 013.536 3.536l-1.225 1.224a.75.75 0 001.061 1.06l1.224-1.224a4 4 0 00-5.656-5.656l-3 3a4 4 0 00.225 5.865.75.75 0 00.977-1.138 2.5 2.5 0 01-.142-3.667l3-3z" />
d="M2.695 14.763l-1.262 3.154a.5.5 0 00.65.65l3.155-1.262a4 4 0 001.343-.885L17.5 5.5a2.121 2.121 0 00-3-3L3.58 13.42a4 4 0 00-.885 1.343z" <path
/> d="M11.603 7.963a.75.75 0 00-.977 1.138 2.5 2.5 0 01.142 3.667l-3 3a2.5 2.5 0 01-3.536-3.536l1.225-1.224a.75.75 0 00-1.061-1.06l-1.224 1.224a4 4 0 105.656 5.656l3-3a4 4 0 00-.225-5.865z" />
</svg> </svg>
Edit Import Address
</button> </a>
<a <RouterLink to="/wallet/keplr">
href="#address-modal" <span class="btn btn-link">Add chain to Keplr</span>
class="inline-flex items-center ml-3 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" </RouterLink>
>
<svg
class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
d="M12.232 4.232a2.5 2.5 0 013.536 3.536l-1.225 1.224a.75.75 0 001.061 1.06l1.224-1.224a4 4 0 00-5.656-5.656l-3 3a4 4 0 00.225 5.865.75.75 0 00.977-1.138 2.5 2.5 0 01-.142-3.667l3-3z"
/>
<path
d="M11.603 7.963a.75.75 0 00-.977 1.138 2.5 2.5 0 01.142 3.667l-3 3a2.5 2.5 0 01-3.536-3.536l1.225-1.224a.75.75 0 00-1.061-1.06l-1.224 1.224a4 4 0 105.656 5.656l3-3a4 4 0 00-.225-5.865z"
/>
</svg>
Import
</a>
</span>
<RouterLink to="/wallet/keplr" class="btn btn-sm btn-primary hidden md:block">
Add chain to Keplr
</RouterLink>
</div>
</th>
</tfoot>
</table>
</div> </div>
</div> </div>
<!-- Put this part before </body> tag --> <!-- Put this part before </body> tag -->
@ -395,10 +368,7 @@ async function loadBalances(endpoint: string, address: string) {
<div> <div>
<label class="input-group input-group-sm w-full"> <label class="input-group input-group-sm w-full">
<span>Connected</span> <span>Connected</span>
<select <select v-model="selectedSource" class="select select-bordered select-sm w-3/4">
v-model="selectedSource"
class="select select-bordered select-sm w-3/4"
>
<option v-for="source in sourceOptions" :value="source"> <option v-for="source in sourceOptions" :value="source">
<span class="overflow-hidden">{{ source.cosmosAddress }}</span> <span class="overflow-hidden">{{ source.cosmosAddress }}</span>
</option> </option>
@ -406,11 +376,7 @@ async function loadBalances(endpoint: string, address: string) {
</label> </label>
<label class="input-group input-group-sm my-2"> <label class="input-group input-group-sm my-2">
<span>Custom</span> <span>Custom</span>
<input <input v-model="sourceAddress" class="input input-bordered w-full input-sm" placeholder="Input an address" />
v-model="sourceAddress"
class="input input-bordered w-full input-sm"
placeholder="Input an address"
/>
</label> </label>
</div> </div>
<div class="py-4 max-h-72 overflow-y-auto"> <div class="py-4 max-h-72 overflow-y-auto">
@ -424,19 +390,10 @@ async function loadBalances(endpoint: string, address: string) {
</div> </div>
</div> </div>
<div> <div>
<div <div class="tooltip" :class="acc.compatiable ? 'tooltip-success' : 'tooltip-error'
class="tooltip" " :data-tip="`Coin Type: ${acc.coinType}`">
:class=" <div class="font-bold capitalize" :class="acc.compatiable ? 'text-green-500' : 'text-red-500'
acc.compatiable ? 'tooltip-success' : 'tooltip-error' ">
"
:data-tip="`Coin Type: ${acc.coinType}`"
>
<div
class="font-bold capitalize"
:class="
acc.compatiable ? 'text-green-500' : 'text-red-500'
"
>
{{ acc.chainName }} {{ acc.chainName }}
</div> </div>
</div> </div>
@ -447,10 +404,7 @@ async function loadBalances(endpoint: string, address: string) {
</div> </div>
</td> </td>
<td class="text-right"> <td class="text-right">
<span <span class="btn !bg-yes !border-yes btn-xs text-white" @click="addAddress(acc)">
class="btn !bg-yes !border-yes btn-xs text-white"
@click="addAddress(acc)"
>
<Icon icon="mdi:plus" /> <Icon icon="mdi:plus" />
</span> </span>
</td> </td>

View File

@ -73,7 +73,8 @@ export const useFormatter = defineStore('formatter', {
const prices = this.dashboard.prices[id]; const prices = this.dashboard.prices[id];
return prices; return prices;
}, },
color(change: number) { color(change?: number) {
if(!change) return ""
switch (true) { switch (true) {
case change > 0: case change > 0:
return "text-success" return "text-success"