harb/web-app/src/views/StakeView.vue
johba f8927b426e webapp - ESLint + Prettier with pre-commit hooks (#54)
resolves #47

Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/54
2025-10-03 16:51:44 +02:00

166 lines
5.7 KiB
Vue

<template>
<div class="stake-view">
<div class="stake-view-wrapper">
<h3>
Staking Dashboard
<IconInfo size="20px">
<template #text>
Stake your $KRK and claim owner slots. Owner slots give a return on every token buy that increases the liquidity of KrAIken.
Owner slots are limited to 20,000 slots in total. To enable everyone and anyone to join staking is protected by a Harberger
Tax mechanism.
</template>
</IconInfo>
</h3>
<div class="stake-view-body">
<ChartComplete></ChartComplete>
<div class="hold-stake-wrapper">
<FCard class="inner-border">
<template v-if="!isChainSupported"> Chain not supported </template>
<template v-else-if="status !== 'connected'">
<FButton @click="showPanel = true" size="large" block>Connect Wallet</FButton>
</template>
<template v-else>
<StakeHolder></StakeHolder>
</template>
</FCard>
</div>
</div>
</div>
<div class="statistics-wrapper">
<h3>Statistics</h3>
<div class="statistics-outputs-wrapper">
<StatsOutput headline="Average Slot Tax" :price="`${averageTaxRate.toFixed(2)} %`"></StatsOutput>
<StatsOutput
headline="Claimed Owner Slots"
:price="`${InsertCommaNumber(stats.claimedSlots)} / ${InsertCommaNumber(stats.maxSlots)}`"
></StatsOutput>
<StatsOutput headline="Total Supply Change / 7d" :price="`+ ${stats.totalSupplyChange7d} $KRK`"></StatsOutput>
<StatsOutput headline="Inflation / 7d" :price="`+${stats.inflation7d}%`"></StatsOutput>
</div>
</div>
<div class="active-positions-wrapper">
<h3>Active Positions</h3>
<div class="active-positions-list">
<CollapseActive
v-for="position in myActivePositions"
:taxRate="position.taxRatePercentage"
:amount="position.amount"
:treshold="tresholdValue"
:id="position.positionId"
:position="position"
:key="position.id"
></CollapseActive>
</div>
</div>
<!-- <f-button @click="getGraphData">graphql test</f-button>
<div v-for="position in positions" :key="position.id">
{{ position }}
</div> -->
</div>
</template>
<script setup lang="ts">
import StakeHolder from '@/components/StakeHolder.vue';
import ChartComplete from '@/components/chart/ChartComplete.vue';
import StatsOutput from '@/components/StatsOutput.vue';
import CollapseActive from '@/components/collapse/CollapseActive.vue';
import { onMounted, computed, inject } from 'vue';
import { useStatCollection } from '@/composables/useStatCollection';
import { useChains, useAccount } from '@wagmi/vue';
import { useWallet } from '@/composables/useWallet';
import FCard from '@/components/fcomponents/FCard.vue';
import IconInfo from '@/components/icons/IconInfo.vue';
import FButton from '@/components/fcomponents/FButton.vue';
import { DEFAULT_CHAIN_ID } from '@/config';
// todo interface positions
import { usePositions } from '@/composables/usePositions';
const { status } = useAccount();
const showPanel = inject('showPanel');
import { InsertCommaNumber } from '@/utils/helper';
const { myActivePositions, tresholdValue, activePositions } = usePositions();
const stats = useStatCollection();
const wallet = useWallet();
const chains = useChains();
function calculateAverageTaxRate(data: Array<{ taxRate: number | string }>): number {
// console.log("data", data);
if (data.length === 0) {
return 0;
}
const totalTaxRate = data.reduce((sum: number, entry: { taxRate: number | string }) => sum + parseFloat(String(entry.taxRate)), 0);
const averageTaxRate = totalTaxRate / data.length;
return averageTaxRate * 100;
}
const averageTaxRate = computed(() => calculateAverageTaxRate(activePositions.value));
const supportedChainIds = computed(() => chains.value.map(chain => chain.id));
const currentChainId = computed(() => wallet.account.chainId ?? DEFAULT_CHAIN_ID);
const isChainSupported = computed(() => supportedChainIds.value.includes(currentChainId.value));
onMounted(async () => {});
</script>
<style lang="sass">
.stake-view
display: flex
flex-direction: column
gap: 32px
padding: 16px
@media (min-width: 992px)
padding: 48px
.stake-view-wrapper
background-color: #07111B
padding: 12px 0
border-radius: 24px
@media (min-width: 992px)
padding: 24px
.stake-view-body
display: flex
gap: 40px
position: relative
flex-direction: column
@media (min-width: 992px)
flex-direction: row
.positions-graph
flex: 1 1 67%
.hold-stake-wrapper
flex: 1 1 33%
display: flex
flex-direction: column
gap: 48px
.f-card
overflow: unset
.f-card__body
height: 100%
display: flex
align-items: center
justify-content: center
&.inner-border
padding: 0
.statistics-wrapper
.statistics-outputs-wrapper
display: flex
justify-content: center
flex-direction: column
gap: 46px
@media (min-width: 768px)
flex-direction: row
flex-wrap: wrap
.stats-output
min-width: 280px
.active-positions-wrapper
width: 100%
margin-left: auto
margin-right: auto
@media (min-width: 768px)
width: 580px
.active-positions-list
display: flex
flex-direction: column
gap: 12px
</style>