Files
vaquant/src/views/accounts/AccountNew.vue
2020-04-11 14:26:31 +02:00

304 lines
8.7 KiB
Vue

<template>
<div class="account-new no-margin">
<h1 class="title is-1" v-t="'account.create'"></h1>
<form @submit.prevent="submitAccount">
<div class="columns is-multiline is-centered">
<div class="column is-two-thirds">
<h3 class="subtitle is-3">Nom</h3>
<div class="field">
<div class="control">
<input
type="text"
class="input"
maxlength="30"
v-model="name"
required
/>
</div>
<p class="help is-primary">
{{
$tc('validation.max_char', 30 - name.length, {
max: 30 - name.length
})
}}
</p>
</div>
</div>
<div class="column is-two-thirds">
<h3 class="subtitle is-3" v-t="'account.main_currency'"></h3>
<div class="control">
<div class="select is-fullwidth">
<select
name="main-currency"
id="main-currency"
v-model="mainCurrency"
>
<option v-for="(cur, k) in currencies" :key="k" :value="cur"
>{{ cur.name }} {{ cur.symbol }}</option
>
</select>
</div>
</div>
</div>
<div class="column is-two-thirds">
<h3 class="subtitle is-3">Compte privé / public</h3>
<div class="field">
<input
id="is-public"
type="checkbox"
name="is-public"
class="switch"
v-model="isPublic"
/>
<label for="is-public">{{ isPublic ? 'public' : 'privé' }}</label>
<p
class="help is-primary"
v-t="
isPublic
? 'account.publicInformation'
: 'account.privateInformation'
"
></p>
</div>
</div>
<div class="column is-two-thirds">
<color-picker v-model="color" />
</div>
<div class="column is-two-thirds">
<account-user-new v-model="users" />
</div>
<div class="column is-two-thirds">
<h3 class="subtitle is-3 title-currency" @click="toggleCurrencyShow">
<div class="icon-container">
<awe-icon
icon="chevron-right"
:rotation="currencyShow ? 90 : undefined"
/>
</div>
{{
$tc('account.used_currencies', accountCurrencies.length, {
count: accountCurrencies.length
})
}}
</h3>
<transition name="fade">
<div class="currency-list" v-if="currencyShow">
<div class="field">
<div class="columns no-margin is-multiline">
<div
class="column is-half"
v-for="(currency, k) in currencies"
:key="k"
>
<input
class="is-checkradio is-block is-medium"
type="checkbox"
:name="`cur-${currency.code}`"
:id="`cur-${currency.code}`"
v-model="accountCurrencies"
:value="currency"
:disabled="currency.code === mainCurrency.code"
/>
<label :for="`cur-${currency.code}`"
>{{ currency.name }} ({{
currency.symbol || currency.code
}})</label
>
</div>
</div>
</div>
</div>
</transition>
</div>
</div>
<div class="columns is-centered">
<div class="column is-two-thirds">
<button type="submit" class="button is-primary is-fullwidth is-large">
<awe-icon icon="check" />
</button>
</div>
</div>
</form>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import { Getter } from 'vuex-class'
import currencies from '@/data/currencies'
import IAccount from '@/models/IAccount'
import ICurrency from '@/models/ICurrency'
import accountService from '@/services/AccountService'
import queueNotifService from '@/services/QueueNotifService'
import IUser from '@/models/IUser'
import { slug } from '@/utils'
@Component({
components: {
'color-picker': () => import('@/components/ColorPicker.vue'),
'account-user-new': () => import('@/components/AccountUserNew.vue')
}
})
export default class AccountNew extends Vue {
@Getter
public user!: IUser | null
public name: string = ''
public currencies: ICurrency[] = currencies
public mainCurrency: ICurrency = currencies[0]
public accountCurrencies: ICurrency[] = [currencies[0]]
public color: string | null = null
public users: IUser[] = []
public currencyShow: boolean = false
public isPublic: boolean = false
public mounted(): void {
if (this.user && !this.user.alias) {
this.user.alias = this.user.userId
}
}
public toggleCurrencyShow(): void {
this.currencyShow = !this.currencyShow
}
public validate(users: IUser[]): boolean {
if (!this.name) {
queueNotifService.error('Le nom doit être rempli.')
return false
}
const aliases: string[] = users.map((user: IUser) =>
user.alias ? user.alias.toLowerCase() : ''
)
if (aliases.length === 0) {
queueNotifService.error(
'Au moins une personne doit être ajoutée au compte.'
)
return false
}
if (aliases.length !== new Set(aliases).size) {
queueNotifService.error('Les alias doivent être uniques.')
return false
}
if (this.user) {
const userIds: string[] = users.map((user: IUser) => user.userId)
if (userIds.length !== new Set(userIds).size) {
queueNotifService.error('Les identifiants doivent être uniques.')
return false
}
}
return true
}
public async submitAccount(): Promise<void> {
let users: IUser[] = this.user ? [this.user, ...this.users] : this.users
if (!this.validate(users)) {
return
}
users = users.map((u: IUser) => ({
userId: u.userId,
email: u.email,
slugEmail: u.slugEmail,
premium: u.premium,
alias: u.alias,
firstname: u.firstname,
lastname: u.lastname
}))
const userIds: string[] = users.map((u: IUser) => slug(u.userId))
const newAccount: IAccount = {
doctype: 'account',
name: this.name,
admin: this.user
? {
userId: this.user.userId,
email: this.user.email,
slugEmail: this.user.slugEmail,
premium: this.user.premium,
alias: this.user.alias,
firstname: this.user.firstname,
lastname: this.user.lastname
}
: null,
color: this.color,
users,
userIds,
mainCurrency: this.mainCurrency,
currencies: this.accountCurrencies,
isPublic: this.isPublic
}
const response: PouchDB.Core.Response = await accountService.add(newAccount)
if (response.ok) {
this.$router.push({ name: 'account', params: { id: response.id } })
} else {
// tslint:disable-next-line:no-console
console.warn(response)
queueNotifService.error(
`Une erreur s'est produite à la création d'un compte.`
)
}
}
@Watch('mainCurrency', { immediate: true })
public onMainCurrencyChange(
currency: ICurrency,
oldCurrency: ICurrency
): void {
if (oldCurrency) {
this.accountCurrencies = this.accountCurrencies.filter(
(c: ICurrency) => c.code !== oldCurrency.code
)
}
const cur: ICurrency | undefined = this.currencies.find(
(c: ICurrency) => c.code === currency.code
)
if (cur) {
const already: ICurrency | undefined = this.accountCurrencies.find(
(c: ICurrency) => c.code === cur.code
)
if (!already) {
this.accountCurrencies.push(cur)
}
}
}
}
</script>
<style lang="scss" scoped>
@import '~bulma-switch';
h3 {
max-width: 400px;
margin: auto;
}
.icon-container {
float: left;
svg {
transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1);
}
}
.title-currency {
&:hover {
cursor: pointer;
}
}
.currency-list {
margin-top: 10px;
max-height: 50vh;
overflow-y: auto;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s cubic-bezier(0.55, 0, 0.1, 1),
transform 0.3s cubic-bezier(0.55, 0, 0.1, 1);
}
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(-50px);
}
</style>