<template> <div class="lg:flex-nowrap flex-wrap justify-between relative"> <slot name="stats" :node="node" :pubkey="pubkey" :target="target" :startDate="startDate" :endDate="endDate" :unit="unit" :dividend="dividend" :total="total" :issuers="issuers" :graph="graph" > <div class="leading-5 px-2 lg:px-0"> <div v-if="unit === 'DU'"> <span v-if="total && dividend" class="text-xl font-bold"> {{ !dividend ? 0 : (total / dividend).toFixed(2).replace('.', ',') }} </span> {{ ' DU' }}<sub>Ğ1</sub> </div> <div v-else> <span class="text-xl font-bold"> {{ total.toFixed(2).replace('.', ',') }} </span> {{ ' Ğ1' }} </div> <div class="text-xl font-extralight"> {{ `Montant collecté en ${months} mois` }} </div> </div> <div class="leading-5 px-2 lg:px-0"> <div class="text-xl font-bold">{{ issuers.length }}</div> <div class="text-xl font-extralight">{{ 'Donneurs' }}</div> </div> </slot> <div class=" flex items-center w-full lg:w-max justify-center px-2 lg:px-0 pt-2 lg:pt-0 " > <slot v-if="!isKeyCopied" name="button" class="w-full lg:w-max" :on-click="onClick" > <t-button class="w-full lg:w-max" @click="onClick"> {{ buttonText }} </t-button> </slot> <t-button v-else variant="success" class="w-full lg:w-max" @click="onClick" > <fa icon="check" /> Clé copiée </t-button> </div> </div> </template> <script> export default { name: 'G1Crowdfunding', props: { /** * Duniter node where to fetch data. */ node: { type: String, default: 'https://g1.duniter.org', }, /** * Pubkey of the crowdfunded wallet. */ pubkey: { type: String, required: true, }, /** * Amount target to reach. */ target: { type: Number, default: null, }, /** * Date of the begining of the crowdfunding * Default 3 months before today */ startDate: { type: [Date, String], default() { const d = new Date() d.setHours(0, 0, 0, 0) return new Date(d.setMonth(d.getMonth() - 3)) }, }, /** * Date of the begining of the crowdfunding * Default 3 months before today */ endDate: { type: [Date, String], default() { return new Date() }, }, /** * Display amount in Ğ1 or DU * Default: DU */ unit: { type: String, default: 'DU', }, buttonText: { type: String, default: 'Donner', }, }, data() { return { now: Math.round(Date.now() / 1000), total: 0, graph: [], mapDelta: [], issuers: [], percentage: 0, dividend: null, isKeyCopied: false, } }, computed: { endpoint() { // Build url from props. Prevent missing protocol. return ( /^https:\/\//.test(this.node) ? this.node : `https://${this.node}` ).replace(/\/$/, '') }, startDateTimestamp() { // TODO Check format starDate prop return Math.round(new Date(this.startDate).getTime() / 1000) }, months() { return ( this.endDate.getMonth() - this.startDate.getMonth() + 12 * (this.endDate.getFullYear() - this.startDate.getFullYear()) ) }, }, mounted() { this.fetchDividend() this.fetchHistory() }, methods: { async fetchDividend() { const dividend = JSON.parse(sessionStorage.getItem('current_dividend')) if (dividend) { this.dividend = dividend } else { const dividend = await fetch(`${this.endpoint}/blockchain/with/ud`) .then((resp) => resp.json()) .then( async (data) => await fetch( `${this.endpoint}/blockchain/block/${[ ...data.result.blocks, ].pop()}` ) .then((resp) => resp.json()) .then((data) => data.dividend / 100) ) this.dividend = dividend sessionStorage.setItem('current_dividend', JSON.stringify(dividend)) } }, async fetchHistory() { // Caches to avoid fetching each time the dropdown is opened const history = JSON.parse( sessionStorage.getItem(`crowdfunding_${this.pubkey}`) ) if (history) { this.total = history.total this.issuers = history.issuers this.graph = history.graph } else { await fetch( `${this.endpoint}/tx/history/${this.pubkey}/times/${this.startDateTimestamp}/${this.now}` ) .then((response) => response.json()) .then((response) => { const data = response.history.received this.buildData(data) }) // eslint-disable-next-line no-console .catch((error) => console.log('Erreur : ' + error)) // this.percentage = Math.round((this.total / this.target) * 100) } }, buildData(data) { let tmpTimestamp = this.startDateTimestamp for (const tx of data) { const issuer = tx.issuers[0] // Why ? To check if issuer is not the account ? aka sent transaction to himself ? if (issuer !== this.pubkey) { // store issuer if (!this.issuers.includes(issuer)) this.issuers.push(issuer) for (const output of tx.outputs) { // One tx can have many output. Keep only our pubkey output. if (output.includes(this.pubkey)) { const timestamp = tx.time const amountTx = Number(output.match(/^(\d+):/)[1]) / 100 if (timestamp !== tmpTimestamp) this.graph.push({ t: tmpTimestamp, y: this.total.toFixed(2), }) // const tday = 43200 + timestamp - (timestamp % 86400) // if (this.mapDelta[tday]) { // this.mapDelta[tday] += Math.round(amountTx) // } else { // this.mapDelta[tday] = Math.round(amountTx) // } // add tx amount to total this.total += amountTx tmpTimestamp = timestamp // // store for graph // this.arrayFinal.push( // { t: tmpTimestamp, y: this.total.toFixed(2) }, // { t: this.now, y: this.total.toFixed(2) } // ) } } } } sessionStorage.setItem( `crowdfunding_${this.pubkey}`, JSON.stringify({ total: this.total, issuers: this.issuers, graph: this.graph, }) ) }, onClick() { this.$copyText(this.pubkey) this.isKeyCopied = true }, }, } </script> <style lang="scss" scoped></style>