Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into auto-update

This commit is contained in:
jayvirsinh_gohil
2019-11-15 14:11:00 +05:30
80 changed files with 19516 additions and 362 deletions

View File

@ -35,9 +35,7 @@ class EnvironmentController extends Controller
{ {
$results = $this->EnvironmentManager->saveDatabaseVariables($request); $results = $this->EnvironmentManager->saveDatabaseVariables($request);
if(array_key_exists("success", $results)) { if(array_key_exists("success", $results)) {
Artisan::call('config:clear'); Artisan::call('config:clear');
Artisan::call('key:generate --force'); Artisan::call('key:generate --force');
Artisan::call('migrate --seed'); Artisan::call('migrate --seed');
@ -58,13 +56,30 @@ class EnvironmentController extends Controller
*/ */
public function saveMailEnvironment(MailEnvironmentRequest $request) public function saveMailEnvironment(MailEnvironmentRequest $request)
{ {
$setting = Setting::getSetting('profile_complete');
$results = $this->EnvironmentManager->saveMailVariables($request); $results = $this->EnvironmentManager->saveMailVariables($request);
if ($setting !== 'COMPLETED')
{
Setting::setSetting('profile_complete', 4); Setting::setSetting('profile_complete', 4);
}
return response()->json($results); return response()->json($results);
} }
public function getMailEnvironment()
{
$MailData = [
'mail_driver' => config('mail.driver'),
'mail_host' => config('mail.host'),
'mail_port' => config('mail.port'),
'mail_username' => config('mail.username'),
'mail_password' => config('mail.password'),
'mail_encryption' => config('mail.encryption')
];
return response()->json($MailData);
}
/** /**
* *

View File

@ -203,7 +203,7 @@ class OnboardingController extends Controller
); );
} }
Setting::setSetting('version','1.0.0'); Setting::setSetting('version', config('crater.version'));
Artisan::call('passport:install --force'); Artisan::call('passport:install --force');

View File

@ -49,12 +49,20 @@ class EnvironmentManager
'DB_PASSWORD='.$request->database_password."\n\n"; 'DB_PASSWORD='.$request->database_password."\n\n";
if (! $this->checkDatabaseConnection($request)) { if (! $this->checkDatabaseConnection($request)) {
return [ return [
'error' => 'connection_failed' 'error' => 'connection_failed'
]; ];
} else {
if(count(DB::connection()->select('SHOW TABLES'))) {
return [
'error' => 'database_should_be_empty'
];
}
} }
try { try {
file_put_contents($this->envPath, str_replace( file_put_contents($this->envPath, str_replace(
$oldDatabaseData, $oldDatabaseData,
$newDatabaseData, $newDatabaseData,
@ -101,7 +109,7 @@ class EnvironmentManager
'MAIL_USERNAME='.$request->mail_username."\n". 'MAIL_USERNAME='.$request->mail_username."\n".
'MAIL_PASSWORD='.$request->mail_password."\n". 'MAIL_PASSWORD='.$request->mail_password."\n".
'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n"; 'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n";
// dd($newMailData);
try { try {
file_put_contents($this->envPath, str_replace( file_put_contents($this->envPath, str_replace(

14
config/crater.php Normal file
View File

@ -0,0 +1,14 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Crater Requirements
|--------------------------------------------------------------------------
|
*/
'version' => '1.0.0',
];

View File

@ -15,10 +15,10 @@ class UsersTableSeeder extends Seeder
public function run() public function run()
{ {
User::create([ User::create([
'email' => 'admin@crater.in', 'email' => 'admin@craterapp.com',
'name' => 'Jane Doe', 'name' => 'Jane Doe',
'role' => 'admin', 'role' => 'admin',
'password' => Hash::make('admin@123') 'password' => Hash::make('crater@123')
]); ]);
Setting::setSetting('profile_complete', 0); Setting::setSetting('profile_complete', 0);

View File

@ -1,27 +0,0 @@
{
"authHost": "http://crater-vue.test",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"apiOriginAllow": {
"allowCors": false,
"allowOrigin": "",
"allowMethods": "",
"allowHeaders": ""
}
}

View File

@ -1,37 +0,0 @@
0 info it worked if it ends with ok
1 verbose cli [ 'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli 'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli 'run',
1 verbose cli 'watch' ]
2 info using npm@3.10.10
3 info using node@v6.11.2
4 verbose run-script [ 'prewatch', 'watch', 'postwatch' ]
5 info lifecycle @~prewatch: @
6 silly lifecycle @~prewatch: no script for prewatch, continuing
7 info lifecycle @~watch: @
8 verbose lifecycle @~watch: unsafe-perm in lifecycle true
9 verbose lifecycle @~watch: PATH: C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin;C:\laragon2\www\crater-vue\node_modules\.bin;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\laragon2\bin\php\php-7.2.5-Win32-VC15-x86;C:\ProgramData\ComposerSetup\bin;C:\Program Files\nodejs\;C:\Program Files\Git\cmd;C:\laragon2\bin\yarn\bin;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Java\jdk-10.0.1\bin;C:\Users\bytefury\AppData\Roaming\Composer\vendor\bin;C:\laragon\www\wp\node_modules\.bin;C:\laragon\www\Laravel\node_modules\webpack\bin;C:\Users\bytefury\AppData\Roaming\npm;C:\Program Files\Microsoft VS Code\bin;C:\Users\bytefury\AppData\Local\Microsoft\WindowsApps;
10 verbose lifecycle @~watch: CWD: C:\laragon2\www\crater-vue
11 silly lifecycle @~watch: Args: [ '/d /s /c',
11 silly lifecycle 'cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js' ]
12 verbose stack Error: kill ENOSYS
12 verbose stack at exports._errnoException (util.js:1020:11)
12 verbose stack at process.kill (internal/process.js:190:13)
12 verbose stack at process.listener (C:\Program Files\nodejs\node_modules\npm\node_modules\npmlog\node_modules\gauge\node_modules\signal-exit\index.js:86:15)
12 verbose stack at emitNone (events.js:91:20)
12 verbose stack at process.emit (events.js:185:7)
12 verbose stack at processEmit (C:\Program Files\nodejs\node_modules\npm\node_modules\npmlog\node_modules\gauge\node_modules\signal-exit\index.js:146:32)
12 verbose stack at processEmit (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-registry-client\node_modules\npmlog\node_modules\gauge\node_modules\signal-exit\index.js:146:32)
12 verbose stack at Signal.wrap.onsignal (internal/process.js:217:44)
13 verbose cwd C:\laragon2\www\crater-vue
14 error Windows_NT 10.0.17134
15 error argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "run" "watch"
16 error node v6.11.2
17 error npm v3.10.10
18 error code ENOSYS
19 error errno ENOSYS
20 error syscall kill
21 error kill ENOSYS
22 error If you need help, you may report this error at:
22 error <https://github.com/npm/npm/issues>
23 verbose exit [ 1, true ]

18556
public/assets/css/laraspace.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="check-circle"
class="svg-inline--fa fa-check-circle fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path
fill="#55547A"
d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z">
</path>
</svg>

After

Width:  |  Height:  |  Size: 658 B

View File

@ -0,0 +1,13 @@
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="envelope"
class="svg-inline--fa fa-envelope fa-w-16"
role="img" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path
fill="#55547A"
d="M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z">
</path>
</svg>

After

Width:  |  Height:  |  Size: 751 B

View File

@ -0,0 +1,14 @@
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="paper-plane"
class="svg-inline--fa fa-paper-plane fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path
fill="#55547A"
d="M476 3.2L12.5 270.6c-18.1 10.4-15.8 35.6 2.2 43.2L121 358.4l287.3-253.2c5.5-4.9 13.3 2.6 8.6 8.3L176 407v80.5c0 23.6 28.5 32.9 42.5 15.8L282 426l124.6 52.2c14.2 6 30.4-2.9 33-18.2l72-432C515 7.8 493.3-6.8 476 3.2z">
</path>
</svg>

After

Width:  |  Height:  |  Size: 510 B

View File

@ -0,0 +1,14 @@
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="times-circle"
class="svg-inline--fa fa-times-circle fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path
fill="#55547A"
d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z">
</path>
</svg>

After

Width:  |  Height:  |  Size: 674 B

View File

@ -0,0 +1,14 @@
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="trash"
class="svg-inline--fa fa-trash fa-w-14"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path
fill="#55547A"
d="M432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM53.2 467a48 48 0 0 0 47.9 45h245.8a48 48 0 0 0 47.9-45L416 128H32z">
</path>
</svg>

After

Width:  |  Height:  |  Size: 519 B

View File

@ -1,9 +1,29 @@
<template> <template>
<button :type="type" :class="btnClass" :disabled="disabled" @click="handleClick"> <button
<font-awesome-icon v-if="icon && !loading && !rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-left" /> :type="type"
<font-awesome-icon v-if="loading" :class="iconClass" icon="spinner" class="fa-spin"/> :class="btnClass"
:disabled="disabled || loading"
@click="handleClick"
>
<font-awesome-icon
v-if="icon && !loading && !rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-left"
/>
<font-awesome-icon
v-if="loading"
:class="iconClass"
icon="spinner"
class="fa-spin"
/>
<slot /> <slot />
<font-awesome-icon v-if="icon && !loading && rightIcon" :class="iconClass" :icon="icon" class="vue-icon icon-right" /> <font-awesome-icon
v-if="icon && !loading && rightIcon"
:class="iconClass"
:icon="icon"
class="vue-icon icon-right"
/>
</button> </button>
</template> </template>

View File

@ -4,7 +4,7 @@
<input <input
ref="baseInput" ref="baseInput"
v-model="inputValue" v-model="inputValue"
:type="type" :type="toggleType"
:disabled="disabled" :disabled="disabled"
:readonly="readOnly" :readonly="readOnly"
:name="name" :name="name"
@ -19,6 +19,9 @@
@keydown="handleKeyDownEnter" @keydown="handleKeyDownEnter"
@blur="handleFocusOut" @blur="handleFocusOut"
> >
<div v-if="showPassword && isAlignLeftIcon" style="cursor: pointer" @click="showPass = !showPass" >
<font-awesome-icon :icon="!showPass ?'eye-slash': 'eye'" class="right-icon" />
</div>
<font-awesome-icon v-if="icon && !isAlignLeftIcon" :icon="icon" class="right-icon" /> <font-awesome-icon v-if="icon && !isAlignLeftIcon" :icon="icon" class="right-icon" />
</div> </div>
</template> </template>
@ -77,12 +80,17 @@ export default {
autocomplete: { autocomplete: {
type: String, type: String,
default: 'on' default: 'on'
},
showPassword: {
type: Boolean,
default: false
} }
}, },
data () { data () {
return { return {
inputValue: this.value, inputValue: this.value,
focus: false focus: false,
showPass: false
} }
}, },
computed: { computed: {
@ -94,6 +102,12 @@ export default {
return true return true
} }
return false return false
},
toggleType () {
if (this.showPass) {
return 'text'
}
return this.type
} }
}, },
watch: { watch: {

View File

@ -1,6 +1,6 @@
<template> <template>
<transition name="fade"> <transition name="fade">
<div v-if="modalActive" class="base-modal" :class="'size-' + modalSize"> <div v-if="modalActive" :class="'size-' + modalSize" class="base-modal">
<div class="modal-body"> <div class="modal-body">
<div class="close-icon"> <div class="close-icon">
<font-awesome-icon class="mr-2" icon="times" @click="closeModal"/> <font-awesome-icon class="mr-2" icon="times" @click="closeModal"/>

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitCategoryData"> <form action="" @submit.prevent="submitCategoryData">
<div class="card-body"> <div class="card-body">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('expenses.category') }}<span class="required text-danger">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
ref="name" ref="name"

View File

@ -7,7 +7,7 @@
<tab id="basic-home" :name="$t('customers.basic_info')"> <tab id="basic-home" :name="$t('customers.basic_info')">
<div class="basic-info"> <div class="basic-info">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.display_name') }} <span class="required">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.display_name') }} <span class="required">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
ref="name" ref="name"
@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.primary_display_name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.primary_display_name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="formData.contact_name" v-model="formData.contact_name"
@ -34,7 +34,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('login.email') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('login.email') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.formData.email.$error" :invalid="$v.formData.email.$error"
@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $tc('settings.currencies.currency') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $tc('settings.currencies.currency') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="currency" v-model="currency"
@ -64,7 +64,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.formData.phone.$error" :invalid="$v.formData.phone.$error"
@ -79,7 +79,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.website') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.website') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="formData.website" v-model="formData.website"
@ -100,7 +100,7 @@
<tab id="basic-profile" :name="$t('customers.billing_address')"> <tab id="basic-profile" :name="$t('customers.billing_address')">
<div class="basic-info"> <div class="basic-info">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="billing.name" v-model="billing.name"
@ -110,7 +110,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.billing.phone.$error" :invalid="$v.billing.phone.$error"
@ -126,7 +126,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="billing.address_street_1" v-model="billing.address_street_1"
@ -155,7 +155,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingCountry" v-model="billingCountry"
@ -171,7 +171,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingState" v-model="billingState"
@ -187,7 +187,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="billingCity" v-model="billingCity"
@ -213,7 +213,7 @@
</div> --> </div> -->
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="billing.zip" v-model="billing.zip"
@ -236,7 +236,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.name') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.name') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="shipping.name" v-model="shipping.name"
@ -246,7 +246,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.phone') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.phone') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
:invalid="$v.shipping.phone.$error" :invalid="$v.shipping.phone.$error"
@ -262,7 +262,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.address') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.address') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="shipping.address_street_1" v-model="shipping.address_street_1"
@ -291,7 +291,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.country') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.country') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingCountry" v-model="shippingCountry"
@ -307,7 +307,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.state') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingState" v-model="shippingState"
@ -323,7 +323,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.city') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="shippingCity" v-model="shippingCity"
@ -339,7 +339,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('customers.zip_code') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-input <base-input
v-model="shipping.zip" v-model="shipping.zip"

