(Account Card) Design Card

This commit is contained in:
Julien Calixte
2019-09-19 19:28:00 +02:00
parent b9e871e6e6
commit 6b1719987a
5 changed files with 169 additions and 32 deletions

View File

@@ -1,15 +1,21 @@
<template>
<div class="account-card box" :style="getColor(account.color)" @click="goToAccount(account._id)">
<div
class="account-card box"
:style="getColor(account.color)"
@click="goToAccount(account._id)"
>
<router-link
:class="{ 'is-primary': !account.color, 'is-white': account.color }"
:style="`color: ${findDarkValue(account.color)}`"
:to="{ name: 'account', params: { id: account._id } }"
>{{ account.name }}</router-link>
>{{ account.name }}</router-link
>
<div v-if="account.isPublic">
<awe-icon icon="users" />
</div>
<div :id="`chart-${account._id}`" class="ct-chart ct-golden-section"></div>
<br />
{{ account.users && account.users.map(u => u.alias).join(', ') }}
{{ account.users && account.users.map((u) => u.alias).join(', ') }}
</div>
</template>
@@ -21,11 +27,51 @@ import accountService from '@/services/AccountService'
import IAccount from '@/models/IAccount'
import IColor from '@/models/IColor'
import FabButton from '@/components/FabButton.vue'
import ITransaction from '../models/ITransaction'
import TransactionService from '../services/TransactionService'
import Chartist from 'chartist'
import TransactionType from '../enums/TransactionType'
import colors from '../data/colors'
@Component
export default class AccountCard extends Vue {
@Prop({ type: Object, required: true })
public account!: IAccount
public transactions: ITransaction[] = []
public async mounted() {
this.transactions = await TransactionService.getAllByAccountId(
this.account._id
)
const data = {
labels: this.labels,
series: [this.sumOfTransactions]
}
const chartId = `#chart-${this.account._id}`
// tslint:disable-next-line:no-unused-expression
new Chartist.Bar(chartId, data, {})
setTimeout(() => {
const color = colors.find((c) => c.value === this.account.color)
if (!color) {
return
}
const bars = document.querySelectorAll(
`${chartId} .ct-bar`
) as NodeListOf<HTMLElement>
bars.forEach((bar) => (bar.style.stroke = color.darkValue || 'red'))
}, 500)
}
public findDarkValue(color: string): string | null {
return findDarkValue(color)
}
public goToAccount(id: string): void {
this.$router.push({ name: 'account', params: { id } })
}
public getColor(color: string | null): any | null {
if (!color) {
@@ -37,18 +83,57 @@ export default class AccountCard extends Vue {
}
}
public findDarkValue(color: string): string | null {
return findDarkValue(color)
public get amounts(): ITransaction[] {
return this.transactions.filter(
(transaction) => transaction.transactionType === TransactionType.normal
)
}
public goToAccount(id: string): void {
this.$router.push({ name: 'account', params: { id } })
public get labels(): string[] {
const dates = this.amounts.map((transaction) =>
this.dateToLabel(new Date(transaction.date))
)
return [...new Set(dates)]
}
public get sumOfTransactions(): number[] {
const sortedTransactions = [...this.amounts].sort((a, b) =>
a.date < b.date ? -1 : 1
)
const groups = sortedTransactions.reduce(
(group: { [key: string]: number }, transaction: ITransaction) => {
const date = this.dateToLabel(new Date(transaction.date))
if (!(date in group)) {
group[date] = 0
}
group[date] += transaction.amount
return group
},
{}
)
return Object.values(groups)
}
private dateToLabel(date: Date): string {
return `${(date.getMonth() + 1)
.toString()
.padStart(2, '0')}/${date.getFullYear()}`
}
}
</script>
<style lang="scss" scoped>
@import '../styles/variables';
@import '~chartist/dist/chartist.min.css';
.ct-chart {
.ct-series-a {
.ct-bar {
stroke: blue;
stroke-width: 10px;
}
}
}
.box {
border-radius: 8px;

View File

@@ -84,7 +84,11 @@ class TransactionService {
return await couchService.multipleSave(transactions)
}
public async getAllByAccountId(accountId: string): Promise<ITransaction[]> {
public async getAllByAccountId(accountId?: string): Promise<ITransaction[]> {
if (!accountId) {
return []
}
const response: PouchDB.Core.AllDocsResponse<
ITransaction
> = await couchService.getByPrefix<ITransaction>(`tra-${accountId}`)

View File

@@ -5,11 +5,21 @@
<ul>
<li>
<router-link
:to="{ name: 'account', params: { id: account._id }, hash: `#${transaction._id}` }"
>{{ account.name }}</router-link>
:to="{
name: 'account',
params: { id: account._id },
hash: `#${transaction._id}`
}"
>{{ account.name }}</router-link
>
</li>
<li class="is-active" v-if="transaction.tag && transaction.tag !== noTag">
<a href="#" @click.prevent>{{ transactionTagLabel[transaction.tag].label }}</a>
<li
class="is-active"
v-if="transaction.tag && transaction.tag !== noTag"
>
<a href="#" @click.prevent>{{
transactionTagLabel[transaction.tag].label
}}</a>
</li>
<li class="is-active">
<a href="#" @click.prevent>{{ transaction.name }}</a>
@@ -23,25 +33,32 @@
<span v-if="payForLabel.length > 1">{{ payForLabel.join(', ') }}</span>
<span v-else>{{ payForLabel[0] }}</span>
d'une somme de
<span
class="numeric"
>{{ transaction.amount | money(transaction.mainCurrency) }}</span>.
<span class="numeric">{{
transaction.amount | money(transaction.mainCurrency)
}}</span
>.
</div>
<div v-if="transaction.exchange" class="exchange">
<div v-if="currencies.length">
<hr />
<h2 class="subtitle is-2">Taux d'échange à date</h2>
<h2 class="subtitle is-2">Taux d'échange aujourd'hui</h2>
<div class="columns is-centered">
<div class="column">
<table class="table is-fullwidth is-striped is-bordered">
<caption>
<span class="numeric">{{ transaction.amount | money(transaction.mainCurrency) }}</span>
<span class="numeric">{{
transaction.amount | money(transaction.mainCurrency)
}}</span>
</caption>
<tbody>
<tr v-for="(currency, k) in currencies" :key="k">
<td
class="numeric"
>{{ (transaction.amount * transaction.exchange.rates[currency.code]) | moneypad(currency) }}</td>
<td class="numeric">
{{
(transaction.amount *
transaction.exchange.rates[currency.code])
| moneypad(currency)
}}
</td>
</tr>
</tbody>
</table>
@@ -49,26 +66,40 @@
<div class="column">
<table class="table is-fullwidth is-striped is-bordered">
<caption>
<span class="numeric">{{ 1 | money(transaction.mainCurrency) }}</span>
<span class="numeric">{{
1 | money(transaction.mainCurrency)
}}</span>
</caption>
<tbody>
<tr v-for="(currency, k) in currencies" :key="k">
<td
class="numeric"
>{{ ( transaction.exchange.rates[currency.code]) | moneypad(currency) }}</td>
<td class="numeric">
{{
transaction.exchange.rates[currency.code]
| moneypad(currency)
}}
</td>
</tr>
</tbody>
</table>
</div>
<div class="column">
<table class="table is-hoverable is-fullwidth is-striped is-bordered">
<caption>{{ $tc('transaction.money', currencies.length) }}</caption>
<table
class="table is-hoverable is-fullwidth is-striped is-bordered"
>
<caption>
{{
$tc('transaction.money', currencies.length)
}}
</caption>
<tbody>
<tr v-for="(currency, k) in currencies" :key="k">
<td>{{ 1 | money(currency) }}</td>
<td
class="numeric"
>{{ (1 / transaction.exchange.rates[currency.code]) | moneypad(transaction.mainCurrency) }}</td>
<td class="numeric">
{{
(1 / transaction.exchange.rates[currency.code])
| moneypad(transaction.mainCurrency)
}}
</td>
</tr>
</tbody>
</table>
@@ -77,7 +108,8 @@
</div>
</div>
<div v-else>
<online-view @online="retrieveExchange" />Le taux d'échange n'a pas pu être récupéré.
<online-view @online="retrieveExchange" />Le taux d'échange n'a pas pu
être récupéré.
</div>
<div class="buttons is-centered" v-if="!account.archive">
<router-link
@@ -85,8 +117,11 @@
tag="button"
class="button"
:to="{ name: 'transaction-update', params: { id } }"
>modifier</router-link>
<confirm-button class="is-danger" @confirm="removeTransaction">supprimer</confirm-button>
>modifier</router-link
>
<confirm-button class="is-danger" @confirm="removeTransaction"
>supprimer</confirm-button
>
</div>
</div>
</template>