|
|
@@ -1,48 +1,43 @@ |
|
|
|
<template> |
|
|
|
<div class="container is-max-desktop pb-4"> |
|
|
|
<section class="section is-small"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
<div> |
|
|
|
<section class="layout-section"> |
|
|
|
<div class="heading"> |
|
|
|
{{ fund.fundInfo.title }} |
|
|
|
</div> |
|
|
|
<div |
|
|
|
class="is-block-mobile |
|
|
|
is-flex-tablet-only |
|
|
|
is-flex-desktop |
|
|
|
is-flex-direction-row |
|
|
|
is-justify-content-space-between"> |
|
|
|
<div class="fund-description pr-5" v-html="fixNewlines(fund.fundInfo.description)"> |
|
|
|
</div> |
|
|
|
<div |
|
|
|
class="fund-details is-flex is-flex-direction-row is-justify-content-end my-auto py-6"> |
|
|
|
<ul> |
|
|
|
<li v-for="(detail, i) in fundDetails" v-bind:key="i"> |
|
|
|
<span class="has-text-weight-bold is-size-6 mr-2">{{ detail.title }}</span> |
|
|
|
<span class="is-size-6">{{ detail.val }}</span> |
|
|
|
<div> |
|
|
|
<p v-html="fixNewlines(fund.fundInfo.description)"></p> |
|
|
|
<div> |
|
|
|
<ul class="fund-details"> |
|
|
|
<li v-for="(detail, i) in fundDetails" :key="i" class="fund-detail"> |
|
|
|
<div class="detail-icon"> |
|
|
|
<svg-icon type="mdi" height="22" width="22" :path="detail.icon"/> |
|
|
|
</div> |
|
|
|
<div class="detail-text"> |
|
|
|
{{ detail.val }} |
|
|
|
</div> |
|
|
|
</li> |
|
|
|
</ul> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
<section> |
|
|
|
<div class="box"> |
|
|
|
<div class="title is-size-4 has-text-grey-dark has-text-centered"> |
|
|
|
<div> |
|
|
|
<div class="heading"> |
|
|
|
Tracker |
|
|
|
</div> |
|
|
|
<div class="level" v-if="fund.fundInfo.bonuses.length > 0"> |
|
|
|
<div class="level-item has-text-centered" |
|
|
|
v-for="bonus in fund.fundInfo.bonuses.sort((v1, v2) => v1.goal - v2.goal)" |
|
|
|
v-bind:key="bonus.goal" |
|
|
|
<div v-if="fund.fundInfo.bonuses.length > 0"> |
|
|
|
<div |
|
|
|
v-for="bonus in fund.fundInfo.bonuses.sort((v1, v2) => v1.goal - v2.goal)" |
|
|
|
v-bind:key="bonus.goal" |
|
|
|
> |
|
|
|
<div> |
|
|
|
<p |
|
|
|
class="heading" |
|
|
|
|
|
|
|
:class="amountHeld >= bonus.goal |
|
|
|
? 'has-text-success' : 'has-text-grey-dark'" |
|
|
|
> |
|
|
|
{{ bonus.goal.toLocaleString() }} XLM |
|
|
|
</p> |
|
|
|
<p |
|
|
|
class="title" |
|
|
|
|
|
|
|
:class="amountHeld >= bonus.goal |
|
|
|
? 'has-text-success' : 'has-text-grey-dark'" |
|
|
|
> |
|
|
@@ -52,15 +47,8 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div |
|
|
|
class="is-flex |
|
|
|
is-flex-direction-row |
|
|
|
is-justify-content-space-around |
|
|
|
is-size-4 |
|
|
|
has-text-white |
|
|
|
mb-3" |
|
|
|
> |
|
|
|
<div class="total"> |
|
|
|
<div> |
|
|
|
<div> |
|
|
|
<span class="total-label is-size-3 pr-2 has-text-weight-light"> |
|
|
|
Raised |
|
|
|
</span> |
|
|
@@ -68,7 +56,7 @@ |
|
|
|
{{ amountHeld.toLocaleString() }} XLM |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
<div class="remaining"> |
|
|
|
<div> |
|
|
|
<span class="remaining-label is-size-3 pr-2 has-text-weight-light"> |
|
|
|
Remaining |
|
|
|
</span> |
|
|
@@ -77,19 +65,17 @@ |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
<section class="section is-small"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
Contribute |
|
|
|
</div> |
|
|
|
<ErrorDisplay :errors="errs" v-if="invalidContributionForm"/> |
|
|
|
<div class="control my-2"> |
|
|
|
<input class="input is-normal has-background-white has-text-black" type="text" |
|
|
|
<input type="text" |
|
|
|
placeholder="Private Key" aria-label="Wallet" v-model="pk" @blur="queryAccount"> |
|
|
|
</div> |
|
|
|
<div class="control my-2" :class="loading.balance ? 'is-loading' : null"> |
|
|
|
<input |
|
|
|
class="input is-normal has-background-white has-text-black" |
|
|
|
|
|
|
|
type="number" |
|
|
|
placeholder="Amount" |
|
|
|
aria-label="Amount" |
|
|
@@ -98,90 +84,89 @@ |
|
|
|
:disabled="loading.balance" |
|
|
|
> |
|
|
|
</div> |
|
|
|
<div class="is-flex is-justify-content-end"> |
|
|
|
<div> |
|
|
|
<button |
|
|
|
class="button is-primary" |
|
|
|
:class="loading.contribution ? 'is-loading' : ''" |
|
|
|
:disabled="invalidContributionForm" |
|
|
|
@click="makeContribution" |
|
|
|
>Submit |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
<section class="section is-small" v-if="contributions.length > 0"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
Contributions |
|
|
|
</div> |
|
|
|
<div class="is-flex is-justify-content-space-between is-rounded my-2"> |
|
|
|
<div class="select"> |
|
|
|
<select v-model="selectedDate" aria-label="Filter by date"> |
|
|
|
<option v-for="date in selectableDates" v-bind:key="date" :value="date"> |
|
|
|
{{ date ?? 'Cutoff Date' }} |
|
|
|
</option> |
|
|
|
</select> |
|
|
|
<section v-if="contributions.length > 0"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
Contributions |
|
|
|
</div> |
|
|
|
<div class="consolidate-option has-background-white px-4 py-1 my-auto"> |
|
|
|
<label for="consolidate" class="checkbox has-text-dark is-size-6"> |
|
|
|
<span class="consolidate-label is-inline-block"> |
|
|
|
<div class="is-flex is-justify-content-space-between is-rounded my-2"> |
|
|
|
<div> |
|
|
|
<select v-model="selectedDate" aria-label="Filter by date"> |
|
|
|
<option v-for="date in selectableDates" v-bind:key="date" :value="date"> |
|
|
|
{{ date ?? 'Cutoff Date' }} |
|
|
|
</option> |
|
|
|
</select> |
|
|
|
</div> |
|
|
|
<div class="consolidate-option has-background-white px-4 py-1 my-auto"> |
|
|
|
<label for="consolidate" class="checkbox has-text-dark is-size-6"> |
|
|
|
<span> |
|
|
|
Consolidate wallets |
|
|
|
</span> |
|
|
|
<input |
|
|
|
type="checkbox" |
|
|
|
class="ml-2" |
|
|
|
id="consolidate" |
|
|
|
aria-label="Consolidate wallets" |
|
|
|
v-model="enableConsolidation" |
|
|
|
> |
|
|
|
</label> |
|
|
|
<input |
|
|
|
type="checkbox" |
|
|
|
class="ml-2" |
|
|
|
id="consolidate" |
|
|
|
aria-label="Consolidate wallets" |
|
|
|
v-model="enableConsolidation" |
|
|
|
> |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div id="contribution-container" @scroll="loadMoreIfNeeded"> |
|
|
|
<table class="contribution-table table is-fullwidth"> |
|
|
|
<thead> |
|
|
|
<tr> |
|
|
|
<th>Wallet</th> |
|
|
|
<th>Amount</th> |
|
|
|
<th v-if="!enableConsolidation">Time</th> |
|
|
|
<th v-else>Tokens</th> |
|
|
|
</tr> |
|
|
|
</thead> |
|
|
|
<tbody> |
|
|
|
<tr v-for="(contribution, i) in contributions" v-bind:key="i"> |
|
|
|
<td>{{ truncateWallet(contribution.wallet, 6, undefined) }}</td> |
|
|
|
<td>{{ contribution.amount }}</td> |
|
|
|
<td v-if="!enableConsolidation"> |
|
|
|
<span class="transaction-date" :title="formatDate(contribution.createdAt, true)"> |
|
|
|
<div id="contribution-container" @scroll="loadMoreIfNeeded"> |
|
|
|
<table> |
|
|
|
<thead> |
|
|
|
<tr> |
|
|
|
<th>Wallet</th> |
|
|
|
<th>Amount</th> |
|
|
|
<th v-if="!enableConsolidation">Time</th> |
|
|
|
<th v-else>Tokens</th> |
|
|
|
</tr> |
|
|
|
</thead> |
|
|
|
<tbody> |
|
|
|
<tr v-for="(contribution, i) in contributions" v-bind:key="i"> |
|
|
|
<td>{{ truncateWallet(contribution.wallet, 6, undefined) }}</td> |
|
|
|
<td>{{ contribution.amount }}</td> |
|
|
|
<td v-if="!enableConsolidation"> |
|
|
|
<span :title="formatDate(contribution.createdAt, true)"> |
|
|
|
{{ formatDate(contribution.createdAt, true) }} |
|
|
|
</span> |
|
|
|
</td> |
|
|
|
<td v-else> |
|
|
|
<span>{{ calculateReward(contribution.amount / fund.fundInfo.price) }}</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
<section v-if="store.getters.getToken && hasPermission(Privileges.AdminPlus)"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
Close Group Fund |
|
|
|
</div> |
|
|
|
<div class="box is-flex is-flex-direction-row is-justify-content-space-between"> |
|
|
|
<div class="my-auto"> |
|
|
|
<label class="checkbox" for="delete-confirm"> |
|
|
|
<input type="checkbox" id="delete-confirm" v-model="allowDelete"> Close |
|
|
|
</label> |
|
|
|
</td> |
|
|
|
<td v-else> |
|
|
|
<span>{{ calculateReward(contribution.amount / fund.fundInfo.price) }}</span> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
<section v-if="store.getters.getToken && hasPermission(Privileges.AdminPlus)"> |
|
|
|
<div class="title is-size-4 has-text-white-ter has-text-centered"> |
|
|
|
Close Group Fund |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<button |
|
|
|
class="button is-danger" |
|
|
|
:disabled="!allowDelete" |
|
|
|
@click="deleteFund" |
|
|
|
> |
|
|
|
Close |
|
|
|
</button> |
|
|
|
<div> |
|
|
|
<label for="delete-confirm"> |
|
|
|
<input type="checkbox" id="delete-confirm" v-model="allowDelete"> Close |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<button |
|
|
|
|
|
|
|
:disabled="!allowDelete" |
|
|
|
@click="deleteFund" |
|
|
|
> |
|
|
|
Close |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
</section> |
|
|
|
</div> |
|
|
|
</template> |
|
|
@@ -220,6 +205,13 @@ import { |
|
|
|
getContributions, |
|
|
|
getRewardFund, |
|
|
|
} from '@/api/composed'; |
|
|
|
import SvgIcon from '@jamescoyle/vue-icon'; |
|
|
|
import { |
|
|
|
mdiCircleMultipleOutline, |
|
|
|
mdiGreaterThanOrEqual, |
|
|
|
mdiNoteTextOutline, |
|
|
|
mdiTarget, |
|
|
|
} from '@mdi/js'; |
|
|
|
|
|
|
|
const route = useRoute(); |
|
|
|
const router = useRouter(); |
|
|
@@ -260,7 +252,7 @@ const fund = ref( |
|
|
|
} as GetRewardFundResponse | null, |
|
|
|
); |
|
|
|
const fundDetails = ref([{ |
|
|
|
title: '', |
|
|
|
icon: '', |
|
|
|
val: '', |
|
|
|
}]); |
|
|
|
|
|
|
@@ -271,19 +263,19 @@ if (!fund.value) { |
|
|
|
} |
|
|
|
fundDetails.value = [ |
|
|
|
{ |
|
|
|
title: 'Asset', |
|
|
|
icon: mdiCircleMultipleOutline, |
|
|
|
val: fund.value.fundInfo.asset, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: 'Min', |
|
|
|
icon: mdiGreaterThanOrEqual, |
|
|
|
val: `${fund.value.fundInfo.minContribution.toLocaleString()}`, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: 'Goal', |
|
|
|
icon: mdiTarget, |
|
|
|
val: `${fund.value.fundInfo.amountAvailable.toLocaleString()}`, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: 'Memo', |
|
|
|
icon: mdiNoteTextOutline, |
|
|
|
val: `"${fund.value.fundInfo.memo}"`, |
|
|
|
}, |
|
|
|
]; |
|
|
@@ -528,14 +520,27 @@ watch(data, (newVal) => { |
|
|
|
min-height 280px |
|
|
|
|
|
|
|
.fund-details |
|
|
|
width 182px |
|
|
|
display flex |
|
|
|
flex-direction row |
|
|
|
justify-content space-around |
|
|
|
background-color darkorange |
|
|
|
border-radius 4px |
|
|
|
list-style-type none |
|
|
|
margin 0 |
|
|
|
padding 8px 4px |
|
|
|
|
|
|
|
.detail-icon |
|
|
|
display flex |
|
|
|
justify-content center |
|
|
|
color #fff |
|
|
|
margin-bottom 8px |
|
|
|
|
|
|
|
.detail-text |
|
|
|
font-size 16px |
|
|
|
text-align center |
|
|
|
color #fff |
|
|
|
font-family "Passion One" |
|
|
|
|
|
|
|
#consolidate |
|
|
|
vertical-align middle |
|
|
|
|
|
|
|
@media screen and (min-width: 1024px) |
|
|
|
.fund-details |
|
|
|
max-width 14vw |
|
|
|
border-left 1px #777 solid |
|
|
|
padding-left 10px |
|
|
|
</style> |