mirror of
https://github.com/mokuappio/serverless-invoices.git
synced 2025-10-27 07:51:08 -04:00
Add en translations.
This commit is contained in:
9
public/locales/en/bank-account-form.json
Normal file
9
public/locales/en/bank-account-form.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Bank account",
|
||||
"bank_name": "Bank name",
|
||||
"account_no": "Bank account details",
|
||||
"loading": "Loading",
|
||||
"done": "Done",
|
||||
"create": "Create",
|
||||
"notification_updated": "Updated"
|
||||
}
|
||||
6
public/locales/en/bank-accounts-list.json
Normal file
6
public/locales/en/bank-accounts-list.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"loading": "Loading",
|
||||
"bank": "Bank",
|
||||
"bank_account_details": "Bank account details",
|
||||
"add_bank_account": "Add bank account"
|
||||
}
|
||||
10
public/locales/en/client-fields.json
Normal file
10
public/locales/en/client-fields.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Label",
|
||||
"field": "Field",
|
||||
"delete_modal": {
|
||||
"title": "Delete field",
|
||||
"ok_title": "Delete",
|
||||
"cancel_title": "Dismiss"
|
||||
},
|
||||
"notification_deleted": "Deleted"
|
||||
}
|
||||
34
public/locales/en/client-form.json
Normal file
34
public/locales/en/client-form.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"title": "Client",
|
||||
"delete": "Delete",
|
||||
"done": "Done",
|
||||
"create": "Create",
|
||||
"loading": "Loading",
|
||||
"general": {
|
||||
"title": "General",
|
||||
"company_name": "Company name",
|
||||
"invoice_email": "Email"
|
||||
},
|
||||
"invoicing": {
|
||||
"title": "Invoicing",
|
||||
"currency": "Currency",
|
||||
"rate": "Hourly rate",
|
||||
"has_tax": "Apply taxes",
|
||||
"bank_account": "Bank account"
|
||||
},
|
||||
"address": {
|
||||
"title": "Address",
|
||||
"company_address": "Company address",
|
||||
"company_postal_code": "Postal code",
|
||||
"company_city": "City",
|
||||
"company_county": "County/State",
|
||||
"company_country": "Country"
|
||||
},
|
||||
"delete_modal": {
|
||||
"title": "Delete client",
|
||||
"ok_title": "Delete",
|
||||
"cancel_title": "Dismiss"
|
||||
},
|
||||
"notification_deleted": "Deleted",
|
||||
"notification_updated": "Updated"
|
||||
}
|
||||
6
public/locales/en/client-selector.json
Normal file
6
public/locales/en/client-selector.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"client": "Client",
|
||||
"create": "Create",
|
||||
"new": "new",
|
||||
"suggest_placeholder": "Search client"
|
||||
}
|
||||
3
public/locales/en/empty-state.json
Normal file
3
public/locales/en/empty-state.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"content": "Nothing here yet"
|
||||
}
|
||||
6
public/locales/en/import-modal.json
Normal file
6
public/locales/en/import-modal.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "Import data",
|
||||
"warning": "Your current data will be erased and overwritten with the imported data!",
|
||||
"button_text": "Select import file",
|
||||
"import-error": "Invalid JSON format"
|
||||
}
|
||||
5
public/locales/en/invoice-bank-details.json
Normal file
5
public/locales/en/invoice-bank-details.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"bank_name": "Add bank",
|
||||
"bank_account_no": "Add bank details",
|
||||
"bank_account_modal_title": "Choose bank account"
|
||||
}
|
||||
8
public/locales/en/invoice-client-details.json
Normal file
8
public/locales/en/invoice-client-details.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"client_address": "Address",
|
||||
"client_postal_code": "Postal code",
|
||||
"client_city": "City",
|
||||
"client_county": "County/State",
|
||||
"client_country": "Country",
|
||||
"client_email": "Client's email"
|
||||
}
|
||||
9
public/locales/en/invoice-company-details.json
Normal file
9
public/locales/en/invoice-company-details.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"your_company_name": "Your company name",
|
||||
"address": "Address",
|
||||
"postal_code": "Postal code",
|
||||
"city": "City",
|
||||
"county": "County/State",
|
||||
"country": "Country",
|
||||
"your_email": "Your email"
|
||||
}
|
||||
5
public/locales/en/invoice-contact-details.json
Normal file
5
public/locales/en/invoice-contact-details.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"add_website": "Add website",
|
||||
"add_email": "Add email",
|
||||
"add_phone": "Add phone"
|
||||
}
|
||||
19
public/locales/en/invoice-controls.json
Normal file
19
public/locales/en/invoice-controls.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"back": "Back",
|
||||
"book": "Book",
|
||||
"download_pdf": "Download PDF",
|
||||
"delete": "Delete",
|
||||
"delete_modal": {
|
||||
"title": "Delete client",
|
||||
"ok_title": "Delete",
|
||||
"cancel_title": "Dismiss"
|
||||
},
|
||||
"statuses": {
|
||||
"draft": "draft",
|
||||
"booked": "booked",
|
||||
"sent": "sent",
|
||||
"paid": "paid",
|
||||
"cancelled": "cancelled"
|
||||
},
|
||||
"notification_deleted": "Deleted"
|
||||
}
|
||||
3
public/locales/en/invoice-form.json
Normal file
3
public/locales/en/invoice-form.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"insert_note": "Insert note"
|
||||
}
|
||||
10
public/locales/en/invoice-header.json
Normal file
10
public/locales/en/invoice-header.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"invoice_title": "Invoice ",
|
||||
"invoice_number": "No.",
|
||||
"issued_at": "Issued at: ",
|
||||
"due_at": "Due at",
|
||||
"late_fee": "Late fee:",
|
||||
"add_late_fee": "Add late fee",
|
||||
"modal_issued_at_title": "Issued at"
|
||||
|
||||
}
|
||||
10
public/locales/en/team-fields.json
Normal file
10
public/locales/en/team-fields.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Label",
|
||||
"field": "Field",
|
||||
"delete_modal": {
|
||||
"title": "Delete field",
|
||||
"ok_title": "Delete",
|
||||
"cancel_title": "Dismiss"
|
||||
},
|
||||
"notification_delete": "Deleted"
|
||||
}
|
||||
27
public/locales/en/team-form.json
Normal file
27
public/locales/en/team-form.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"title": "Team",
|
||||
"done": "Done",
|
||||
"updated": "Updated",
|
||||
"loading": "Loading",
|
||||
"general": {
|
||||
"title": "General",
|
||||
"company_name": "Company Name",
|
||||
"contact_email": "Email",
|
||||
"contact_phone": "Phone",
|
||||
"website": "Website"
|
||||
},
|
||||
"invoicing": {
|
||||
"title": "Invoicing",
|
||||
"invoice_late_fee": "Late fee (%)",
|
||||
"invoice_due_days": "Payment terms, days",
|
||||
"currency": "Default currency"
|
||||
},
|
||||
"address": {
|
||||
"title": "Address",
|
||||
"company_address": "Company Address",
|
||||
"company_postal_code": "Postal code",
|
||||
"company_city": "City",
|
||||
"company_county": "County/State",
|
||||
"company_country": "Country"
|
||||
}
|
||||
}
|
||||
7
public/locales/en/team-logo.json
Normal file
7
public/locales/en/team-logo.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"modal_title": "Choose logo",
|
||||
"button_text": "Select from files",
|
||||
"logo_url": "Insert web url",
|
||||
"logo_url_err": "Logo has to be under 512kb.",
|
||||
"or": "or"
|
||||
}
|
||||
10
public/locales/en/team-taxes.json
Normal file
10
public/locales/en/team-taxes.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Label",
|
||||
"tax": "Tax",
|
||||
"delete_modal": {
|
||||
"title": "Delete tax",
|
||||
"ok_title": "Delete",
|
||||
"cancel_title": "Dismiss"
|
||||
},
|
||||
"notification_deleted": "Deleted"
|
||||
}
|
||||
8
public/locales/en/the-footer.json
Normal file
8
public/locales/en/the-footer.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"lights": "Lights",
|
||||
"title": "All your data is saved in your browser and not on any server.\n This application is truly serverless and only you have access to your data.",
|
||||
"what_about_my_data": "What about my data? ",
|
||||
"made_with": "Made with",
|
||||
"by": "by",
|
||||
"upgrade": "Upgrade"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div :class="`col-12 text-muted text-${align}`">
|
||||
<small>{{ content }}</small>
|
||||
<small>{{ content || $t('content') }}</small>
|
||||
<h4 class="mt-2">¯\_(ツ)_/¯</h4>
|
||||
<slot></slot>
|
||||
</div>
|
||||
@ -8,9 +8,10 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'empty-state' },
|
||||
props: {
|
||||
content: {
|
||||
default: 'Nothing here yet',
|
||||
default: null,
|
||||
},
|
||||
align: {
|
||||
default: 'center',
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
<BModal v-model="isOpen"
|
||||
centered
|
||||
hide-footer
|
||||
title="Import data"
|
||||
:title="$t('title')"
|
||||
size="md"
|
||||
content-class="bg-base dp--24 text-center">
|
||||
<p>
|
||||
<AppFileInput @selected="onSelected" button-text="Select import file"/>
|
||||
<AppFileInput @selected="onSelected" :button-text="$t('button_text')"/>
|
||||
<AppError :errors="errors" field="file"/>
|
||||
</p>
|
||||
<p>
|
||||
<small>Your current data will be erased and overwritten with the imported data!</small>
|
||||
<small>{{ $t('warning') }}</small>
|
||||
</p>
|
||||
</BModal>
|
||||
</template>
|
||||
@ -22,6 +22,7 @@ import Errors from '../utils/errors';
|
||||
import AppError from './form/AppError';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'import-modal' },
|
||||
components: {
|
||||
AppError,
|
||||
AppFileInput,
|
||||
@ -54,7 +55,7 @@ export default {
|
||||
this.close();
|
||||
} catch (e) {
|
||||
return this.errors.set({
|
||||
file: ['Invalid JSON format'],
|
||||
file: [this.$t('on-select-error')],
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<footer class="col-12 d-flex justify-content-between align-items-center text-secondary px-0 mt-3 d-print-none">
|
||||
<button class="btn btn-sm text-secondary" @click="toggleTheme">
|
||||
Lights {{ theme === 'dark' ? 'on' : 'off' }}
|
||||
{{ $t('lights') }}{{ theme === 'dark' ? 'on' : 'off' }}
|
||||
<i class="material-icons material-icons-round md-14 align-text-bottom ml-1">
|
||||
{{ theme === 'dark' ? 'wb_sunny' : 'brightness_2' }}
|
||||
</i>
|
||||
@ -9,15 +9,14 @@
|
||||
<LanguageSwitcher/>
|
||||
<div>
|
||||
<small v-b-tooltip.hover
|
||||
title="All your data is saved in your browser and not on any server.
|
||||
This application is truly serverless and only you have access to your data."
|
||||
:title="$t('title')"
|
||||
class="pointer">
|
||||
What about my data?
|
||||
{{ $t('what_about_my_data') }}
|
||||
</small>
|
||||
<small class="pl-2">
|
||||
Made with
|
||||
{{ $t('made_with') }}
|
||||
<i class="material-icons material-icons-round md-14 align-text-bottom">favorite</i>
|
||||
by
|
||||
{{ $t('by') }}
|
||||
<a href="https://mokuapp.io/" class="text-secondary" target="_blank">Moku</a>.
|
||||
</small>
|
||||
<a href="https://github.com/mokuappio/serverless-invoices"
|
||||
@ -32,7 +31,7 @@
|
||||
</a>
|
||||
<a href="https://app.mokuapp.io/"
|
||||
class="btn btn-sm btn-primary ml-2"
|
||||
target="_blank">Upgrade</a>
|
||||
target="_blank">{{ $t('upgrade') }}</a>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
@ -43,6 +42,7 @@ import { VBTooltip } from 'bootstrap-vue';
|
||||
import LanguageSwitcher from './LanguageSwitcher';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'the-footer' },
|
||||
components: { LanguageSwitcher },
|
||||
directives: {
|
||||
'b-tooltip': VBTooltip,
|
||||
|
||||
@ -2,38 +2,38 @@
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h4>Bank account</h4>
|
||||
<h4>{{ $t('bank_account') }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="bankAccount" class="row">
|
||||
<AppInput :value="bankAccount.bank_name"
|
||||
@change="updateProp({ bank_name: $event })"
|
||||
label="Bank name"
|
||||
:label="$t('bank_name')"
|
||||
field="bank_name"
|
||||
:errors="errors"
|
||||
class="col-sm-10"/>
|
||||
<AppTextarea :value="bankAccount.account_no"
|
||||
@change="updateProp({ account_no: $event })"
|
||||
label="Bank account details"
|
||||
field="account_no"
|
||||
:errors="errors"
|
||||
class="col-12"/>
|
||||
@change="updateProp({ account_no: $event })"
|
||||
:label="$t('account_no')"
|
||||
field="account_no"
|
||||
:errors="errors"
|
||||
class="col-12"/>
|
||||
</div>
|
||||
|
||||
<div v-else class="row">
|
||||
<div class="col-12 pt-3">
|
||||
<p>Loading..</p>
|
||||
<p>{{ $t('loading') }} ..</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3 text-right">
|
||||
<div class="col-12">
|
||||
<button v-if="!isNew" class="btn btn-primary"
|
||||
@click="$emit('done')">Done
|
||||
@click="$emit('done')">{{ $t('done') }}
|
||||
</button>
|
||||
<button v-if="isNew" class="btn btn-primary ml-2"
|
||||
:disabled="loading"
|
||||
@click="createBankAccount">Create
|
||||
@click="createBankAccount">{{ $t('create') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -47,6 +47,7 @@ import AppTextarea from '@/components/form/AppTextarea';
|
||||
import Errors from '@/utils/errors';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'bank-account-form' },
|
||||
components: {
|
||||
AppInput,
|
||||
AppTextarea,
|
||||
@ -74,7 +75,7 @@ export default {
|
||||
|
||||
return this.$store.dispatch('bankAccounts/updateBankAccount', props)
|
||||
.then(() => {
|
||||
NotificationService.success('Updated');
|
||||
NotificationService.success(this.$t('notification_updated'));
|
||||
})
|
||||
.catch(err => this.errors.set(err.errors));
|
||||
},
|
||||
|
||||
@ -1,37 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!bankAccounts">Loading</div>
|
||||
<div v-else-if="bankAccounts && bankAccounts.length > 0">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bank</th>
|
||||
<th>Bank account details</th>
|
||||
<th class="text-right"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="account in bankAccounts" :key="account.id"
|
||||
@click="onSelect(account)" :class="{pointer: $listeners.select }">
|
||||
<td>{{ account.bank_name }}</td>
|
||||
<td>{{ account.account_no }}</td>
|
||||
<td class="text-right">
|
||||
<i class="material-icons md-18 p-1 pointer"
|
||||
@click.stop="openBankAccountModal(account)">
|
||||
edit
|
||||
</i>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn btn-sm btn-link" @click="createNewAccount">Add bank account</button>
|
||||
<div>
|
||||
<div v-if="!bankAccounts">{{ $t('loading') }}</div>
|
||||
<div v-else-if="bankAccounts && bankAccounts.length > 0">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t('bank') }}</th>
|
||||
<th>{{ $t('bank_account_details') }}</th>
|
||||
<th class="text-right"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="account in bankAccounts" :key="account.id"
|
||||
@click="onSelect(account)" :class="{pointer: $listeners.select }">
|
||||
<td>{{ account.bank_name }}</td>
|
||||
<td>{{ account.account_no }}</td>
|
||||
<td class="text-right">
|
||||
<i class="material-icons md-18 p-1 pointer"
|
||||
@click.stop="openBankAccountModal(account)">
|
||||
edit
|
||||
</i>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn btn-sm btn-link" @click="createNewAccount">{{ $t('add_bank_account') }}</button>
|
||||
</div>
|
||||
<EmptyState v-else>
|
||||
<template v-slot>
|
||||
<button class="btn btn-sm btn-link" @click="createNewAccount">{{ $t('add_bank_account') }}</button>
|
||||
</template>
|
||||
</EmptyState>
|
||||
</div>
|
||||
<EmptyState v-else>
|
||||
<template v-slot>
|
||||
<button class="btn btn-sm btn-link" @click="createNewAccount">Add bank account</button>
|
||||
</template>
|
||||
</EmptyState>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
@ -39,6 +39,7 @@ import { formatDate } from '@/filters/date.filter';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'bank-accounts-list' },
|
||||
components: {
|
||||
EmptyState,
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div v-for="field in client.fields" :key="field.id" class="col-sm-6">
|
||||
<AppEditable :value="field.label"
|
||||
placeholder="Label"
|
||||
:placeholder="$t('label')"
|
||||
@change="updateFieldProp({ label: $event }, field)"/>
|
||||
<i class="material-icons md-18 float-right pointer" @click="removeField(field)">close</i>
|
||||
<AppInput :value="field.value" @change="updateFieldProp({ value: $event }, field)"
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="col-12">
|
||||
<button class="btn btn-sm btn-secondary" @click="addNewField">
|
||||
<i class="material-icons md-18">add</i>
|
||||
Field
|
||||
{{ $t('field') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,6 +22,7 @@ import AppInput from '@/components/form/AppInput';
|
||||
import AppEditable from '@/components/form/AppEditable';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'client-fields' },
|
||||
props: ['client'],
|
||||
components: {
|
||||
AppEditable,
|
||||
@ -37,17 +38,17 @@ export default {
|
||||
this.$store.dispatch('clientFields/addNewField', this.client.id);
|
||||
},
|
||||
async removeField(field) {
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`Delete field ${field.label}?`, {
|
||||
okTitle: 'Delete',
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`${this.$t('delete_modal.title')} ${field.label}?`, {
|
||||
okTitle: this.$t('delete_modal.ok_title'),
|
||||
okVariant: 'danger',
|
||||
cancelTitle: 'Dismiss',
|
||||
cancelTitle: this.$t('delete_modal.cancel_title'),
|
||||
cancelVariant: 'btn-link',
|
||||
contentClass: 'bg-base dp--24',
|
||||
});
|
||||
if (confirmed) {
|
||||
await this.$store.dispatch('clientFields/deleteClientField', field.id);
|
||||
try {
|
||||
NotificationService.success('Deleted');
|
||||
NotificationService.success(this.$t('notification_deleted'));
|
||||
} catch (err) {
|
||||
NotificationService.error(err.message);
|
||||
}
|
||||
|
||||
@ -2,50 +2,51 @@
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-between">
|
||||
<h4>Client</h4>
|
||||
<h4>{{ $t('title') }}</h4>
|
||||
<div v-if="client">
|
||||
<div v-if="!isNew">
|
||||
<b-dropdown variant="link" size="sm" no-caret right>
|
||||
<template slot="button-content">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</template>
|
||||
<b-dropdown-item-button @click="deleteClient">Delete</b-dropdown-item-button>
|
||||
<b-dropdown-item-button @click="deleteClient">{{ $t('delete') }}</b-dropdown-item-button>
|
||||
</b-dropdown>
|
||||
<button class="btn btn-sm btn-primary"
|
||||
@click="$emit('done')">Done
|
||||
@click="$emit('done')">{{ $t('done') }}
|
||||
</button>
|
||||
</div>
|
||||
<button v-else class="btn btn-primary ml-2"
|
||||
:disabled="loading"
|
||||
@click="createClient">Create
|
||||
@click="createClient">{{ $t('create') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<b-tabs v-if="client" nav-class="nav-tabs--simple mb-4" active-tab-class="active" class="row">
|
||||
<b-tab title="General" class="col-12">
|
||||
<b-tab :title="$t('general.title')" class="col-12">
|
||||
<div class="row">
|
||||
<AppInput :value="client.company_name" @change="updateProp({ company_name: $event })"
|
||||
label="Company Name" field="company_name" :errors="errors" class="col-12"/>
|
||||
:label="$t('general.company_name')" field="company_name" :errors="errors" class="col-12"/>
|
||||
<AppInput :value="client.invoice_email" @change="updateProp({ invoice_email: $event })"
|
||||
label="Email" field="invoice_email" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('general.invoice_email')" field="invoice_email" :errors="errors"
|
||||
class="col-sm-7"/>
|
||||
</div>
|
||||
|
||||
<ClientFields class="row" :client="client"/>
|
||||
</b-tab>
|
||||
|
||||
<b-tab title="Invoicing" class="col-12">
|
||||
<b-tab :title="$t('invoicing.title')" class="col-12">
|
||||
<div class="row">
|
||||
<AppInput :value="client.currency" @change="updateProp({ currency: $event })"
|
||||
label="Currency" field="currency" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.currency')" field="currency" :errors="errors" class="col-sm-4"/>
|
||||
<AppInput :value="client.rate" @change="updateProp({ rate: $event })"
|
||||
label="Hourly rate" field="rate" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.rate')" field="rate" :errors="errors" class="col-sm-4"/>
|
||||
<AppCheckbox :value="client.has_tax" @input="updateProp({ has_tax: $event })"
|
||||
label="Apply taxes" field="has_tax" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.has_tax')" field="has_tax" :errors="errors" class="col-sm-4"/>
|
||||
<AppSelect :value="client.bank_account"
|
||||
track-by="id"
|
||||
label="Bank account"
|
||||
:label="$t('invoicing.bank_account')"
|
||||
label-field="bank_name"
|
||||
:options="bankAccounts || []"
|
||||
@input="bankAccountChanged"
|
||||
@ -53,27 +54,30 @@
|
||||
</div>
|
||||
</b-tab>
|
||||
|
||||
<b-tab title="Address" class="col-12">
|
||||
<b-tab :title="$t('address.title')" class="col-12">
|
||||
<div class="row">
|
||||
<AppInput :value="client.company_address" @change="updateProp({ company_address: $event })"
|
||||
label="Company Address" field="company_address" :errors="errors"
|
||||
:label="$t('address.company_address')" field="company_address" :errors="errors"
|
||||
class="col-12"/>
|
||||
<AppInput :value="client.company_postal_code"
|
||||
@change="updateProp({ company_postal_code: $event })"
|
||||
label="Postal code" field="company_postal_code" :errors="errors"
|
||||
:label="$t('address.company_postal_code')" field="company_postal_code" :errors="errors"
|
||||
class="col-sm-5"/>
|
||||
<AppInput :value="client.company_city" @change="updateProp({ company_city: $event })"
|
||||
label="City" field="company_city" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('address.company_city')" field="company_city" :errors="errors"
|
||||
class="col-sm-7"/>
|
||||
<AppInput :value="client.company_county" @change="updateProp({ company_county: $event })"
|
||||
label="County/State" field="company_county" :errors="errors" class="col-sm-6"/>
|
||||
:label="$t('address.company_county')" field="company_county" :errors="errors"
|
||||
class="col-sm-6"/>
|
||||
<AppInput :value="client.company_country" @change="updateProp({ company_country: $event })"
|
||||
label="Country" field="company_country" :errors="errors" class="col-sm-6"/>
|
||||
:label="$t('address.company_country')" field="company_country" :errors="errors"
|
||||
class="col-sm-6"/>
|
||||
</div>
|
||||
</b-tab>
|
||||
|
||||
</b-tabs>
|
||||
|
||||
<div v-if="!client">Loading</div>
|
||||
<div v-if="!client">{{ $t('loading') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -89,6 +93,7 @@ import AppCheckbox from '@/components/form/AppCheckbox';
|
||||
import ClientFields from '@/components/clients/ClientFields';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'client-form' },
|
||||
components: {
|
||||
ClientFields,
|
||||
AppCheckbox,
|
||||
@ -135,7 +140,7 @@ export default {
|
||||
clientId: this.client.id,
|
||||
})
|
||||
.then(() => {
|
||||
NotificationService.success('Updated');
|
||||
NotificationService.success(this.$t('notification_updated'));
|
||||
})
|
||||
.catch(err => this.errors.set(err.errors));
|
||||
},
|
||||
@ -164,10 +169,10 @@ export default {
|
||||
});
|
||||
},
|
||||
async deleteClient() {
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`Delete client ${this.client.company_name}?`, {
|
||||
okTitle: 'Delete',
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`${this.$t('delete_modal.title')} ${this.client.company_name}?`, {
|
||||
okTitle: this.$t('ok_title'),
|
||||
okVariant: 'danger',
|
||||
cancelTitle: 'Dismiss',
|
||||
cancelTitle: this.$t('cancel_title'),
|
||||
cancelVariant: 'btn-link',
|
||||
contentClass: 'bg-base dp--24',
|
||||
});
|
||||
@ -175,7 +180,7 @@ export default {
|
||||
this.$emit('done');
|
||||
await this.$store.dispatch('clients/deleteClient', this.client.id);
|
||||
try {
|
||||
NotificationService.success('Deleted');
|
||||
NotificationService.success(this.$t('notification_deleted'));
|
||||
} catch (err) {
|
||||
NotificationService.error(err.message);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
ref="button"
|
||||
:tabindex="tabindex"
|
||||
@click="toggleOpen">
|
||||
<span v-if="!value">Client</span>
|
||||
<span v-if="!value">{{ $t('client') }}</span>
|
||||
<span v-else>{{ value }}</span>
|
||||
</div>
|
||||
<div class="search-popover__overlay" v-if="isOpen" @click="toggleOpen"></div>
|
||||
@ -13,7 +13,7 @@
|
||||
class="search-popover__select"
|
||||
v-show="isOpen"
|
||||
ref="suggest"
|
||||
:input-props="{placeholder: 'Search client', class: 'form-control'}"
|
||||
:input-props="{placeholder: $t('suggest_placeholder'), class: 'form-control'}"
|
||||
:suggestions="suggestions"
|
||||
:value="query"
|
||||
:get-suggestion-value="getSuggestionValue"
|
||||
@ -35,7 +35,7 @@
|
||||
@click="createNewClient"
|
||||
@keydown.up="returnToSuggestions">
|
||||
<i class="material-icons material-icons-round md-18">add</i>
|
||||
Create {{this.query ? `"${this.query}"` : 'new'}}
|
||||
{{ $t('create') }} {{this.query ? `"${this.query}"` : $t('new')}}
|
||||
<code class="ml-2 badge badge-secondary">ctrl + enter</code>
|
||||
</button>
|
||||
</template>
|
||||
@ -47,6 +47,7 @@
|
||||
import { VueAutosuggest } from 'vue-autosuggest';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'client-selector' },
|
||||
components: {
|
||||
VueAutosuggest,
|
||||
},
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
:errors="errors"
|
||||
:disabled="true"
|
||||
field="bank_name"
|
||||
placeholder="Add bank"
|
||||
:placeholder="$t('bank_name')"
|
||||
class="break-line"/>
|
||||
</strong>
|
||||
<AppEditable :value="invoice.bank_account_no"
|
||||
@ -14,11 +14,11 @@
|
||||
:errors="errors"
|
||||
:disabled="true"
|
||||
field="bank_account_no"
|
||||
placeholder="Add bank details"
|
||||
:placeholder="$t('bank_account_no')"
|
||||
class="break-line"/>
|
||||
<BModal id="bank_account_no"
|
||||
centered
|
||||
title="Choose bank account"
|
||||
:title="$t('bank_account_modal_title')"
|
||||
hide-footer
|
||||
size="lg"
|
||||
content-class="bg-base dp--24">
|
||||
@ -32,6 +32,7 @@ import BankAccountsList from '@/components/bank-accounts/BankAccountsList';
|
||||
import AppEditable from '@/components/form/AppEditable';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-bank-details' },
|
||||
props: ['invoice', 'errors'],
|
||||
components: {
|
||||
AppEditable,
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
</div>
|
||||
<AppEditable :value="invoice.client_address"
|
||||
suffix=", "
|
||||
placeholder="Address"
|
||||
:placeholder="$t('client_address')"
|
||||
@change="updateProp({ client_address: $event })"/>
|
||||
<AppEditable :value="invoice.client_postal_code"
|
||||
placeholder="Postal code"
|
||||
:placeholder="$t('client_postal_code')"
|
||||
class="break-line"
|
||||
@change="updateProp({ client_postal_code: $event })"/>
|
||||
<AppError :errors="errors" field="client_address"/>
|
||||
@ -17,14 +17,14 @@
|
||||
|
||||
<AppEditable :value="invoice.client_city"
|
||||
suffix=", "
|
||||
placeholder="City"
|
||||
:placeholder="$t('client_city')"
|
||||
@change="updateProp({ client_city: $event })"/>
|
||||
<AppEditable :value="invoice.client_county"
|
||||
suffix=", "
|
||||
placeholder="County/State"
|
||||
:placeholder="$t('client_county')"
|
||||
@change="updateProp({ client_county: $event })"/>
|
||||
<AppEditable :value="invoice.client_country"
|
||||
placeholder="Country"
|
||||
:placeholder="$t('client_country')"
|
||||
class="break-line"
|
||||
@change="updateProp({ client_country: $event })"/>
|
||||
<AppError :errors="errors" field="client_city"/>
|
||||
@ -37,7 +37,7 @@
|
||||
:errors="errors"
|
||||
field="client_email"
|
||||
class="break-line"
|
||||
placeholder="Client's email"
|
||||
:placeholder="$t('client_email')"
|
||||
@change="updateProp({ client_email: $event })"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -48,6 +48,7 @@ import ClientSelector from '@/components/clients/ClientSelector';
|
||||
import InvoiceClientFields from '@/components/invoices/InvoiceClientFields';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-client-details' },
|
||||
props: ['invoice', 'errors'],
|
||||
components: {
|
||||
AppError,
|
||||
|
||||
@ -4,16 +4,16 @@
|
||||
<AppEditable :value="invoice.from_name"
|
||||
:errors="errors"
|
||||
field="from_name"
|
||||
placeholder="Your company name"
|
||||
:placeholder="$t('your_company_name')"
|
||||
@change="updateProp({ from_name: $event })"/>
|
||||
<i class="material-icons md-18 ml-2 pointer d-print-none" @click="editTeam">edit</i>
|
||||
</strong>
|
||||
<AppEditable :value="invoice.from_address"
|
||||
suffix=", "
|
||||
placeholder="Address"
|
||||
:placeholder="$t('address')"
|
||||
@change="updateProp({ from_address: $event })"/>
|
||||
<AppEditable :value="invoice.from_postal_code"
|
||||
placeholder="Postal code"
|
||||
:placeholder="$t('postal_code')"
|
||||
class="break-line"
|
||||
@change="updateProp({ from_postal_code: $event })"/>
|
||||
<AppError :errors="errors" field="from_address"/>
|
||||
@ -21,14 +21,14 @@
|
||||
|
||||
<AppEditable :value="invoice.from_city"
|
||||
suffix=", "
|
||||
placeholder="City"
|
||||
:placeholder="$t('city')"
|
||||
@change="updateProp({ from_city: $event })"/>
|
||||
<AppEditable :value="invoice.from_county"
|
||||
suffix=", "
|
||||
placeholder="County/State"
|
||||
:placeholder="$t('county')"
|
||||
@change="updateProp({ from_county: $event })"/>
|
||||
<AppEditable :value="invoice.from_country"
|
||||
placeholder="Country"
|
||||
:placeholder="$t('country')"
|
||||
class="break-line"
|
||||
@change="updateProp({ from_country: $event })"/>
|
||||
<AppError :errors="errors" field="from_city"/>
|
||||
@ -40,7 +40,7 @@
|
||||
<AppEditable :value="invoice.from_email"
|
||||
:errors="errors"
|
||||
field="from_email"
|
||||
placeholder="Your email"
|
||||
:placeholder="$t('your_email')"
|
||||
@change="updateProp({ from_email: $event })"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -50,6 +50,7 @@ import InvoiceTeamFields from '@/components/invoices/InvoiceTeamFields';
|
||||
import AppEditable from '../form/AppEditable';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-company-details' },
|
||||
props: ['invoice', 'errors'],
|
||||
components: {
|
||||
AppEditable,
|
||||
|
||||
@ -3,19 +3,19 @@
|
||||
<AppEditable :value="invoice.from_website"
|
||||
:errors="errors"
|
||||
field="from_website"
|
||||
placeholder="Add website"
|
||||
:placeholder="$t('add_website')"
|
||||
class="break-line"
|
||||
@change="updateProp({ from_website: $event })"/>
|
||||
<AppEditable :value="invoice.from_email"
|
||||
:errors="errors"
|
||||
field="from_email"
|
||||
placeholder="Add email"
|
||||
:placeholder="$t('add_email')"
|
||||
class="break-line"
|
||||
@change="updateProp({ from_email: $event })"/>
|
||||
<AppEditable :value="invoice.from_phone"
|
||||
:errors="errors"
|
||||
field="from_phone"
|
||||
placeholder="Add phone"
|
||||
:placeholder="$t('add_phone')"
|
||||
@change="updateProp({ from_phone: $event })"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -23,6 +23,7 @@
|
||||
import AppEditable from '../form/AppEditable';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-contact-details' },
|
||||
props: ['invoice', 'errors'],
|
||||
components: {
|
||||
AppEditable,
|
||||
|
||||
@ -2,25 +2,26 @@
|
||||
<div class="row" v-if="invoice">
|
||||
<div class="col-12 mb-4 d-flex justify-content-between align-items-start">
|
||||
<router-link class="btn btn-sm btn-light btn--icon-left"
|
||||
:to="{name: 'invoices'}">
|
||||
:to="{name: 'invoices'}">
|
||||
<i class="material-icons">arrow_back</i>
|
||||
<span class="d-inline-block">Back</span>
|
||||
<span class="d-inline-block">{{ $t('back') }}</span>
|
||||
</router-link>
|
||||
<div class="d-flex align-items-center">
|
||||
<AppSelect :value="invoice.status"
|
||||
<AppSelect :value="getStatusObj"
|
||||
class="mb-0 mr-2 text-capitalize multiselect--capitalize"
|
||||
:options="['draft', 'booked', 'sent', 'paid', 'cancelled']"
|
||||
@input="updateProp({status: $event})"/>
|
||||
:options="invoiceStatuses"
|
||||
label-field="name"
|
||||
@input="updateProp({status: $event.value})"/>
|
||||
<button class="btn btn-sm btn-outline-dark"
|
||||
v-if="invoice.status === 'draft'"
|
||||
@click="bookInvoice">Book
|
||||
@click="bookInvoice">{{ $t('book') }}
|
||||
</button>
|
||||
<b-dropdown variant="link" size="sm" no-caret right>
|
||||
<template slot="button-content">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</template>
|
||||
<b-dropdown-item-button @click="print">Download PDF</b-dropdown-item-button>
|
||||
<b-dropdown-item-button @click="deleteInvoice">Delete</b-dropdown-item-button>
|
||||
<b-dropdown-item-button @click="print">{{ $t('download_pdf') }} </b-dropdown-item-button>
|
||||
<b-dropdown-item-button @click="deleteInvoice">{{ $t('delete') }}</b-dropdown-item-button>
|
||||
</b-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
@ -34,6 +35,7 @@ import { BDropdown, BDropdownItemButton } from 'bootstrap-vue';
|
||||
import AppSelect from '@/components/form/AppSelect';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-controls' },
|
||||
components: {
|
||||
BDropdown,
|
||||
BDropdownItemButton,
|
||||
@ -43,13 +45,36 @@ export default {
|
||||
...mapGetters({
|
||||
invoice: 'invoices/invoice',
|
||||
}),
|
||||
getStatusObj() {
|
||||
const test = this.invoiceStatuses
|
||||
.find(obj => obj.value === this.invoice.status);
|
||||
return test;
|
||||
},
|
||||
invoiceStatuses() {
|
||||
return [{
|
||||
value: 'draft',
|
||||
name: this.$t('statuses.draft'),
|
||||
}, {
|
||||
value: 'booked',
|
||||
name: this.$t('statuses.booked'),
|
||||
}, {
|
||||
value: 'sent',
|
||||
name: this.$t('statuses.sent'),
|
||||
}, {
|
||||
value: 'paid',
|
||||
name: this.$t('statuses.paid'),
|
||||
}, {
|
||||
value: 'cancelled',
|
||||
name: this.$t('statuses.cancelled'),
|
||||
}];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async deleteInvoice() {
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`Delete invoice ${this.invoice.number}?`, {
|
||||
okTitle: 'Delete',
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`${this.$t('delete_modal.title')} ${this.invoice.number}?`, {
|
||||
okTitle: this.$t('delete_modal.ok_title'),
|
||||
okVariant: 'danger',
|
||||
cancelTitle: 'Dismiss',
|
||||
cancelTitle: this.$t('delete_modal.cancel_title'),
|
||||
cancelVariant: 'btn-link',
|
||||
contentClass: 'bg-base dp--24',
|
||||
});
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<div class="row mt-3">
|
||||
<AppEditable :value="invoice.notes"
|
||||
class="col-12"
|
||||
placeholder="Insert note"
|
||||
:placeholder="$t('insert_note')"
|
||||
@change="updateProp({ notes: $event })"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -54,6 +54,7 @@ import InvoiceRowsHeader from '@/components/invoices/InvoiceRowsHeader';
|
||||
import InvoiceAddRowBtn from '@/components/invoices/InvoiceAddRowBtn';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-form' },
|
||||
components: {
|
||||
InvoiceAddRowBtn,
|
||||
TeamLogo,
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h3>
|
||||
Invoice
|
||||
{{ $t('invoice_title') }}
|
||||
<AppEditable :value="invoice.number"
|
||||
:errors="errors"
|
||||
field="number"
|
||||
placeholder="NO."
|
||||
:placeholder="$t('invoice_number')"
|
||||
@change="updateProp({ number: $event })"/>
|
||||
</h3>
|
||||
Issued at: <span class="editable__item" v-b-modal.modal_issued_at>{{ invoice.issued_at | date('D. MMM YYYY', 'YYYY-MM-DD') }}</span>
|
||||
{{ $t('issued_at') }}
|
||||
<span class="editable__item" v-b-modal.modal_issued_at>{{ invoice.issued_at | date('D. MMM YYYY', 'YYYY-MM-DD') }}</span>
|
||||
<BModal id="modal_issued_at"
|
||||
centered
|
||||
title="Issued at"
|
||||
:title="$t('modal_issued_at_title')"
|
||||
hide-footer
|
||||
size="sm"
|
||||
content-class="bg-base dp--24">
|
||||
@ -21,10 +22,12 @@
|
||||
:inline="true"
|
||||
field="issued_at"/>
|
||||
</BModal>
|
||||
<br>Due at: <span class="editable__item" v-b-modal.modal_due_at>{{ invoice.due_at | date('D. MMM YYYY', 'YYYY-MM-DD') }}</span>
|
||||
<br>{{ $t('due_at') }}:
|
||||
<span class="editable__item"
|
||||
v-b-modal.modal_due_at>{{ invoice.due_at | date('D. MMM YYYY', 'YYYY-MM-DD') }}</span>
|
||||
<BModal id="modal_due_at"
|
||||
centered
|
||||
title="Due at"
|
||||
:title="$t('due_at')"
|
||||
hide-footer
|
||||
size="sm"
|
||||
content-class="bg-base dp--24">
|
||||
@ -34,12 +37,12 @@
|
||||
:inline="true"
|
||||
field="due_at"/>
|
||||
</BModal>
|
||||
<br>Late fee:
|
||||
<br>{{ $t('due_at') }}
|
||||
<AppEditable :value="invoice.late_fee | currency"
|
||||
:errors="errors"
|
||||
suffix="%"
|
||||
field="late_fee"
|
||||
placeholder="Add late fee"
|
||||
:placeholder="$t('add_late_fee')"
|
||||
@change="updateProp({ late_fee: $event })"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -51,6 +54,7 @@ import { formatDate } from '@/filters/date.filter';
|
||||
import { formatCurrency } from '@/filters/currency.filter';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'invoice-header' },
|
||||
props: ['invoice', 'errors'],
|
||||
components: {
|
||||
AppEditable,
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<AppEditable :value="row.quantity"
|
||||
:errors="errors"
|
||||
:field="`rows.${index}.quantity`"
|
||||
:placeholder="$('enter_quantity')"
|
||||
:placeholder="$t('enter_quantity')"
|
||||
@change="updateProp({ quantity: $event })"/>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div v-for="field in team.fields" :key="field.id" class="col-sm-6">
|
||||
<AppEditable :value="field.label"
|
||||
placeholder="Label"
|
||||
:placeholder="$t('label')"
|
||||
@change="updateFieldProp({ label: $event }, field)"/>
|
||||
<i class="material-icons md-18 float-right pointer" @click="removeField(field)">close</i>
|
||||
<AppInput :value="field.value" @change="updateFieldProp({ value: $event }, field)"
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="col-12">
|
||||
<button class="btn btn-sm btn-secondary" @click="addNewField">
|
||||
<i class="material-icons md-18">add</i>
|
||||
Field
|
||||
{{ $t('field') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,6 +22,7 @@ import AppInput from '@/components/form/AppInput';
|
||||
import AppEditable from '@/components/form/AppEditable';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'team-fields' },
|
||||
props: ['team'],
|
||||
components: {
|
||||
AppEditable,
|
||||
@ -32,17 +33,17 @@ export default {
|
||||
this.$store.dispatch('teamFields/addNewField', this.team.id);
|
||||
},
|
||||
async removeField(field) {
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`Delete field ${field.label}?`, {
|
||||
okTitle: 'Delete',
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`${this.$t('delete_modal.title')} ${field.label}?`, {
|
||||
okTitle: this.$t('delete_modal.ok_title'),
|
||||
okVariant: 'danger',
|
||||
cancelTitle: 'Dismiss',
|
||||
cancelTitle: this.$t('delete_modal.cancel_title'),
|
||||
cancelVariant: 'btn-link',
|
||||
contentClass: 'bg-base dp--24',
|
||||
});
|
||||
if (confirmed) {
|
||||
await this.$store.dispatch('teamFields/deleteTeamField', field.id);
|
||||
try {
|
||||
NotificationService.success('Deleted');
|
||||
NotificationService.success(this.$t('notification_delete'));
|
||||
} catch (err) {
|
||||
NotificationService.error(err.message);
|
||||
}
|
||||
|
||||
@ -2,62 +2,62 @@
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-between">
|
||||
<h4>Team</h4>
|
||||
<h4>{{ $t('title') }}</h4>
|
||||
<div v-if="team">
|
||||
<button class="btn btn-sm btn-primary"
|
||||
@click="$emit('done')">Done
|
||||
@click="$emit('done')">{{ $t('done') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<b-tabs v-if="team" nav-class="nav-tabs--simple mb-4" active-tab-class="active" class="row">
|
||||
<b-tab title="General" class="col-12">
|
||||
<b-tab :title="$t('general.title')" class="col-12">
|
||||
<div class="row">
|
||||
<TeamLogo :errors="errors" class="col-sm-4"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<AppInput :value="team.company_name" @change="updateProp({ company_name: $event })"
|
||||
label="Company Name" field="company_name" :errors="errors" class="col-12"/>
|
||||
:label="$t('general.company_name')" field="company_name" :errors="errors" class="col-12"/>
|
||||
<AppInput :value="team.contact_email" @change="updateProp({ contact_email: $event })"
|
||||
label="Email" field="contact_email" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('email')" field="contact_email" :errors="errors" class="col-sm-7"/>
|
||||
<AppInput :value="team.contact_phone" @change="updateProp({ contact_phone: $event })"
|
||||
label="Phone" field="contact_phone" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('contact_phone')" field="contact_phone" :errors="errors" class="col-sm-7"/>
|
||||
<AppInput :value="team.website" @change="updateProp({ website: $event })"
|
||||
label="Website" field="website" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('website')" field="website" :errors="errors" class="col-sm-7"/>
|
||||
</div>
|
||||
|
||||
<TeamFields class="row" :team="team"/>
|
||||
</b-tab>
|
||||
|
||||
<b-tab title="Invoicing" class="col-12">
|
||||
<b-tab :title="$t('invoicing.title')" class="col-12">
|
||||
<div class="row">
|
||||
<AppInput :value="team.invoice_late_fee" @change="updateProp({ invoice_late_fee: $event })"
|
||||
type="number"
|
||||
label="Late fee (%)" field="invoice_late_fee" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.invoice_late_fee')" field="invoice_late_fee" :errors="errors" class="col-sm-4"/>
|
||||
<AppInput :value="team.invoice_due_days" @change="updateProp({ invoice_due_days: $event })"
|
||||
type="number"
|
||||
label="Payment terms, days" field="invoice_due_days" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.invoice_due_days')" field="invoice_due_days" :errors="errors" class="col-sm-4"/>
|
||||
<AppInput :value="team.currency" @change="updateProp({ currency: $event })"
|
||||
label="Default currency" field="currency" :errors="errors" class="col-sm-4"/>
|
||||
:label="$t('invoicing.currency')" field="currency" :errors="errors" class="col-sm-4"/>
|
||||
</div>
|
||||
</b-tab>
|
||||
|
||||
<b-tab title="Address" class="col-12">
|
||||
<b-tab :title="$t('address.title')" class="col-12">
|
||||
<div class="row">
|
||||
<AppInput :value="team.company_address" @change="updateProp({ company_address: $event })"
|
||||
label="Company Address" field="company_address" :errors="errors"
|
||||
:label="$t('address.company_address')" field="company_address" :errors="errors"
|
||||
class="col-12"/>
|
||||
<AppInput :value="team.company_postal_code"
|
||||
@change="updateProp({ company_postal_code: $event })"
|
||||
label="Postal code" field="company_postal_code" :errors="errors"
|
||||
:label="$t('address.company_postal_code')" field="company_postal_code" :errors="errors"
|
||||
class="col-sm-5"/>
|
||||
<AppInput :value="team.company_city" @change="updateProp({ company_city: $event })"
|
||||
label="City" field="company_city" :errors="errors" class="col-sm-7"/>
|
||||
:label="$t('address.company_city')" field="company_city" :errors="errors" class="col-sm-7"/>
|
||||
<AppInput :value="team.company_county" @change="updateProp({ company_county: $event })"
|
||||
label="County/State" field="company_county" :errors="errors" class="col-sm-6"/>
|
||||
:label="$t('address.company_county')" field="company_county" :errors="errors" class="col-sm-6"/>
|
||||
<AppInput :value="team.company_country" @change="updateProp({ company_country: $event })"
|
||||
label="Country" field="company_country" :errors="errors" class="col-sm-6"/>
|
||||
:label="$t('address.company_country')" field="company_country" :errors="errors" class="col-sm-6"/>
|
||||
</div>
|
||||
</b-tab>
|
||||
|
||||
@ -67,7 +67,7 @@
|
||||
|
||||
</b-tabs>
|
||||
|
||||
<div v-if="!team">Loading</div>
|
||||
<div v-if="!team">{{ $t('loading') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -83,6 +83,7 @@ import TeamLogo from '@/components/team/TeamLogo';
|
||||
import TeamTaxes from '@/components/team/TeamTaxes';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'team-form' },
|
||||
components: {
|
||||
TeamLogo,
|
||||
TeamFields,
|
||||
@ -108,7 +109,7 @@ export default {
|
||||
|
||||
this.$store.dispatch('teams/updateTeam', props)
|
||||
.then(() => {
|
||||
NotificationService.success('Updated');
|
||||
NotificationService.success(this.$t('updated'));
|
||||
})
|
||||
.catch(err => this.errors.set(err.errors));
|
||||
},
|
||||
|
||||
@ -10,17 +10,17 @@
|
||||
<AppError :errors="errors" field="logo_url"/>
|
||||
<BModal v-model="isModalOpen"
|
||||
centered
|
||||
title="Choose logo"
|
||||
:title="$t('modal_title')"
|
||||
hide-footer
|
||||
size="sm"
|
||||
content-class="bg-base dp--24 text-center">
|
||||
<AppFileInput accept="image/*" class="mb-4" @selected="logoSelected"
|
||||
button-text="Select from files" output-type="base64"/>
|
||||
or
|
||||
:button-text="$t('button_text')" output-type="base64"/>
|
||||
{{ $t('or') }}
|
||||
<AppInput :value="team.logo_url"
|
||||
class="mt-4"
|
||||
@change="updateTeam({ logo_url: $event })"
|
||||
label="Insert web url"
|
||||
:label="$t('logo_url')"
|
||||
field="logo_url"
|
||||
:errors="errors"
|
||||
type="url"/>
|
||||
@ -35,6 +35,7 @@ import AppInput from '@/components/form/AppInput';
|
||||
import AppFileInput from '@/components/form/AppFileInput';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'team-logo' },
|
||||
props: ['errors'],
|
||||
components: {
|
||||
AppFileInput,
|
||||
@ -59,7 +60,7 @@ export default {
|
||||
logoSelected(payload) {
|
||||
this.errors.clear();
|
||||
if (payload.size / 1000 > 512) {
|
||||
return this.errors.set({ logo_url: ['Logo has to be under 512kb.'] });
|
||||
return this.errors.set({ logo_url: [this.$t('logo_url_err')] });
|
||||
}
|
||||
this.updateTeam({ logo_url: payload.content });
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div v-for="tax in taxes" :key="tax.id" class="col-sm-6">
|
||||
<AppEditable :value="tax.label"
|
||||
placeholder="Label"
|
||||
:placeholder="$t('label')"
|
||||
@change="updateTaxProp({ label: $event }, tax)"/>
|
||||
<i class="material-icons md-18 float-right pointer" @click="removeTax(tax)">close</i>
|
||||
<AppInput :value="tax.value" @change="updateTaxProp({ value: $event }, tax)"
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="col-12">
|
||||
<button class="btn btn-sm btn-secondary " @click="addNewTax">
|
||||
<i class="material-icons md-18">add</i>
|
||||
Tax
|
||||
{{ $t('tax') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -23,6 +23,7 @@ import AppEditable from '@/components/form/AppEditable';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
i18nOptions: { namespaces: 'team-taxes' },
|
||||
components: {
|
||||
AppEditable,
|
||||
AppInput,
|
||||
@ -37,17 +38,17 @@ export default {
|
||||
this.$store.dispatch('taxes/addNewTax');
|
||||
},
|
||||
async removeTax(field) {
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`Delete tax ${field.label}?`, {
|
||||
okTitle: 'Delete',
|
||||
const confirmed = await this.$bvModal.msgBoxConfirm(`${this.$t('delete_modal.title')} ${field.label}?`, {
|
||||
okTitle: this.$t('delete_modal.ok_title'),
|
||||
okVariant: 'danger',
|
||||
cancelTitle: 'Dismiss',
|
||||
cancelTitle: this.$t('delete_modal.cancel_title'),
|
||||
cancelVariant: 'btn-link',
|
||||
contentClass: 'bg-base dp--24',
|
||||
});
|
||||
if (confirmed) {
|
||||
await this.$store.dispatch('taxes/deleteTax', field.id);
|
||||
try {
|
||||
NotificationService.success('Deleted');
|
||||
NotificationService.success(this.$t('notification_deleted'));
|
||||
} catch (err) {
|
||||
NotificationService.error(err.message);
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ const initialized = i18next.init({
|
||||
fallbackLng: 'en',
|
||||
whitelist: ['en', 'et'],
|
||||
backend: {
|
||||
loadPath: 'locales/{{lng}}/{{ns}}.json',
|
||||
loadPath: `${window.location.origin}/locales/{{lng}}/{{ns}}.json`,
|
||||
},
|
||||
detection: {
|
||||
order: ['querystring', 'path', 'localStorage', 'navigator'],
|
||||
|
||||
Reference in New Issue
Block a user