View File

@ -3,7 +3,7 @@
<form action="" @submit.prevent="submitItemData"> <form action="" @submit.prevent="submitItemData">
<div class="card-body"> <div class="card-body">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label"> <label class="col-sm-4 col-form-label input-label">
{{ $t('items.name') }}<span class="required">*</span> {{ $t('items.name') }}<span class="required">*</span>
</label> </label>
<div class="col-sm-7"> <div class="col-sm-7">
@ -22,7 +22,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.price') }}<span class="required">*</span></label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.price') }}<span class="required">*</span></label>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="base-input"> <div class="base-input">
<money <money
@ -41,7 +41,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.unit') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.unit') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-select <base-select
v-model="formData.unit" v-model="formData.unit"
@ -54,7 +54,7 @@
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">{{ $t('items.description') }}</label> <label class="col-sm-4 col-form-label input-label">{{ $t('items.description') }}</label>
<div class="col-sm-7"> <div class="col-sm-7">
<base-text-area <base-text-area
v-model="formData.description" v-model="formData.description"
@ -121,7 +121,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
formData: { formData: {
name: null, name: null,

View File

@ -228,7 +228,13 @@ export default {
save_estimate: 'Save Estimate', save_estimate: 'Save Estimate',
confirm_conversion: 'You want to convert this Estimate into Invoice?', confirm_conversion: 'You want to convert this Estimate into Invoice?',
conversion_message: 'Conversion successful', conversion_message: 'Conversion successful',
confirm_send_estimate: 'This estimate will be sent via email to the customer',
confirm_mark_as_sent: 'This estimate will be marked as sent',
confirm_mark_as_accepted: 'This estimate will be marked as Accepted',
confirm_mark_as_rejected: 'This estimate will be marked as Rejected',
no_matching_estimates: 'There are no matching estimates!', no_matching_estimates: 'There are no matching estimates!',
mark_as_sent_successfully: 'Estimate marked as sent successfully',
send_estimate_successfully: 'Estimate sent successfully',
errors: { errors: {
required: 'Field is required' required: 'Field is required'
}, },
@ -303,7 +309,9 @@ export default {
send_invoice: 'Send Invoice', send_invoice: 'Send Invoice',
invoice_template: 'Invoice Template', invoice_template: 'Invoice Template',
template: 'Template', template: 'Template',
mark_as_sent: 'Mark as Sent', mark_as_sent: 'Mark as sent',
invoice_mark_as_sent: 'This invoice will be marked as sent',
confirm_send: 'This invoice will be sent via email to the customer',
invoice_date: 'Invoice Date', invoice_date: 'Invoice Date',
record_payment: 'Record Payment', record_payment: 'Record Payment',
add_new_invoice: 'Add New Invoice', add_new_invoice: 'Add New Invoice',
@ -317,6 +325,8 @@ export default {
list_of_invoices: 'This section will contain the list of invoices.', list_of_invoices: 'This section will contain the list of invoices.',
select_invoice: 'Select Invoice', select_invoice: 'Select Invoice',
no_matching_invoices: 'There are no matching invoices!', no_matching_invoices: 'There are no matching invoices!',
mark_as_sent_successfully: 'Invoice marked as sent successfully',
send_invoice_successfully: 'Invoice sent successfully',
item: { item: {
title: 'Item Title', title: 'Item Title',
description: 'Description', description: 'Description',
@ -522,7 +532,8 @@ export default {
preferences: 'Preferences', preferences: 'Preferences',
notifications: 'Notifications', notifications: 'Notifications',
tax_types: 'Tax Types', tax_types: 'Tax Types',
expense_category: 'Expense Categories' expense_category: 'Expense Categories',
update_app: 'Update App'
}, },
title: 'Settings', title: 'Settings',
setting: 'Settings | Settings', setting: 'Settings | Settings',
@ -604,8 +615,6 @@ export default {
estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.', estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.',
save: 'Save', save: 'Save',
email_save_message: 'Email saved successfully', email_save_message: 'Email saved successfully',
// invoice_viewed_message: 'Invoice viewed updated successfully',
// estimate_viewed_message: 'Estimate viewed updated successfully',
please_enter_email: 'Please Enter Email' please_enter_email: 'Please Enter Email'
}, },
tax_types: { tax_types: {
@ -615,7 +624,6 @@ export default {
add_new_tax: 'Add New Tax', add_new_tax: 'Add New Tax',
tax_settings: 'Tax Settings', tax_settings: 'Tax Settings',
tax_per_item: 'Tax Per Item', tax_per_item: 'Tax Per Item',
// tax_per_item_switch: 'Tax Per Item updated successfully',
tax_name: 'Tax Name', tax_name: 'Tax Name',
compound_tax: 'Compound Tax', compound_tax: 'Compound Tax',
percent: 'Percent', percent: 'Percent',
@ -624,6 +632,7 @@ export default {
created_message: 'Sales tax created successfully', created_message: 'Sales tax created successfully',
updated_message: 'Sales tax updated successfully', updated_message: 'Sales tax updated successfully',
deleted_message: 'Sales tax deleted successfully', deleted_message: 'Sales tax deleted successfully',
confirm_delete: 'You will not be able to recover this Tax Type',
already_in_use: 'Tax is already in use' already_in_use: 'Tax is already in use'
}, },
expense_category: { expense_category: {
@ -636,6 +645,7 @@ export default {
created_message: 'Category created successfully', created_message: 'Category created successfully',
deleted_message: 'Expense category deleted successfully', deleted_message: 'Expense category deleted successfully',
updated_message: 'Expense category updated successfully', updated_message: 'Expense category updated successfully',
confirm_delete: 'You will not be able to recover this Expense Category',
already_in_use: 'Category is already in use' already_in_use: 'Category is already in use'
}, },
preferences: { preferences: {
@ -651,11 +661,15 @@ export default {
preference: 'Preference | Preferences', preference: 'Preference | Preferences',
general_settings: 'Default preferences for the system.', general_settings: 'Default preferences for the system.',
updated_message: 'Preferences updated successfully', updated_message: 'Preferences updated successfully',
// set_discount_per_item_message: 'Discount set per item updated successfully',
select_language: 'select language', select_language: 'select language',
select_time_zone: 'select Time Zone', select_time_zone: 'select Time Zone',
select_date_formate: 'select Date Formate', select_date_formate: 'select Date Formate',
select_financial_year: 'select financial year' select_financial_year: 'select financial year'
},
update_app: {
title: 'Update App',
description: 'update app description',
update: 'Update'
} }
}, },
wizard: { wizard: {
@ -726,7 +740,8 @@ export default {
migrate_failed: 'Migrate Failed', migrate_failed: 'Migrate Failed',
database_variables_save_error: 'Unable to connect to the DB with Provided Values.', database_variables_save_error: 'Unable to connect to the DB with Provided Values.',
mail_variables_save_error: 'Email configuration failed.', mail_variables_save_error: 'Email configuration failed.',
connection_failed: 'Database Connection Failed' connection_failed: 'Database connection failed',
database_should_be_empty: 'Database should be empty'
}, },
success: { success: {
mail_variables_save_successfully: 'Email configured successfully', mail_variables_save_successfully: 'Email configured successfully',
@ -745,6 +760,7 @@ export default {
invalid_url: 'Invalid url (ex: http://www.crater.com)', invalid_url: 'Invalid url (ex: http://www.crater.com)',
required: 'Field is required', required: 'Field is required',
email_incorrect: 'Incorrect Email.', email_incorrect: 'Incorrect Email.',
email_already_taken: 'The email has already been taken.',
email_does_not_exist: "User with given email doesn't exist", email_does_not_exist: "User with given email doesn't exist",
send_reset_link: 'Send Reset Link', send_reset_link: 'Send Reset Link',
not_yet: 'Not yet? Send it again', not_yet: 'Not yet? Send it again',
@ -761,9 +777,9 @@ export default {
payment_greater_than_due_amount: 'Entered Payment is more than due amount of this invoice.', payment_greater_than_due_amount: 'Entered Payment is more than due amount of this invoice.',
quantity_maxlength: 'Quantity should not be greater than 10 digits.', quantity_maxlength: 'Quantity should not be greater than 10 digits.',
price_maxlength: 'Price should not be greater than 10 digits.', price_maxlength: 'Price should not be greater than 10 digits.',
price_minvalue: 'Price should be greater than 0 digits', price_minvalue: 'Price should be greater than 0.',
amount_maxlength: 'Amount should not be greater than 10 digits.', amount_maxlength: 'Amount should not be greater than 10 digits.',
amount_minvalue: 'Amount should be greater than 0 digits', amount_minvalue: 'Amount should be greater than 0.',
description_maxlength: 'Description should not be greater than 255 characters.', description_maxlength: 'Description should not be greater than 255 characters.',
maximum_options_error: 'Maximum of {max} options selected. First remove a selected option to select another.', maximum_options_error: 'Maximum of {max} options selected. First remove a selected option to select another.',
notes_maxlength: 'Notes should not be greater than 255 characters.', notes_maxlength: 'Notes should not be greater than 255 characters.',

View File

@ -228,12 +228,17 @@ export default {
estimate_template: 'Plantilla de estimación', estimate_template: 'Plantilla de estimación',
convert_to_invoice: 'Convertir a factura', convert_to_invoice: 'Convertir a factura',
mark_as_sent: 'Marcar como enviado', mark_as_sent: 'Marcar como enviado',
send_estimate: 'Enviar presupuesto',
record_payment: 'Registro de pago', record_payment: 'Registro de pago',
add_estimate: 'Agregar presupuesto', add_estimate: 'Agregar presupuesto',
save_estimate: 'Guardar estimación', save_estimate: 'Guardar estimación',
confirm_conversion: '¿Quiere convertir esta estimación en factura?', confirm_conversion: '¿Quiere convertir esta estimación en factura?',
conversion_message: 'Conversión exitosa', conversion_message: 'Conversión exitosa',
confirm_send_estimate: 'Esta estimación se enviará por correo electrónico al cliente',
confirm_mark_as_sent: 'Esta estimación se marcará como enviada',
confirm_mark_as_accepted: 'Esta estimación se marcará como Aceptada',
confirm_mark_as_rejected: 'Esta estimación se marcará como Rechazada',
mark_as_sent_successfully: 'Estimación marcada como enviada correctamente',
send_estimate_successfully: 'Estimación enviada con éxito',
errors: { errors: {
required: 'Se requiere campo' required: 'Se requiere campo'
}, },
@ -309,6 +314,8 @@ export default {
invoice_template: 'Plantilla de factura', invoice_template: 'Plantilla de factura',
template: 'Modelo', template: 'Modelo',
mark_as_sent: 'Marcar como enviado', mark_as_sent: 'Marcar como enviado',
invoice_mark_as_sent: 'Esta factura se marcará como enviada',
confirm_send: 'Estas facturas se enviarán por correo electrónico al cliente.',
invoice_date: 'Fecha de la factura', invoice_date: 'Fecha de la factura',
record_payment: 'Registro de pago', record_payment: 'Registro de pago',
add_new_invoice: 'Añadir nueva factura', add_new_invoice: 'Añadir nueva factura',
@ -321,6 +328,8 @@ export default {
no_invoices: '¡Aún no hay facturas!', no_invoices: '¡Aún no hay facturas!',
list_of_invoices: 'Esta sección contendrá la lista de facturas.', list_of_invoices: 'Esta sección contendrá la lista de facturas.',
select_invoice: 'Seleccionar factura', select_invoice: 'Seleccionar factura',
mark_as_sent_successfully: 'Factura marcada como enviada con éxito',
send_invoice_successfully: 'Factura enviada exitosamente',
item: { item: {
title: 'Título del artículo', title: 'Título del artículo',
description: 'Descripción', description: 'Descripción',
@ -524,7 +533,8 @@ export default {
preferences: 'Preferencias', preferences: 'Preferencias',
notifications: 'Notificaciones', notifications: 'Notificaciones',
tax_types: 'Tipos de impuestos', tax_types: 'Tipos de impuestos',
expense_category: 'Categorías de gastos' expense_category: 'Categorías de gastos',
update_app: 'Actualizar aplicación'
}, },
title: 'Configuraciones', title: 'Configuraciones',
setting: 'Configuraciones | Configuraciones', setting: 'Configuraciones | Configuraciones',
@ -551,6 +561,16 @@ export default {
action: 'Acción', action: 'Acción',
add_currency: 'Agregar moneda' add_currency: 'Agregar moneda'
}, },
mail: {
host: 'Host de correo',
port: 'Puerto de correo',
driver: 'Conductor de correo',
password: 'Contraseña de correo',
username: 'Nombre de usuario de correo',
mail_config: 'Configuración de correo',
encryption: 'Cifrado de correo',
mail_config_desc: 'Los detalles a continuación se utilizarán para actualizar el entorno de correo. También puede cambiar los detalles en cualquier momento después de iniciar sesión.'
},
pdf: { pdf: {
title: 'Configuración de PDF', title: 'Configuración de PDF',
footer_text: 'Texto de pie de página', footer_text: 'Texto de pie de página',
@ -613,6 +633,7 @@ export default {
created_message: 'Impuesto sobre las ventas creado con éxito', created_message: 'Impuesto sobre las ventas creado con éxito',
updated_message: 'Impuesto sobre ventas actualizado con éxito', updated_message: 'Impuesto sobre ventas actualizado con éxito',
deleted_message: 'Impuesto sobre las ventas eliminado con éxito', deleted_message: 'Impuesto sobre las ventas eliminado con éxito',
confirm_delete: 'No podrá recuperar este tipo de impuesto',
already_in_use: 'El impuesto ya está en uso.' already_in_use: 'El impuesto ya está en uso.'
}, },
expense_category: { expense_category: {
@ -625,6 +646,7 @@ export default {
created_message: 'Categoría creada con éxito', created_message: 'Categoría creada con éxito',
deleted_message: 'Categoría de gastos eliminada correctamente', deleted_message: 'Categoría de gastos eliminada correctamente',
updated_message: 'Categoría de gastos actualizada con éxito', updated_message: 'Categoría de gastos actualizada con éxito',
confirm_delete: 'No podrá recuperar esta categoría de gastos',
already_in_use: 'La categoría ya está en uso.' already_in_use: 'La categoría ya está en uso.'
}, },
preferences: { preferences: {
@ -644,6 +666,11 @@ export default {
select_time_zone: 'selecciona la zona horaria', select_time_zone: 'selecciona la zona horaria',
select_date_formate: 'seleccione formato de fecha', select_date_formate: 'seleccione formato de fecha',
select_financial_year: 'seleccione año financiero' select_financial_year: 'seleccione año financiero'
},
update_app: {
title: 'Actualizar aplicación',
description: 'actualizar la descripción de la aplicación',
update: 'Actualizar'
} }
}, },
wizard: { wizard: {
@ -742,7 +769,7 @@ export default {
numbers_only: 'Solo numeros.', numbers_only: 'Solo numeros.',
characters_only: 'Solo personajes.', characters_only: 'Solo personajes.',
password_incorrect: 'Las contraseñas deben ser idénticas', password_incorrect: 'Las contraseñas deben ser idénticas',
password_length: 'La contraseña debe tener 6 caracteres de longitud.', password_length: 'La contraseña debe tener 5 caracteres de longitud.',
qty_must_greater_than_zero: 'La cantidad debe ser mayor que cero.', qty_must_greater_than_zero: 'La cantidad debe ser mayor que cero.',
price_greater_than_zero: 'El precio debe ser mayor que cero.', price_greater_than_zero: 'El precio debe ser mayor que cero.',
payment_greater_than_zero: 'El pago debe ser mayor que cero.', payment_greater_than_zero: 'El pago debe ser mayor que cero.',

View File

@ -233,6 +233,12 @@ export default {
save_estimate: 'Sauvegarder lestimation', save_estimate: 'Sauvegarder lestimation',
confirm_conversion: 'Vous souhaitez convertir cette estimation en facture?', confirm_conversion: 'Vous souhaitez convertir cette estimation en facture?',
conversion_message: 'Conversion réussie', conversion_message: 'Conversion réussie',
confirm_send_estimate: 'Cette estimation sera envoyée par courrier électronique au client.',
confirm_mark_as_sent: 'Cette estimation sera marquée comme envoyé',
confirm_mark_as_accepted: 'Cette estimation sera marquée comme acceptée',
confirm_mark_as_rejected: 'Cette estimation sera marquée comme Rejetée',
mark_as_sent_successfully: 'Estimation marquée comme envoyée avec succès',
send_estimate_successfully: 'Estimation envoyée avec succès',
errors: { errors: {
required: 'Champ requis' required: 'Champ requis'
}, },
@ -308,6 +314,8 @@ export default {
invoice_template: 'Modèle de facture', invoice_template: 'Modèle de facture',
template: 'Modèle', template: 'Modèle',
mark_as_sent: 'Marquer comme envoyé', mark_as_sent: 'Marquer comme envoyé',
invoice_mark_as_sent: 'Cette facture sera marquée comme envoyé',
confirm_send: 'Cette facture sera envoyée par courrier électronique au client.',
invoice_date: 'Date de facturation', invoice_date: 'Date de facturation',
record_payment: 'Record de paiement', record_payment: 'Record de paiement',
add_new_invoice: 'Ajouter une nouvelle facture', add_new_invoice: 'Ajouter une nouvelle facture',
@ -320,6 +328,8 @@ export default {
no_invoices: 'Aucune facture pour le moment!', no_invoices: 'Aucune facture pour le moment!',
list_of_invoices: 'Cette section contiendra la liste des factures.', list_of_invoices: 'Cette section contiendra la liste des factures.',
select_invoice: 'Sélectionnez facture', select_invoice: 'Sélectionnez facture',
mark_as_sent_successfully: 'Facture marquée comme envoyée avec succès',
send_invoice_successfully: 'Facture envoyée avec succès',
item: { item: {
title: 'Titre de larticle', title: 'Titre de larticle',
description: 'La description', description: 'La description',
@ -523,7 +533,8 @@ export default {
preferences: 'Préférences', preferences: 'Préférences',
notifications: 'Les notifications', notifications: 'Les notifications',
tax_types: 'Types de taxe', tax_types: 'Types de taxe',
expense_category: 'Catégories de dépenses' expense_category: 'Catégories de dépenses',
update_app: "Mise à jour de l'application"
}, },
title: 'Paramètres', title: 'Paramètres',
setting: 'Paramètres | Paramètres', setting: 'Paramètres | Paramètres',
@ -548,7 +559,17 @@ export default {
right: 'Droite', right: 'Droite',
left: 'La gauche', left: 'La gauche',
action: 'action', action: 'action',
add_currency: 'Ajouter une devise', add_currency: 'Ajouter une devise'
},
mail: {
host: 'Mail Host',
port: 'Port mail',
driver: 'Pilote de courrier',
password: 'Mot de passe mail',
username: "Mail Nom d'utilisateur",
mail_config: 'Configuration du courrier',
encryption: 'Chiffrement du courrier',
mail_config_desc: "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
}, },
pdf: { pdf: {
title: 'Paramètre PDF', title: 'Paramètre PDF',
@ -614,6 +635,7 @@ export default {
created_message: 'La taxe de vente créée avec succès', created_message: 'La taxe de vente créée avec succès',
updated_message: 'La taxe de vente a été mise à jour avec succès', updated_message: 'La taxe de vente a été mise à jour avec succès',
deleted_message: 'La taxe de vente a été supprimée avec succès', deleted_message: 'La taxe de vente a été supprimée avec succès',
confirm_delete: 'Vous ne pourrez pas récupérer ce type de taxe',
already_in_use: 'La taxe est déjà utilisée' already_in_use: 'La taxe est déjà utilisée'
}, },
expense_category: { expense_category: {
@ -626,6 +648,7 @@ export default {
created_message: 'Catégorie créée avec succès', created_message: 'Catégorie créée avec succès',
deleted_message: 'La catégorie de dépenses a été supprimée avec succès', deleted_message: 'La catégorie de dépenses a été supprimée avec succès',
updated_message: 'Catégorie de dépenses mise à jour avec succès', updated_message: 'Catégorie de dépenses mise à jour avec succès',
confirm_delete: 'Vous ne pourrez pas récupérer cette catégorie de dépenses',
already_in_use: 'La catégorie est déjà utilisée' already_in_use: 'La catégorie est déjà utilisée'
}, },
preferences: { preferences: {
@ -646,6 +669,11 @@ export default {
select_time_zone: 'sélectionnez le fuseau horaire', select_time_zone: 'sélectionnez le fuseau horaire',
select_date_formate: 'sélectionnez Date Formate', select_date_formate: 'sélectionnez Date Formate',
select_financial_year: 'sélectionner lexercice' select_financial_year: 'sélectionner lexercice'
},
update_app: {
title: "Mise à jour de l'application",
description: "mettre à jour la description de l'application",
update: 'Mise à jour'
} }
}, },
wizard: { wizard: {
@ -744,7 +772,7 @@ export default {
numbers_only: 'Chiffres uniquement.', numbers_only: 'Chiffres uniquement.',
characters_only: 'Caractères seulement.', characters_only: 'Caractères seulement.',
password_incorrect: 'Les mots de passe doivent être identiques', password_incorrect: 'Les mots de passe doivent être identiques',
password_length: 'Le mot de passe doit comporter 6 caractères.', password_length: 'Le mot de passe doit comporter 5 caractères.',
qty_must_greater_than_zero: 'La quantité doit être supérieure à zéro.', qty_must_greater_than_zero: 'La quantité doit être supérieure à zéro.',
price_greater_than_zero: 'Le prix doit être supérieur à zéro.', price_greater_than_zero: 'Le prix doit être supérieur à zéro.',
payment_greater_than_zero: 'Le paiement doit être supérieur à zéro.', payment_greater_than_zero: 'Le paiement doit être supérieur à zéro.',

View File

@ -72,6 +72,7 @@ import UserProfile from './views/settings/UserProfile.vue'
import TaxTypes from './views/settings/TaxTypes.vue' import TaxTypes from './views/settings/TaxTypes.vue'
import ExpenseCategory from './views/settings/ExpenseCategory.vue' import ExpenseCategory from './views/settings/ExpenseCategory.vue'
import MailConfig from './views/settings/MailConfig.vue' import MailConfig from './views/settings/MailConfig.vue'
import UpdateApp from './views/settings/UpdateApp.vue'
import Wizard from './views/wizard/Index.vue' import Wizard from './views/wizard/Index.vue'
@ -337,6 +338,11 @@ const routes = [
path: 'notifications', path: 'notifications',
name: 'notifications', name: 'notifications',
component: Notifications component: Notifications
},
{
path: 'update-app',
name: 'updateapp',
component: UpdateApp
} }
] ]
} }

View File

@ -12,10 +12,15 @@
focus focus
type="email" type="email"
name="email" name="email"
@input="$v.loginData.email.$touch()"
/> />
<div v-if="$v.loginData.email.$error"> <div v-if="$v.loginData.email.$error">
<span v-if="!$v.loginData.email.required" class="text-danger">{{ $tc('validation.required') }}</span> <span v-if="!$v.loginData.email.required" class="text-danger">
<span v-if="!$v.loginData.email.email" class="text-danger"> {{ $tc('validation.email_incorrect') }} </span> {{ $tc('validation.required') }}
</span>
<span v-if="!$v.loginData.email.email" class="text-danger">
{{ $tc('validation.email_incorrect') }}
</span>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -25,8 +30,10 @@
:invalid="$v.loginData.password.$error" :invalid="$v.loginData.password.$error"
type="password" type="password"
name="password" name="password"
show-password
@input="$v.loginData.password.$touch()"
/> />
<div v-if="$v.loginData.email.$error"> <div v-if="$v.loginData.password.$error">
<span v-if="!$v.loginData.password.required" class="text-danger">{{ $tc('validation.required') }}</span> <span v-if="!$v.loginData.password.required" class="text-danger">{{ $tc('validation.required') }}</span>
<span v-if="!$v.loginData.password.minLength" class="text-danger"> {{ $tc('validation.password_min_length', $v.loginData.password.$params.minLength.min, {count: $v.loginData.password.$params.minLength.min}) }} </span> <span v-if="!$v.loginData.password.minLength" class="text-danger"> {{ $tc('validation.password_min_length', $v.loginData.password.$params.minLength.min, {count: $v.loginData.password.$params.minLength.min}) }} </span>
</div> </div>
@ -91,7 +98,7 @@ export default {
}, },
password: { password: {
required, required,
minLength: minLength(8) minLength: minLength(5)
} }
} }
}, },

View File

@ -219,7 +219,7 @@
</div> </div>
</div> </div>
<hr> <!-- second row complete --> <hr> <!-- second row complete -->
<div class="row same-address-checkbox-container"> <div class="same-address-checkbox-container">
<div class="p-1"> <div class="p-1">
<base-button ref="sameAddress" icon="copy" color="theme" class="btn-sm" @click="copyAddress(true)"> <base-button ref="sameAddress" icon="copy" color="theme" class="btn-sm" @click="copyAddress(true)">
{{ $t('customers.copy_billing_address') }} {{ $t('customers.copy_billing_address') }}
@ -624,17 +624,20 @@ export default {
this.isLoading = true this.isLoading = true
this.formData.currency_id = this.currency.id this.formData.currency_id = this.currency.id
} }
try {
let response = await this.addCustomer(this.formData) let response = await this.addCustomer(this.formData)
if (response.data.success) { if (response.data.success) {
window.toastr['success'](this.$t('customers.created_message')) window.toastr['success'](this.$t('customers.created_message'))
this.$router.push('/admin/customers') this.$router.push('/admin/customers')
this.isLoading = false this.isLoading = false
return true return true
} }
} catch (err) {
window.toastr['error'](response.data.error) if (err.response.data.errors.email) {
this.isLoading = false
window.toastr['error'](this.$t('validation.email_already_taken'))
}
}
} }
}, },
async fetchBillingState () { async fetchBillingState () {

View File

@ -343,7 +343,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('customers.confirm_delete'), text: this.$tc('customers.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -363,7 +363,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('customers.confirm_delete', 2), text: this.$tc('customers.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="app" class="main-content"> <div id="app" class="main-content dashboard">
<div class="row"> <div class="row">
<div class="dash-item col-sm-6"> <div class="dash-item col-sm-6">
<router-link slot="item-title" to="/admin/invoices"> <router-link slot="item-title" to="/admin/invoices">
@ -168,7 +168,7 @@
> >
<table-column :label="$t('dashboard.recent_invoices_card.due_on')" show="formattedDueDate" /> <table-column :label="$t('dashboard.recent_invoices_card.due_on')" show="formattedDueDate" />
<table-column :label="$t('dashboard.recent_invoices_card.customer')" show="user.name" /> <table-column :label="$t('dashboard.recent_invoices_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_invoices_card.amount_due')" sort-as="due_amount"> <table-column :label="$t('dashboard.recent_invoices_card.amount_due')" show="due_amount" sort-as="due_amount">
<template slot-scope="row"> <template slot-scope="row">
<span>{{ $t('dashboard.recent_invoices_card.amount_due') }}</span> <span>{{ $t('dashboard.recent_invoices_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.due_amount, row.user.currency)"/> <div v-html="$utils.formatMoney(row.due_amount, row.user.currency)"/>
@ -177,7 +177,7 @@
<table-column <table-column
:sortable="false" :sortable="false"
:filterable="false" :filterable="false"
cell-class="action-dropdown no-click" cell-class="action-dropdown dashboard-recent-invoice-options no-click"
> >
<template slot-scope="row"> <template slot-scope="row">
<v-dropdown> <v-dropdown>
@ -242,7 +242,7 @@
> >
<table-column :label="$t('dashboard.recent_estimate_card.date')" show="formattedExpiryDate" /> <table-column :label="$t('dashboard.recent_estimate_card.date')" show="formattedExpiryDate" />
<table-column :label="$t('dashboard.recent_estimate_card.customer')" show="user.name" /> <table-column :label="$t('dashboard.recent_estimate_card.customer')" show="user.name" />
<table-column :label="$t('dashboard.recent_estimate_card.amount_due')" sort-as="total"> <table-column :label="$t('dashboard.recent_estimate_card.amount_due')" show="total" sort-as="total">
<template slot-scope="row"> <template slot-scope="row">
<span>{{ $t('dashboard.recent_estimate_card.amount_due') }}</span> <span>{{ $t('dashboard.recent_estimate_card.amount_due') }}</span>
<div v-html="$utils.formatMoney(row.total, row.user.currency)"/> <div v-html="$utils.formatMoney(row.total, row.user.currency)"/>
@ -396,7 +396,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('estimates.confirm_delete', 1), text: this.$tc('estimates.confirm_delete', 1),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -416,7 +416,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_conversion'), text: this.$t('estimates.confirm_conversion'),
icon: 'error', icon: '/assets/icon/envelope-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -433,14 +433,24 @@ export default {
}) })
}, },
async onMarkAsSent (id) { async onMarkAsSent (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSent) => {
if (willMarkAsSent) {
const data = { const data = {
id: id id: id
} }
let response = await this.markAsSent(data) let response = await this.markAsSent(data)
this.$refs.table.refresh() this.$refs.table.refresh()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent')) window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully'))
} }
}
})
}, },
async removeInvoice (id) { async removeInvoice (id) {
@ -448,7 +458,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('invoices.confirm_delete'), text: this.$tc('invoices.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -465,25 +475,45 @@ export default {
}, },
async sendInvoice (id) { async sendInvoice (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('invoices.confirm_send'),
icon: '/assets/icon/paper-plane-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willSendInvoice) => {
if (willSendInvoice) {
const data = { const data = {
id: id id: id
} }
let response = await this.sendEmail(data) let response = await this.sendEmail(data)
this.$refs.table.refresh() this.$refs.table.refresh()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('invoices.send_invoice')) window.toastr['success'](this.$tc('invoices.send_invoice_successfully'))
} }
}
})
}, },
async sentInvoice (id) { async sentInvoice (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('invoices.invoice_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSend) => {
if (willMarkAsSend) {
const data = { const data = {
id: id id: id
} }
let response = await this.markAsSent(data) let response = await this.markAsSent(data)
this.$refs.table.refresh() this.$refs.table.refresh()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('invoices.mark_as_sent')) window.toastr['success'](this.$tc('invoices.mark_as_sent_successfully'))
} }
} }
})
}
} }
} }

View File

@ -553,6 +553,8 @@ export default {
if (response.data) { if (response.data) {
this.selectCustomer(response.data.estimate.user_id) this.selectCustomer(response.data.estimate.user_id)
this.newEstimate = response.data.estimate this.newEstimate = response.data.estimate
this.newEstimate.estimate_date = moment(response.data.estimate.estimate_date, 'YYYY-MM-DD').toString()
this.newEstimate.expiry_date = moment(response.data.estimate.expiry_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency this.selectedCurrency = this.defaultCurrency

View File

@ -249,25 +249,25 @@
{{ $t('estimates.convert_to_invoice') }} {{ $t('estimates.convert_to_invoice') }}
</a> </a>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item> <v-dropdown-item v-if="row.status !== 'SENT'">
<a class="dropdown-item" href="#" @click.self="onMarkAsSent(row.id)"> <a class="dropdown-item" href="#" @click.self="onMarkAsSent(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" /> <font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
{{ $t('estimates.mark_as_sent') }} {{ $t('estimates.mark_as_sent') }}
</a> </a>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item> <v-dropdown-item v-if="row.status !== 'SENT'">
<a class="dropdown-item" href="#" @click.self="sendEstimate(row.id)"> <a class="dropdown-item" href="#" @click.self="sendEstimate(row.id)">
<font-awesome-icon icon="paper-plane" class="dropdown-item-icon" /> <font-awesome-icon icon="paper-plane" class="dropdown-item-icon" />
{{ $t('estimates.send_estimate') }} {{ $t('estimates.send_estimate') }}
</a> </a>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item v-if="row.status === 'DRAFT'"> <v-dropdown-item v-if="row.status !== 'ACCEPTED'">
<a class="dropdown-item" href="#" @click.self="onMarkAsAccepted(row.id)"> <a class="dropdown-item" href="#" @click.self="onMarkAsAccepted(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" /> <font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
{{ $t('estimates.mark_as_accepted') }} {{ $t('estimates.mark_as_accepted') }}
</a> </a>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item v-if="row.status === 'DRAFT'"> <v-dropdown-item v-if="row.status !== 'REJECTED'">
<a class="dropdown-item" href="#" @click.self="onMarkAsRejected(row.id)"> <a class="dropdown-item" href="#" @click.self="onMarkAsRejected(row.id)">
<font-awesome-icon icon="times-circle" class="dropdown-item-icon" /> <font-awesome-icon icon="times-circle" class="dropdown-item-icon" />
{{ $t('estimates.mark_as_rejected') }} {{ $t('estimates.mark_as_rejected') }}
@ -409,6 +409,14 @@ export default {
} }
}, },
async onMarkAsAccepted (id) { async onMarkAsAccepted (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_accepted'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (markedAsRejected) => {
if (markedAsRejected) {
const data = { const data = {
id: id id: id
} }
@ -417,10 +425,20 @@ export default {
if (response.data) { if (response.data) {
this.filters.status = 'ACCEPTED' this.filters.status = 'ACCEPTED'
this.$refs.table.refresh() this.$refs.table.refresh()
window.toastr['success'](this.$tc('estimates.marked_as_rejected_message')) window.toastr['success'](this.$tc('estimates.confirm_mark_as_accepted'))
} }
}
})
}, },
async onMarkAsRejected (id) { async onMarkAsRejected (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_rejected'),
icon: '/assets/icon/times-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (markedAsRejected) => {
if (markedAsRejected) {
const data = { const data = {
id: id id: id
} }
@ -431,6 +449,8 @@ export default {
this.$refs.table.refresh() this.$refs.table.refresh()
window.toastr['success'](this.$tc('estimates.marked_as_rejected_message')) window.toastr['success'](this.$tc('estimates.marked_as_rejected_message'))
} }
}
})
}, },
setFilters () { setFilters () {
this.filtersApplied = true this.filtersApplied = true
@ -470,7 +490,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('estimates.confirm_delete', 1), text: this.$tc('estimates.confirm_delete', 1),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -491,11 +511,11 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_conversion'), text: this.$t('estimates.confirm_conversion'),
icon: 'error', icon: '/assets/icon/envelope-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willConvertInToinvoice) => {
if (willDelete) { if (willConvertInToinvoice) {
let res = await this.convertToInvoice(id) let res = await this.convertToInvoice(id)
if (res.data) { if (res.data) {
window.toastr['success'](this.$t('estimates.conversion_message')) window.toastr['success'](this.$t('estimates.conversion_message'))
@ -510,7 +530,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('estimates.confirm_delete', 2), text: this.$tc('estimates.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -536,25 +556,45 @@ export default {
this.refreshTable() this.refreshTable()
}, },
async onMarkAsSent (id) { async onMarkAsSent (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSent) => {
if (willMarkAsSent) {
const data = { const data = {
id: id id: id
} }
let response = await this.markAsSent(data) let response = await this.markAsSent(data)
this.refreshTable() this.refreshTable()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent')) window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully'))
} }
}
})
}, },
async sendEstimate (id) { async sendEstimate (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_send_estimate'),
icon: '/assets/icon/paper-plane-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willSendEstimate) => {
if (willSendEstimate) {
const data = { const data = {
id: id id: id
} }
let response = await this.sendEmail(data) let response = await this.sendEmail(data)
this.refreshTable() this.refreshTable()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent')) window.toastr['success'](this.$tc('estimates.send_estimate_successfully'))
} }
} }
})
}
} }
} }
</script> </script>

View File

@ -5,6 +5,7 @@
<div class="page-actions row"> <div class="page-actions row">
<div class="col-xs-2"> <div class="col-xs-2">
<base-button <base-button
v-if="estimate.status !== 'SENT'"
:loading="isRequestOnGoing" :loading="isRequestOnGoing"
:disabled="isRequestOnGoing" :disabled="isRequestOnGoing"
:outline="true" :outline="true"
@ -144,6 +145,8 @@ export default {
orderByField: null, orderByField: null,
searchText: null searchText: null
}, },
status: ['DRAFT', 'SENT', 'VIEWED', 'EXPIRED', 'ACCEPTED', 'REJECTED'],
isMarkAsSent: false,
isRequestOnGoing: false, isRequestOnGoing: false,
isSearching: false isSearching: false
} }
@ -222,12 +225,22 @@ export default {
return true return true
}, },
async onMarkAsSent () { async onMarkAsSent () {
this.isRequestOnGoing = true swal({
title: this.$t('general.are_you_sure'),
text: this.$t('estimates.confirm_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSent) => {
if (willMarkAsSent) {
this.isMarkAsSent = true
let response = await this.markAsSent({id: this.estimate.id}) let response = await this.markAsSent({id: this.estimate.id})
this.isRequestOnGoing = false this.isMarkAsSent = false
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('estimates.mark_as_sent')) window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully'))
} }
}
})
}, },
async removeEstimate (id) { async removeEstimate (id) {
this.selectEstimate([parseInt(id)]) this.selectEstimate([parseInt(id)])
@ -235,7 +248,7 @@ export default {
swal({ swal({
title: 'Deleted', title: 'Deleted',
text: 'you will not be able to recover this estimate!', text: 'you will not be able to recover this estimate!',
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -358,7 +358,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('expenses.confirm_delete'), text: this.$tc('expenses.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -378,7 +378,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('expenses.confirm_delete', 2), text: this.$tc('expenses.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -554,6 +554,8 @@ export default {
if (response.data) { if (response.data) {
this.selectCustomer(response.data.invoice.user_id) this.selectCustomer(response.data.invoice.user_id)
this.newInvoice = response.data.invoice this.newInvoice = response.data.invoice
this.newInvoice.invoice_date = moment(response.data.invoice.invoice_date, 'YYYY-MM-DD').toString()
this.newInvoice.due_date = moment(response.data.invoice.due_date, 'YYYY-MM-DD').toString()
this.discountPerItem = response.data.discount_per_item this.discountPerItem = response.data.discount_per_item
this.taxPerItem = response.data.tax_per_item this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency this.selectedCurrency = this.defaultCurrency

View File

@ -247,13 +247,13 @@
{{ $t('invoices.view') }} {{ $t('invoices.view') }}
</router-link> </router-link>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item> <v-dropdown-item v-if="row.status == 'DRAFT'">
<a class="dropdown-item" href="#" @click="sendInvoice(row.id)" > <a class="dropdown-item" href="#" @click="sendInvoice(row.id)" >
<font-awesome-icon icon="paper-plane" class="dropdown-item-icon" /> <font-awesome-icon icon="paper-plane" class="dropdown-item-icon" />
{{ $t('invoices.send_invoice') }} {{ $t('invoices.send_invoice') }}
</a> </a>
</v-dropdown-item> </v-dropdown-item>
<v-dropdown-item v-if="row.status === 'DRAFT'"> <v-dropdown-item v-if="row.status == 'DRAFT'">
<a class="dropdown-item" href="#" @click="sentInvoice(row.id)"> <a class="dropdown-item" href="#" @click="sentInvoice(row.id)">
<font-awesome-icon icon="check-circle" class="dropdown-item-icon" /> <font-awesome-icon icon="check-circle" class="dropdown-item-icon" />
{{ $t('invoices.mark_as_sent') }} {{ $t('invoices.mark_as_sent') }}
@ -384,24 +384,44 @@ export default {
'fetchCustomers' 'fetchCustomers'
]), ]),
async sendInvoice (id) { async sendInvoice (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('invoices.confirm_send'),
icon: '/assets/icon/paper-plane-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willSendInvoice) => {
if (willSendInvoice) {
const data = { const data = {
id: id id: id
} }
let response = await this.sendEmail(data) let response = await this.sendEmail(data)
this.refreshTable() this.refreshTable()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('invoices.send_invoice')) window.toastr['success'](this.$tc('invoices.send_invoice_successfully'))
} }
}
})
}, },
async sentInvoice (id) { async sentInvoice (id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('invoices.invoice_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willMarkAsSend) => {
if (willMarkAsSend) {
const data = { const data = {
id: id id: id
} }
let response = await this.markAsSent(data) let response = await this.markAsSent(data)
this.refreshTable() this.refreshTable()
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('invoices.mark_as_sent')) window.toastr['success'](this.$tc('invoices.mark_as_sent_successfully'))
} }
}
})
}, },
getStatus (val) { getStatus (val) {
this.filters.status = { this.filters.status = {
@ -476,7 +496,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('invoices.confirm_delete'), text: this.$tc('invoices.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -506,7 +526,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('invoices.confirm_delete', 2), text: this.$tc('invoices.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -229,12 +229,22 @@ export default {
return true return true
}, },
async onMarkAsSent () { async onMarkAsSent () {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('invoices.invoice_mark_as_sent'),
icon: '/assets/icon/check-circle-solid.svg',
buttons: true,
dangerMode: true
}).then(async (MarkAsSend_Invoice) => {
if (MarkAsSend_Invoice) {
this.isRequestOnGoing = true this.isRequestOnGoing = true
let response = await this.markAsSent({id: this.invoice.id}) let response = await this.markAsSent({id: this.invoice.id})
this.isRequestOnGoing = false this.isRequestOnGoing = false
if (response.data) { if (response.data) {
window.toastr['success'](this.$tc('invoices.marked_as_sent_message')) window.toastr['success'](this.$tc('invoices.marked_as_sent_message'))
} }
}
})
}, },
async removeInvoice (id) { async removeInvoice (id) {
this.selectInvoice([parseInt(id)]) this.selectInvoice([parseInt(id)])
@ -242,7 +252,7 @@ export default {
swal({ swal({
title: 'Deleted', title: 'Deleted',
text: 'you will not be able to recover this invoice!', text: 'you will not be able to recover this invoice!',
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -112,7 +112,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
formData: { formData: {
name: '', name: '',

View File

@ -245,7 +245,8 @@ export default {
{ name: 'kg', value: 'kg' }, { name: 'kg', value: 'kg' },
{ name: 'km', value: 'km' }, { name: 'km', value: 'km' },
{ name: 'lb', value: 'lb' }, { name: 'lb', value: 'lb' },
{ name: 'mg', value: 'mg' } { name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
], ],
isRequestOngoing: true, isRequestOngoing: true,
filtersApplied: false, filtersApplied: false,
@ -362,7 +363,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('items.confirm_delete'), text: this.$tc('items.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -388,7 +389,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('items.confirm_delete', 2), text: this.$tc('items.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -101,7 +101,6 @@
</div> </div>
<div v-if="$v.formData.amount.$error"> <div v-if="$v.formData.amount.$error">
<span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span> <span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span>
<span v-if="!$v.formData.amount.numeric" class="text-danger">{{ $t('validation.numbers_only') }}</span>
<span v-if="!$v.formData.amount.between && $v.formData.amount.numeric && amount <= 0" class="text-danger">{{ $t('validation.payment_greater_than_zero') }}</span> <span v-if="!$v.formData.amount.between && $v.formData.amount.numeric && amount <= 0" class="text-danger">{{ $t('validation.payment_greater_than_zero') }}</span>
<span v-if="!$v.formData.amount.between && amount > 0" class="text-danger">{{ $t('validation.payment_greater_than_due_amount') }}</span> <span v-if="!$v.formData.amount.between && amount > 0" class="text-danger">{{ $t('validation.payment_greater_than_due_amount') }}</span>
</div> </div>
@ -156,7 +155,7 @@ import { mapActions, mapGetters } from 'vuex'
import MultiSelect from 'vue-multiselect' import MultiSelect from 'vue-multiselect'
import { validationMixin } from 'vuelidate' import { validationMixin } from 'vuelidate'
import moment from 'moment' import moment from 'moment'
const { required, numeric, between, maxLength } = require('vuelidate/lib/validators') const { required, between, maxLength } = require('vuelidate/lib/validators')
export default { export default {
components: { MultiSelect }, components: { MultiSelect },
@ -201,7 +200,6 @@ export default {
}, },
amount: { amount: {
required, required,
numeric,
between: between(1, this.maxPayableAmount + 1) between: between(1, this.maxPayableAmount + 1)
}, },
notes: { notes: {

View File

@ -368,7 +368,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('payments.confirm_delete'), text: this.$tc('payments.confirm_delete'),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {
@ -388,7 +388,7 @@ export default {
swal({ swal({
title: this.$t('general.are_you_sure'), title: this.$t('general.are_you_sure'),
text: this.$tc('payments.confirm_delete', 2), text: this.$tc('payments.confirm_delete', 2),
icon: 'error', icon: '/assets/icon/trash-solid.svg',
buttons: true, buttons: true,
dangerMode: true dangerMode: true
}).then(async (willDelete) => { }).then(async (willDelete) => {

View File

@ -196,7 +196,14 @@ export default {
return true return true
}, },
downloadReport () { downloadReport () {
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true' this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => { setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200) }, 200)

View File

@ -200,7 +200,14 @@ export default {
return true return true
}, },
downloadReport () { downloadReport () {
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true' this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => { setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200) }, 200)

View File

@ -238,7 +238,14 @@ export default {
return true return true
}, },
downloadReport () { downloadReport () {
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true' this.url += '&download=true'
} else {
window.open(this.getReportUrl + '&download=true')
}
setTimeout(() => { setTimeout(() => {
if (this.selectedType === 'By Customer') { if (this.selectedType === 'By Customer') {
this.url = `${this.customerSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.customerSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`

View File

@ -189,14 +189,21 @@ export default {
this.$v.formData.$touch() this.$v.formData.$touch()
if (this.$v.$invalid) { if (this.$v.$invalid) {
return true return false
} }
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
return true return true
}, },
downloadReport () { downloadReport () {
if (!this.getReports()) {
return false
}
if (navigator.appVersion.indexOf('Mac') !== -1) {
this.url += '&download=true' this.url += '&download=true'
} else {
window.open(this.url + '&download=true')
}
setTimeout(() => { setTimeout(() => {
this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.siteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
}, 200) }, 200)

View File

@ -101,13 +101,23 @@ export default {
'deleteCategory' 'deleteCategory'
]), ]),
async removeExpenseCategory (id, index) { async removeExpenseCategory (id, index) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('settings.expense_category.confirm_delete'),
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {
if (willDelete) {
let response = await this.deleteCategory(id) let response = await this.deleteCategory(id)
if (response.data.success) { if (response.data.success) {
window.toastr['success'](this.$tc('settings.expense_category.deleted_message')) window.toastr['success'](this.$tc('settings.expense_category.deleted_message'))
this.id = null this.id = null
this.$refs.table.refresh() this.$refs.table.refresh()
return true return true
} window.toastr['success'](this.$t('settings.expense_category.already_in_use')) } window.toastr['error'](this.$t('settings.expense_category.already_in_use'))
}
})
}, },
openCategoryModal () { openCategoryModal () {
this.openModal({ this.openModal({

View File

@ -8,7 +8,7 @@
</p> </p>
</div> </div>
<form action="" @submit.prevent="saveEmailConfig()"> <form action="" @submit.prevent="saveEmailConfig()">
<div class="row my-2 mt-5"> <div class="row">
<div class="col-md-6 my-2"> <div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.driver') }}</label> <label class="form-label">{{ $t('settings.mail.driver') }}</label>
<span class="text-danger"> *</span> <span class="text-danger"> *</span>
@ -66,8 +66,9 @@
<base-input <base-input
:invalid="$v.mailConfigData.mail_password.$error" :invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password" v-model.trim="mailConfigData.mail_password"
type="mail_password" type="password"
name="name" name="name"
show-password
@input="$v.mailConfigData.mail_password.$touch()" @input="$v.mailConfigData.mail_password.$touch()"
/> />
<div v-if="$v.mailConfigData.mail_password.$error"> <div v-if="$v.mailConfigData.mail_password.$error">
@ -116,12 +117,12 @@
</div> </div>
<base-button <base-button
:loading="loading" :loading="loading"
class="pull-right mt-5" class="pull-right mt-4"
icon="save" icon="save"
color="theme" color="theme"
type="submit" type="submit"
> >
{{ $t('wizard.save_cont') }} {{ $t('general.save') }}
</base-button> </base-button>
</form> </form>
</div> </div>
@ -141,12 +142,12 @@ export default {
data () { data () {
return { return {
mailConfigData: { mailConfigData: {
mail_driver: 'smtp', mail_driver: '',
mail_host: 'mailtrap.io', mail_host: '',
mail_port: 2525, mail_port: null,
mail_username: 'cc3c64516febd4', mail_username: '',
mail_password: 'e6a0176301f587', mail_password: '',
mail_encryption: 'tls' mail_encryption: ''
}, },
loading: false, loading: false,
mail_drivers: [] mail_drivers: []
@ -176,18 +177,22 @@ export default {
} }
}, },
mounted () { mounted () {
// this.getMailDrivers() this.loadData()
}, },
methods: { methods: {
async getMailDrivers () { async loadData () {
this.loading = true this.loading = true
let response = await window.axios.get('/api/admin/onboarding/environment/mail') let mailDrivers = await window.axios.get('/api/settings/environment/mail')
let mailData = await window.axios.get('/api/settings/environment/mail-env')
if (response.data) { if (mailDrivers.data) {
this.mail_drivers = response.data this.mail_drivers = mailDrivers.data
this.loading = false
} }
if (mailData.data) {
this.mailConfigData = mailData.data
}
this.loading = false
}, },
async saveEmailConfig () { async saveEmailConfig () {
this.$v.mailConfigData.$touch() this.$v.mailConfigData.$touch()
@ -196,7 +201,7 @@ export default {
} }
this.loading = true this.loading = true
try { try {
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData) let response = await window.axios.post('/api/settings/environment/mail', this.mailConfigData)
if (response.data.success) { if (response.data.success) {
window.toastr['success'](this.$t('wizard.success.' + response.data.success)) window.toastr['success'](this.$t('wizard.success.' + response.data.success))
} else { } else {

View File

@ -29,16 +29,9 @@
> >
<table-column <table-column
:sortable="true" :sortable="true"
:filterable="true"
:label="$t('settings.tax_types.tax_name')" :label="$t('settings.tax_types.tax_name')"
> show="name"
<template slot-scope="row"> />
<span>{{ $t('settings.tax_types.tax_name') }}</span>
<span class="tax-name">
{{ row.name }}
</span>
</template>
</table-column>
<table-column <table-column
:sortable="true" :sortable="true"
:filterable="true" :filterable="true"
@ -159,13 +152,23 @@ export default {
} }
}, },
async removeTax (id, index) { async removeTax (id, index) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$t('settings.tax_types.confirm_delete'),
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
}).then(async (willDelete) => {
if (willDelete) {
let response = await this.deleteTaxType(id) let response = await this.deleteTaxType(id)
if (response.data.success) { if (response.data.success) {
window.toastr['success'](this.$t('settings.tax_types.deleted_message')) window.toastr['success'](this.$t('settings.tax_types.deleted_message'))
this.id = null this.id = null
this.$refs.table.refresh() this.$refs.table.refresh()
return true return true
}window.toastr['success'](this.$t('settings.tax_types.already_in_use')) }window.toastr['error'](this.$t('settings.tax_types.already_in_use'))
}
})
}, },
openTaxModal () { openTaxModal () {
this.openModal({ this.openModal({

View File

@ -0,0 +1,55 @@
<template>
<div class="setting-main-container">
<div class="card setting-card">
<div class="page-header">
<h3 class="page-title">{{ $t('settings.update_app.title') }}</h3>
<p class="page-sub-title">
{{ $t('settings.update_app.description') }}
</p>
<base-button size="large" icon="sync-alt" color="theme" @click="onUpdateApp">
{{ $t('settings.update_app.update') }}
</base-button>
<div v-if="isShowProgressBar" class="progress mt-4">
<div
:style="[{'width': progress+'%'}]"
class="progress-bar progress-bar-striped progress-bar-animated"
role="progressbar"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
isShowProgressBar: false,
progress: 10,
interval: null
}
},
watch: {
},
mounted () {
},
methods: {
onUpdateApp () {
this.isShowProgressBar = true
this.interval = setInterval(() => {
if (this.progress >= 100) {
clearInterval(this.interval)
setTimeout(() => {
this.isShowProgressBar = false
}, 1000)
}
this.progress += 10
}, 250)
}
}
}
</script>

View File

@ -43,6 +43,9 @@
type="password" type="password"
@input="$v.formData.password.$touch()" @input="$v.formData.password.$touch()"
/> />
<div v-if="$v.formData.password.$error">
<span v-if="!$v.formData.password.minLength" class="text-danger"> {{ $tc('validation.password_min_length', $v.formData.password.$params.minLength.min, {count: $v.formData.password.$params.minLength.min}) }} </span>
</div>
</div> </div>
<div class="col-md-6 mb-4 form-group"> <div class="col-md-6 mb-4 form-group">
<label class="input-label">{{ $tc('settings.account_settings.confirm_password') }}</label> <label class="input-label">{{ $tc('settings.account_settings.confirm_password') }}</label>
@ -78,7 +81,7 @@
<script> <script>
import { validationMixin } from 'vuelidate' import { validationMixin } from 'vuelidate'
import { mapActions } from 'vuex' import { mapActions } from 'vuex'
const { required, requiredIf, sameAs, email } = require('vuelidate/lib/validators') const { required, requiredIf, sameAs, email, minLength } = require('vuelidate/lib/validators')
export default { export default {
mixins: [validationMixin], mixins: [validationMixin],
@ -103,6 +106,7 @@ export default {
email email
}, },
password: { password: {
minLength: minLength(5)
}, },
confirm_password: { confirm_password: {
required: requiredIf('isRequired'), required: requiredIf('isRequired'),

View File

@ -74,6 +74,12 @@ export default {
title: 'settings.menu_title.notifications', title: 'settings.menu_title.notifications',
icon: 'bell', icon: 'bell',
iconType: 'far' iconType: 'far'
},
{
link: '/admin/settings/update-app',
title: 'settings.menu_title.update_app',
icon: 'sync-alt',
iconType: 'fas'
} }
] ]
} }

View File

@ -94,17 +94,27 @@
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label">{{ $t('wizard.address') }}</label> <label class="form-label">{{ $t('wizard.address') }}</label>
<base-text-area <base-text-area
:invalid="$v.companyData.address_street_1.$error"
v-model.trim="companyData.address_street_1" v-model.trim="companyData.address_street_1"
:placeholder="$t('general.street_1')" :placeholder="$t('general.street_1')"
name="billing_street1" name="billing_street1"
rows="2" rows="2"
@input="$v.companyData.address_street_1.$touch()"
/> />
<div v-if="$v.companyData.address_street_1.$error">
<span v-if="!$v.companyData.address_street_1.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span>
</div>
<base-text-area <base-text-area
:invalid="$v.companyData.address_street_2.$error"
v-model="companyData.address_street_2" v-model="companyData.address_street_2"
:placeholder="$t('general.street_2')" :placeholder="$t('general.street_2')"
name="billing_street2" name="billing_street2"
rows="2" rows="2"
@input="$v.companyData.address_street_2.$touch()"
/> />
<div v-if="$v.companyData.address_street_2.$error">
<span v-if="!$v.companyData.address_street_2.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span>
</div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="row"> <div class="row">
@ -146,7 +156,7 @@ import MultiSelect from 'vue-multiselect'
import AvatarCropper from 'vue-avatar-cropper' import AvatarCropper from 'vue-avatar-cropper'
import { validationMixin } from 'vuelidate' import { validationMixin } from 'vuelidate'
import Ls from '../../services/ls' import Ls from '../../services/ls'
const { required, minLength, email } = require('vuelidate/lib/validators') const { required, minLength, email, maxLength } = require('vuelidate/lib/validators')
export default { export default {
components: { components: {
@ -197,6 +207,12 @@ export default {
}, },
country_id: { country_id: {
required required
},
address_street_1: {
maxLength: maxLength(255)
},
address_street_2: {
maxLength: maxLength(255)
} }
} }
}, },

View File

@ -97,7 +97,6 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label">{{ $t('wizard.database.password') }}</label> <label class="form-label">{{ $t('wizard.database.password') }}</label>
<span class="text-danger"> *</span>
<base-input <base-input
v-model.trim="databaseData.database_password" v-model.trim="databaseData.database_password"
type="password" type="password"
@ -154,7 +153,7 @@ export default {
database_name: null, database_name: null,
database_username: null, database_username: null,
database_password: null, database_password: null,
app_url: null app_url: window.location.origin
}, },
loading: false, loading: false,
connections: [ connections: [
@ -207,8 +206,8 @@ export default {
} }
this.loading = false this.loading = false
} catch (e) { } catch (e) {
console.log(e) console.log(e.response)
window.toastr['error']('Something went wrong') window.toastr['error'](e.response.data.message)
} }
} }
} }

View File

@ -61,7 +61,8 @@
<base-input <base-input
:invalid="$v.mailConfigData.mail_password.$error" :invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password" v-model.trim="mailConfigData.mail_password"
type="mail_password" type="password"
show-password
name="name" name="name"
@input="$v.mailConfigData.mail_password.$touch()" @input="$v.mailConfigData.mail_password.$touch()"
/> />

View File

@ -67,8 +67,8 @@ export default {
data () { data () {
return { return {
loading: false, loading: false,
tab: 'step_1', tab: 'step_3',
step: 1 step: 3
} }
}, },
created () { created () {

View File

@ -35,7 +35,7 @@
</div> </div>
</div> </div>
<base-button <base-button
v-if="requirements" v-if="hasNext"
:loading="loading" :loading="loading"
class="pull-right mt-4" class="pull-right mt-4"
icon="arrow-right" icon="arrow-right"
@ -46,7 +46,7 @@
{{ $t('wizard.continue') }} {{ $t('wizard.continue') }}
</base-button> </base-button>
<base-button <base-button
v-else v-if="!requirements"
:loading="loading" :loading="loading"
class="pull-right mt-4" class="pull-right mt-4"
color="theme" color="theme"
@ -74,6 +74,20 @@ export default {
isShow: true isShow: true
} }
}, },
computed: {
hasNext () {
if (this.requirements) {
let isRequired = true
for (const key in this.requirements) {
if (!this.requirements[key]) {
isRequired = false
}
}
return this.requirements && this.phpSupportInfo.supported && isRequired
}
return false
}
},
methods: { methods: {
listToggle () { listToggle () {
this.isShow = !this.isShow this.isShow = !this.isShow

View File

@ -45,6 +45,7 @@
/> />
<div v-if="$v.profileData.password.$error"> <div v-if="$v.profileData.password.$error">
<span v-if="!$v.profileData.password.required" class="text-danger">{{ $tc('validation.required') }}</span> <span v-if="!$v.profileData.password.required" class="text-danger">{{ $tc('validation.required') }}</span>
<span v-if="!$v.profileData.password.minLength" class="text-danger"> {{ $tc('validation.password_min_length', $v.profileData.password.$params.minLength.min, {count: $v.profileData.password.$params.minLength.min}) }} </span>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
@ -106,7 +107,8 @@ export default {
required required
}, },
password: { password: {
required required,
minLength: minLength(5)
}, },
confirm_password: { confirm_password: {
required: requiredIf('isRequired'), required: requiredIf('isRequired'),

View File

@ -50,7 +50,9 @@ import {
faShare, faShare,
faEllipsisH, faEllipsisH,
faCopy, faCopy,
faPaperPlane faPaperPlane,
faEyeSlash,
faSyncAlt
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons' import { far } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
@ -108,10 +110,12 @@ library.add(
faFilePdf, faFilePdf,
faEnvelope, faEnvelope,
faEye, faEye,
faEyeSlash,
faShare, faShare,
faEllipsisH, faEllipsisH,
faCopy, faCopy,
faPaperPlane faPaperPlane,
faSyncAlt
) )
Vue.component('font-awesome-icon', FontAwesomeIcon) Vue.component('font-awesome-icon', FontAwesomeIcon)

View File

@ -111,3 +111,7 @@ code, .code {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.swal-icon--custom {
height: 70px !important;
}

View File

@ -19,3 +19,19 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.category-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -34,3 +34,20 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.customer-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -19,3 +19,20 @@
} }
} }
@media(max-width: $x-small-breakpoint ) {
.base-modal {
.item-modal {
.input-label {
text-align: left;
}
}
}
}

View File

@ -1,6 +1,7 @@
fieldset[disabled] .multiselect { fieldset[disabled] .multiselect {
pointer-events: none; pointer-events: none;
} }
.in-valid { .in-valid {
border: 1px solid $ls-color-red !important; border: 1px solid $ls-color-red !important;
} }
@ -18,6 +19,7 @@ fieldset[disabled] .multiselect {
background: #fff; background: #fff;
display: block; display: block;
} }
.multiselect__spinner:before, .multiselect__spinner:before,
.multiselect__spinner:after { .multiselect__spinner:after {
position: absolute; position: absolute;
@ -33,23 +35,28 @@ fieldset[disabled] .multiselect {
border-width: 2px; border-width: 2px;
box-shadow: 0 0 0 1px transparent; box-shadow: 0 0 0 1px transparent;
} }
.multiselect__spinner:before { .multiselect__spinner:before {
animation: spinning 2.4s cubic-bezier(0.41, 0.26, 0.2, 0.62); animation: spinning 2.4s cubic-bezier(0.41, 0.26, 0.2, 0.62);
animation-iteration-count: infinite; animation-iteration-count: infinite;
} }
.multiselect__spinner:after { .multiselect__spinner:after {
animation: spinning 2.4s cubic-bezier(0.51, 0.09, 0.21, 0.8); animation: spinning 2.4s cubic-bezier(0.51, 0.09, 0.21, 0.8);
animation-iteration-count: infinite; animation-iteration-count: infinite;
} }
.multiselect__loading-enter-active, .multiselect__loading-enter-active,
.multiselect__loading-leave-active { .multiselect__loading-leave-active {
transition: opacity 0.4s ease-in-out; transition: opacity 0.4s ease-in-out;
opacity: 1; opacity: 1;
} }
.multiselect__loading-enter, .multiselect__loading-enter,
.multiselect__loading-leave-active { .multiselect__loading-leave-active {
opacity: 0; opacity: 0;
} }
.multiselect, .multiselect,
.multiselect__input, .multiselect__input,
.multiselect__single { .multiselect__single {
@ -57,34 +64,41 @@ fieldset[disabled] .multiselect {
font-size: 14px; font-size: 14px;
touch-action: manipulation; touch-action: manipulation;
} }
.multiselect { .multiselect {
box-sizing: content-box; box-sizing: content-box;
display: block; display: block;
position: relative; position: relative;
width: 100%; width: 100%;
min-height: 45px; min-height: 40px;
text-align: left; text-align: left;
color: #35495e; color: #35495e;
} }
.multiselect * { .multiselect * {
box-sizing: border-box; box-sizing: border-box;
} }
.multiselect:focus { .multiselect:focus {
border: 1px solid #817ae3 !important; border: 1px solid #817ae3 !important;
} }
.multiselect--disabled { .multiselect--disabled {
pointer-events: none; pointer-events: none;
opacity: 0.6; opacity: 0.6;
} }
.multiselect--active { .multiselect--active {
z-index: 50; z-index: 50;
} }
.multiselect--active:not(.multiselect--above) .multiselect__current, .multiselect--active:not(.multiselect--above) .multiselect__current,
.multiselect--active:not(.multiselect--above) .multiselect__input, .multiselect--active:not(.multiselect--above) .multiselect__input,
.multiselect--active:not(.multiselect--above) .multiselect__tags { .multiselect--active:not(.multiselect--above) .multiselect__tags {
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.multiselect--active .multiselect__select { .multiselect--active .multiselect__select {
transform: rotateZ(180deg); transform: rotateZ(180deg);
} }
@ -94,6 +108,7 @@ fieldset[disabled] .multiselect {
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
} }
.multiselect__input, .multiselect__input,
.multiselect__single { .multiselect__single {
position: relative; position: relative;
@ -110,9 +125,11 @@ fieldset[disabled] .multiselect {
// margin-bottom: 8px; // margin-bottom: 8px;
vertical-align: top; vertical-align: top;
} }
.multiselect__input::placeholder { .multiselect__input::placeholder {
color: $ls-color-gray; color: $ls-color-gray;
} }
.multiselect__tag ~ .multiselect__input, .multiselect__tag ~ .multiselect__input,
.multiselect__tag ~ .multiselect__single { .multiselect__tag ~ .multiselect__single {
width: auto; width: auto;
@ -345,68 +362,85 @@ fieldset[disabled] .multiselect {
cursor: text; cursor: text;
pointer-events: none; pointer-events: none;
} }
.multiselect__option--group { .multiselect__option--group {
background: #ededed; background: #ededed;
color: #35495e; color: #35495e;
} }
.multiselect__option--group.multiselect__option--highlight { .multiselect__option--group.multiselect__option--highlight {
background: #35495e; background: #35495e;
color: #fff; color: #fff;
} }
.multiselect__option--group.multiselect__option--highlight:after { .multiselect__option--group.multiselect__option--highlight:after {
background: #35495e; background: #35495e;
} }
.multiselect__option--disabled.multiselect__option--highlight { .multiselect__option--disabled.multiselect__option--highlight {
background: #dedede; background: #dedede;
} }
.multiselect__option--group-selected.multiselect__option--highlight { .multiselect__option--group-selected.multiselect__option--highlight {
background: #ff6a6a; background: #ff6a6a;
color: #fff; color: #fff;
} }
.multiselect__option--group-selected.multiselect__option--highlight:after { .multiselect__option--group-selected.multiselect__option--highlight:after {
background: #ff6a6a; background: #ff6a6a;
content: attr(data-deselect); content: attr(data-deselect);
color: #fff; color: #fff;
} }
.multiselect-enter-active, .multiselect-enter-active,
.multiselect-leave-active { .multiselect-leave-active {
transition: all 0.15s ease; transition: all 0.15s ease;
} }
.multiselect-enter, .multiselect-enter,
.multiselect-leave-active { .multiselect-leave-active {
opacity: 0; opacity: 0;
} }
.multiselect__strong { .multiselect__strong {
margin-bottom: 8px; margin-bottom: 8px;
line-height: 20px; line-height: 20px;
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
} }
*[dir="rtl"] .multiselect { *[dir="rtl"] .multiselect {
text-align: right; text-align: right;
} }
*[dir="rtl"] .multiselect__select { *[dir="rtl"] .multiselect__select {
right: auto; right: auto;
left: 1px; left: 1px;
} }
*[dir="rtl"] .multiselect__tags { *[dir="rtl"] .multiselect__tags {
padding: 8px 8px 0px 40px; padding: 8px 8px 0px 40px;
} }
*[dir="rtl"] .multiselect__content { *[dir="rtl"] .multiselect__content {
text-align: right; text-align: right;
} }
*[dir="rtl"] .multiselect__option:after { *[dir="rtl"] .multiselect__option:after {
right: auto; right: auto;
left: 0; left: 0;
} }
*[dir="rtl"] .multiselect__clear { *[dir="rtl"] .multiselect__clear {
right: auto; right: auto;
left: 12px; left: 12px;
} }
*[dir="rtl"] .multiselect__spinner { *[dir="rtl"] .multiselect__spinner {
right: auto; right: auto;
left: 1px; left: 1px;
} }
@keyframes spinning { @keyframes spinning {
from { from {
transform: rotate(0); transform: rotate(0);
@ -417,6 +451,7 @@ fieldset[disabled] .multiselect {
} }
.multiselect { .multiselect {
.multiselect__option--highlight { .multiselect__option--highlight {
background: $ls-color-primary; background: $ls-color-primary;
color: $ls-color-black; color: $ls-color-black;
@ -459,6 +494,7 @@ fieldset[disabled] .multiselect {
} }
} }
} }
&.error { &.error {
border: 1px solid $ls-color-red; border: 1px solid $ls-color-red;
border-radius: 5px; border-radius: 5px;

View File

@ -27,8 +27,6 @@
.same-address-checkbox-container { .same-address-checkbox-container {
display: flex; display: flex;
justify-content: flex-end;
padding-left: 12px;
margin-bottom: 1.5rem; margin-bottom: 1.5rem;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
@ -97,7 +95,6 @@
.same-address-checkbox-container { .same-address-checkbox-container {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
padding-left: 15px;
margin-bottom: 0rem; margin-bottom: 0rem;
} }

View File

@ -1,6 +1,23 @@
// Dashboard // Dashboard
// ------------------------- // -------------------------
.dashboard {
.dashboard-table
.table-component {
.dashboard-recent-invoice-options {
.dropdown-container {
margin: 10px 5px 0 -75px;
}
}
}
}
.dashbox { .dashbox {
background-color: $white; background-color: $white;
box-shadow: $shadow; box-shadow: $shadow;
@ -364,5 +381,7 @@
justify-content: center; justify-content: center;
} }
} }
} }
} }

View File

@ -58,6 +58,7 @@
.content { .content {
display: flex; display: flex;
flex:1;
flex-direction: column; flex-direction: column;
label { label {
@ -445,6 +446,9 @@
.estimate-amount { .estimate-amount {
font-size: 18px; font-size: 18px;
color: #55547A; color: #55547A;
display: flex;
justify-content: center;
align-items: center;
} }
.total { .total {
@ -491,7 +495,6 @@
font-weight: 300; font-weight: 300;
font-size: 12px; font-size: 12px;
padding-top: 2px; padding-top: 2px;
padding-left: 10px;
textarea { textarea {

View File

@ -38,7 +38,7 @@
} }
.filter-date { .filter-date {
flex: 1; flex: 2;
display: flex; display: flex;
margin-right: 40px; margin-right: 40px;
align-items: center; align-items: center;
@ -60,7 +60,7 @@
margin-top: 28px; margin-top: 28px;
} }
@media(max-width: $medium-breakpoint ) { @media(max-width: $large-breakpoint ) {
.filter-container { .filter-container {
flex-direction: column; flex-direction: column;
} }

View File

@ -58,6 +58,7 @@
.content { .content {
display: flex; display: flex;
flex: 1;
flex-direction: column; flex-direction: column;
label { label {
@ -445,6 +446,9 @@
.invoice-amount { .invoice-amount {
font-size: 18px; font-size: 18px;
color: #55547A; color: #55547A;
display: flex;
justify-content: center;
align-items: center;
} }
.total { .total {
@ -490,7 +494,7 @@
font-weight: 300; font-weight: 300;
font-size: 12px; font-size: 12px;
padding-top: 2px; padding-top: 2px;
padding-left: 10px; // padding-left: 10px;
textarea { textarea {
@ -504,6 +508,7 @@
border: none; border: none;
resize: none; resize: none;
width: 100%; width: 100%;
padding-left: 11px;
color: $ls-color-gray--very-dark; color: $ls-color-gray--very-dark;
} }
} }

View File

@ -33,7 +33,7 @@
} }
.filter-date { .filter-date {
flex: 1; flex: 2;
display: flex; display: flex;
margin-right: 40px; margin-right: 40px;
align-items: center; align-items: center;
@ -55,7 +55,7 @@
margin-top: 28px; margin-top: 28px;
} }
@media(max-width: $medium-breakpoint ) { @media(max-width: $large-breakpoint ) {
.filter-container { .filter-container {
flex-direction: column; flex-direction: column;
} }

View File

@ -1,6 +1,6 @@
// Invoice statuses // Invoice statuses
.inv-status-due { .inv-status-overdue {
background: #FED7D7; background: #FED7D7;
font-size: 13px; font-size: 13px;
color: #9B2C2C; color: #9B2C2C;
@ -15,9 +15,9 @@
} }
.inv-status-unpaid { .inv-status-unpaid {
background: rgba(246, 208, 154, 0.4); background: #F8EDCB;
font-size: 13px; font-size: 13px;
color: #A96E1A; color: #6C432E;
padding: 5px 10px; padding: 5px 10px;
} }
@ -50,9 +50,9 @@
} }
.inv-status-partially_paid { .inv-status-partially_paid {
background: #E1E0EA; background: #C9E3EC;
font-size: 13px; font-size: 13px;
color: #312F57; color: #1E576C;
padding: 5px 10px; padding: 5px 10px;
} }

View File

@ -98,6 +98,9 @@
border-radius: 50%; border-radius: 50%;
height: 21px; height: 21px;
width: 21px; width: 21px;
display: flex;
align-items: center;
justify-content: center;
.icon-check { .icon-check {
font-style: normal; font-style: normal;

View File

@ -182,6 +182,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 160px;
} }
.ship-user-phone { .ship-user-phone {
font-style: normal; font-style: normal;
@ -229,6 +230,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 160px;
} }
.bill-user-phone { .bill-user-phone {
@ -261,7 +263,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -142,6 +142,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 170px;
} }
.bill-user-phone { .bill-user-phone {
font-style: normal; font-style: normal;
@ -190,6 +191,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 170px;
} }
.ship-user-phone { .ship-user-phone {
@ -262,7 +264,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -146,6 +146,7 @@
line-height: 15px; line-height: 15px;
color: #595959; color: #595959;
margin: 0px; margin: 0px;
width: 160px;
} }
.ship-user-phone { .ship-user-phone {
@ -184,6 +185,7 @@
line-height: 15px; line-height: 15px;
color: #595959; color: #595959;
margin: 0px; margin: 0px;
width: 160px;
} }
.bill-user-phone { .bill-user-phone {

View File

@ -1,6 +1,8 @@
@if ($estimate->notes != '' && $estimate->notes != null)
<div class="notes"> <div class="notes">
<div class="notes-label"> <div class="notes-label">
Notes Notes
</div> </div>
{{$estimate->notes}} {{$estimate->notes}}
</div> </div>
@endif

View File

@ -1,27 +1,32 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
@if($estimate->discount_per_item === 'NO') @if($estimate->discount_per_item === 'NO')
<th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@else @else
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@endif @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th>
@if($estimate->discount_per_item === 'YES') @if($estimate->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
@endif @endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@php
$index = 1
@endphp
@foreach ($estimate->items as $item) @foreach ($estimate->items as $item)
<tr class="item-details"> <tr class="item-details">
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td>
<td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td>
@if($estimate->discount_per_item === 'YES') @if($estimate->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -30,12 +35,15 @@
@endif @endif
</td> </td>
@endif @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td>
</tr> </tr>
@php
$index += 1
@endphp
@endforeach @endforeach
</table> </table>
<table width="100%" style="margin-left:420px" cellspacing="0px" border="0" class="table3"> <table width="100%" cellspacing="0px" style="margin-left:420px" border="0" class="table3 @if(count($estimate->items) > 12) page-break @endif">
<tr> <tr>
<td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td> <td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items" <td class="no-border items"

View File

@ -11,6 +11,7 @@
html { html {
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
margin-top: 50px;
} }
table { table {
@ -35,7 +36,7 @@
width: 100%; width: 100%;
height: 90px; height: 90px;
left: 0px; left: 0px;
top: 0px; top: -50px;
} }
.header-logo { .header-logo {
@ -71,7 +72,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 60px; padding-top: 16px;
padding-bottom: 60px; padding-bottom: 60px;
} }
@ -182,6 +183,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 160px;
} }
.ship-user-phone { .ship-user-phone {
font-style: normal; font-style: normal;
@ -229,6 +231,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 160px;
} }
.bill-user-phone { .bill-user-phone {
@ -249,6 +252,7 @@
page-break-after: auto; page-break-after: auto;
} }
.table2 hr { .table2 hr {
height:0.1px; height:0.1px;
} }
@ -261,7 +265,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;
@ -378,8 +382,8 @@
</td> </td>
</tr> </tr>
</table> </table>
<hr class="header-line" style="border: 0.620315px solid #E8E8E8;"/>
</div> </div>
<hr class="header-line" />
<div class="wrapper"> <div class="wrapper">
<div class="address"> <div class="address">
<div class="company"> <div class="company">

View File

@ -142,6 +142,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 170px;
} }
.bill-user-phone { .bill-user-phone {
font-style: normal; font-style: normal;
@ -190,6 +191,7 @@
color: #595959; color: #595959;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 170px;
} }
.ship-user-phone { .ship-user-phone {
@ -262,7 +264,7 @@
} }
tr.main-table-header th { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 0.620315px solid #E8E8E8;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;

View File

@ -89,7 +89,7 @@
} }
.bill-add { .bill-add {
display: inline; display: block;
float:left; float:left;
width:40%; width:40%;
padding: 0 0 0 30px; padding: 0 0 0 30px;
@ -146,6 +146,7 @@
line-height: 15px; line-height: 15px;
color: #595959; color: #595959;
margin: 0px; margin: 0px;
width: 160px;
} }
.ship-user-phone { .ship-user-phone {
@ -184,6 +185,7 @@
line-height: 15px; line-height: 15px;
color: #595959; color: #595959;
margin:0px; margin:0px;
width: 160px;
} }
.bill-user-phone { .bill-user-phone {

View File

@ -1,6 +1,8 @@
@if ($invoice->notes != '' && $invoice->notes != null)
<div class="notes"> <div class="notes">
<div class="notes-label"> <div class="notes-label">
Notes Notes
</div> </div>
{{$invoice->notes}} {{$invoice->notes}}
</div> </div>
@endif

View File

@ -1,27 +1,32 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th>
@if($invoice->discount_per_item === 'NO') @if($invoice->discount_per_item === 'NO')
<th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@else @else
<th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
@endif @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th>
@if($invoice->discount_per_item === 'YES') @if($invoice->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th>
@endif @endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@php
$index = 1
@endphp
@foreach ($invoice->items as $item) @foreach ($invoice->items as $item)
<tr class="item-details"> <tr class="item-details">
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td>
<td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td>
@if($invoice->discount_per_item === 'YES') @if($invoice->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -30,8 +35,11 @@
@endif @endif
</td> </td>
@endif @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td>
</tr> </tr>
@php
$index += 1
@endphp
@endforeach @endforeach
</table> </table>

View File

@ -337,6 +337,21 @@ Route::group(['middleware' => 'api'], function () {
'uses' => 'CompanyController@updateSetting' 'uses' => 'CompanyController@updateSetting'
]); ]);
Route::get('/environment/mail', [
'as' => 'admin.environment.mail',
'uses' => 'EnvironmentController@getMailDrivers'
]);
Route::get('/environment/mail-env', [
'as' => 'admin.mail.env',
'uses' => 'EnvironmentController@getMailEnvironment'
]);
Route::post('/environment/mail', [
'as' => 'admin.environment.mail.save',
'uses' => 'EnvironmentController@saveMailEnvironment'
]);
}); });
}); });