mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-30 13:11:08 -04:00 
			
		
		
		
	Add New SweetAlert & Notification Components
This commit is contained in:
		
				
					committed by
					
						 Mohit Panjwani
						Mohit Panjwani
					
				
			
			
				
	
			
			
			
						parent
						
							3f7db2793f
						
					
				
				
					commit
					c3d3e5e35f
				
			| @ -45,9 +45,8 @@ | ||||
| </template> | ||||
|  | ||||
| <script type="text/babel"> | ||||
| import { async } from 'q' | ||||
| const { required, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
| @ -67,6 +66,7 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async validateBeforeSubmit(e) { | ||||
|       this.$v.formData.$touch() | ||||
|       if (!this.$v.formData.$invalid) { | ||||
| @ -78,7 +78,10 @@ export default { | ||||
|           ) | ||||
|  | ||||
|           if (res.data) { | ||||
|             toastr['success']('Mail sent successfuly!', 'Success') | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: 'Mail sent successfuly!', | ||||
|             }) | ||||
|           } | ||||
|  | ||||
|           this.isSent = true | ||||
|  | ||||
| @ -145,6 +145,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('auth', ['login']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async validateBeforeSubmit() { | ||||
|       axios.defaults.withCredentials = true | ||||
|  | ||||
| @ -158,6 +159,10 @@ export default { | ||||
|       try { | ||||
|         await this.login(this.loginData) | ||||
|         this.$router.push('/admin/dashboard') | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: 'Logged in successfully.', | ||||
|         }) | ||||
|         this.isLoading = false | ||||
|       } catch (error) { | ||||
|         this.isLoading = false | ||||
|  | ||||
| @ -92,6 +92,7 @@ const { | ||||
|   sameAs, | ||||
|   minLength, | ||||
| } = require('vuelidate/lib/validators') | ||||
| import { mapActions } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   data() { | ||||
| @ -120,6 +121,7 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async validateBeforeSubmit(e) { | ||||
|       this.$v.formData.$touch() | ||||
|  | ||||
| @ -135,18 +137,18 @@ export default { | ||||
|           let res = await axios.post('/api/v1/auth/reset/password', data) | ||||
|           this.isLoading = false | ||||
|           if (res.data) { | ||||
|             toastr['success']( | ||||
|               this.$t('login.password_reset_successfully'), | ||||
|               'Success' | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('login.password_reset_successfully'), | ||||
|             }) | ||||
|             this.$router.push('/login') | ||||
|           } | ||||
|         } catch (err) { | ||||
|           if (err.response && err.response.status === 403) { | ||||
|             toastr['error']( | ||||
|               err.response.data, | ||||
|               this.$t('validation.email_incorrect') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('validation.email_incorrect'), | ||||
|             }) | ||||
|             this.isLoading = false | ||||
|           } | ||||
|         } | ||||
|  | ||||
| @ -1,26 +1,26 @@ | ||||
| <template> | ||||
|   <base-page class="customer-create"> | ||||
|     <form v-if="!initLoad" @submit.prevent="submitCustomerData"> | ||||
|       <sw-page-header class="mb-5" :title="pageTitle"> | ||||
|       <sw-page-header :title="pageTitle" class="mb-5"> | ||||
|         <sw-breadcrumb slot="breadcrumbs"> | ||||
|           <sw-breadcrumb-item | ||||
|             to="/admin/dashboard" | ||||
|             :title="$t('general.home')" | ||||
|             to="/admin/dashboard" | ||||
|           /> | ||||
|           <sw-breadcrumb-item | ||||
|             to="/admin/customers" | ||||
|             :title="$tc('customers.customer', 2)" | ||||
|             to="/admin/customers" | ||||
|           /> | ||||
|           <sw-breadcrumb-item | ||||
|             v-if="$route.name === 'customers.edit'" | ||||
|             to="#" | ||||
|             :title="$t('customers.edit_customer')" | ||||
|             to="#" | ||||
|             active | ||||
|           /> | ||||
|           <sw-breadcrumb-item | ||||
|             v-else | ||||
|             to="#" | ||||
|             :title="$t('customers.new_customer')" | ||||
|             to="#" | ||||
|             active | ||||
|           /> | ||||
|         </sw-breadcrumb> | ||||
| @ -56,8 +56,8 @@ | ||||
|           > | ||||
|             <sw-input-group | ||||
|               :label="$t('customers.display_name')" | ||||
|               class="md:col-span-3" | ||||
|               :error="displayNameError" | ||||
|               class="md:col-span-3" | ||||
|               required | ||||
|             > | ||||
|               <sw-input | ||||
| @ -85,8 +85,8 @@ | ||||
|  | ||||
|             <sw-input-group | ||||
|               :label="$t('customers.email')" | ||||
|               class="md:col-span-3" | ||||
|               :error="emailError" | ||||
|               class="md:col-span-3" | ||||
|             > | ||||
|               <sw-input | ||||
|                 :invalid="$v.formData.email.$error" | ||||
| @ -243,8 +243,8 @@ | ||||
|  | ||||
|               <sw-input-group :label="$t('customers.zip_code')"> | ||||
|                 <sw-input | ||||
|                   tabindex="14" | ||||
|                   v-model.trim="billing.zip" | ||||
|                   tabindex="14" | ||||
|                   type="text" | ||||
|                   name="zip" | ||||
|                 /> | ||||
| @ -406,16 +406,16 @@ | ||||
|             class="grid col-span-5 lg:col-span-4 gap-y-6 gap-x-4 md:grid-cols-6" | ||||
|           > | ||||
|             <sw-input-group | ||||
|               class="md:col-span-3" | ||||
|               v-for="(field, index) in customFields" | ||||
|               :label="field.label" | ||||
|               :required="field.is_required ? true : false" | ||||
|               :key="index" | ||||
|               class="md:col-span-3" | ||||
|             > | ||||
|               <component | ||||
|                 :type="field.type.label" | ||||
|                 :field="field" | ||||
|                 :isEdit="isEdit" | ||||
|                 :is-edit="isEdit" | ||||
|                 :is="field.type + 'Field'" | ||||
|                 :invalid-fields="invalidFields" | ||||
|                 :tabindex="23 + index" | ||||
| @ -694,7 +694,7 @@ export default { | ||||
|       'updateCustomer', | ||||
|       'fetchViewCustomer', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     ...mapActions('customFields', ['fetchCustomFields']), | ||||
|  | ||||
|     currencyNameWithCode({ name, code }) { | ||||
| @ -786,10 +786,16 @@ export default { | ||||
|             this.$router.push( | ||||
|               `/admin/customers/${response.data.customer.id}/view` | ||||
|             ) | ||||
|             window.toastr['success'](this.$t('customers.updated_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('customers.updated_message'), | ||||
|             }) | ||||
|           } | ||||
|           if (response.data.error) { | ||||
|             window.toastr['error'](this.$t('validation.email_already_taken')) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('validation.email_already_taken'), | ||||
|             }) | ||||
|           } | ||||
|         } else { | ||||
|           response = await this.addCustomer(this.formData) | ||||
| @ -797,7 +803,10 @@ export default { | ||||
|             this.$router.push( | ||||
|               `/admin/customers/${response.data.customer.id}/view` | ||||
|             ) | ||||
|             window.toastr['success'](this.$t('customers.created_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('customers.created_message'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|  | ||||
| @ -806,7 +815,10 @@ export default { | ||||
|       } catch (error) { | ||||
|         this.isLoading = false | ||||
|         if (err.response.data.errors.email) { | ||||
|           window.toastr['error'](this.$t('validation.email_already_taken')) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('validation.email_already_taken'), | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -195,7 +195,11 @@ | ||||
|           <template slot-scope="row"> | ||||
|             <span>{{ $t('customers.contact_name') }}</span> | ||||
|             <span> | ||||
|               {{ row.contact_name ? row.contact_name : $t('customers.no_contact_name') }} | ||||
|               {{ | ||||
|                 row.contact_name | ||||
|                   ? row.contact_name | ||||
|                   : $t('customers.no_contact_name') | ||||
|               }} | ||||
|             </span> | ||||
|           </template> | ||||
|         </sw-table-column> | ||||
| @ -354,6 +358,7 @@ export default { | ||||
|       'deleteMultipleCustomers', | ||||
|       'setSelectAllState', | ||||
|     ]), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     refreshTable() { | ||||
|       this.$refs.table.refresh() | ||||
|     }, | ||||
| @ -398,43 +403,60 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeCustomer(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('customers.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteCustomer({ ids: [id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('customers.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('customers.deleted_message', 1), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](res.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$tc(res.data.message), | ||||
|           }) | ||||
|           return true | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleCustomers() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('customers.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deleteMultipleCustomers() | ||||
|           if (request.data.success) { | ||||
|             window.toastr['success'](this.$tc('customers.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('customers.deleted_message', 2), | ||||
|             }) | ||||
|             this.refreshTable() | ||||
|           } else if (request.data.error) { | ||||
|             window.toastr['error'](request.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -3,8 +3,8 @@ | ||||
|     <sw-page-header :title="pageTitle"> | ||||
|       <template slot="actions"> | ||||
|         <sw-button | ||||
|           tag-name="router-link" | ||||
|           :to="`/admin/customers/${$route.params.id}/edit`" | ||||
|           tag-name="router-link" | ||||
|           class="mr-3" | ||||
|           variant="primary-outline" | ||||
|         > | ||||
| @ -15,29 +15,29 @@ | ||||
|             {{ $t('customers.new_transaction') }} | ||||
|           </sw-button> | ||||
|           <sw-dropdown-item | ||||
|             tag-name="router-link" | ||||
|             :to="`/admin/estimates/create?customer=${$route.params.id}`" | ||||
|             tag-name="router-link" | ||||
|           > | ||||
|             <document-icon class="h-5 mr-3 text-gray-600" /> | ||||
|             {{ $t('estimates.new_estimate') }} | ||||
|           </sw-dropdown-item> | ||||
|           <sw-dropdown-item | ||||
|             tag-name="router-link" | ||||
|             :to="`/admin/invoices/create?customer=${$route.params.id}`" | ||||
|             tag-name="router-link" | ||||
|           > | ||||
|             <document-text-icon class="h-5 mr-3 text-gray-600" /> | ||||
|             {{ $t('invoices.new_invoice') }} | ||||
|           </sw-dropdown-item> | ||||
|           <sw-dropdown-item | ||||
|             tag-name="router-link" | ||||
|             :to="`/admin/payments/create?customer=${$route.params.id}`" | ||||
|             tag-name="router-link" | ||||
|           > | ||||
|             <credit-card-icon class="h-5 mr-3 text-gray-600" /> | ||||
|             {{ $t('payments.new_payment') }} | ||||
|           </sw-dropdown-item> | ||||
|           <sw-dropdown-item | ||||
|             tag-name="router-link" | ||||
|             :to="`/admin/expenses/create?customer=${$route.params.id}`" | ||||
|             tag-name="router-link" | ||||
|           > | ||||
|             <calculator-icon class="h-5 mr-3 text-gray-600" /> | ||||
|             {{ $t('expenses.new_expense') }} | ||||
| @ -112,25 +112,48 @@ export default { | ||||
|       'selectCustomer', | ||||
|       'deleteMultipleCustomers', | ||||
|     ]), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async removeCustomer(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('customers.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let data = [id] | ||||
|           this.selectCustomer(data) | ||||
|           let res = await this.deleteMultipleCustomers() | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('customers.deleted_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('customers.deleted_message'), | ||||
|             }) | ||||
|             this.$router.push('/admin/customers') | ||||
|             return true | ||||
|           } else if (request.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -98,16 +98,16 @@ | ||||
|             <sw-dropdown slot-scope="row"> | ||||
|               <dot-icon slot="activator" /> | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`invoices/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
|               </sw-dropdown-item> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`invoices/${row.id}/view`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <eye-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('invoices.view') }} | ||||
| @ -227,16 +227,16 @@ | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`estimates/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
|               </sw-dropdown-item> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`estimates/${row.id}/view`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <eye-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.view') }} | ||||
| @ -350,6 +350,8 @@ export default { | ||||
|       'convertToInvoice', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     ...mapActions('estimate', { | ||||
|       sendEstimateEmail: 'sendEmail', | ||||
|       markEstimateAsSent: 'markAsSent', | ||||
| @ -362,25 +364,32 @@ export default { | ||||
|  | ||||
|     async removeEstimate(id) { | ||||
|       this.id = id | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: this.$tc('estimates.confirm_delete', 1), | ||||
|           icon: '/assets/icon/trash-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (willDelete) => { | ||||
|           if (willDelete) { | ||||
|             let res = await this.deleteEstimate({ ids: [this.id] }) | ||||
|             if (res.data.success) { | ||||
|               window.toastr['success'](this.$tc('estimates.deleted_message', 1)) | ||||
|               this.refreshEstTable() | ||||
|             } else if (res.data.error) { | ||||
|               window.toastr['error'](res.data.message) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('estimates.confirm_delete', 1), | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteEstimate({ ids: [this.id] }) | ||||
|           if (res.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.deleted_message', 1), | ||||
|             }) | ||||
|             this.refreshEstTable() | ||||
|           } else if (res.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     refreshInvTable() { | ||||
| @ -392,229 +401,355 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async convertInToinvoice(id) { | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: this.$t('estimates.confirm_conversion'), | ||||
|           icon: '/assets/icon/file-alt-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (willDelete) => { | ||||
|           if (willDelete) { | ||||
|             let res = await this.convertToInvoice(id) | ||||
|             this.selectAllField = false | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_conversion'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             viewBox="0 0 384 512" | ||||
|             class="w-6 h-6" | ||||
|             data-prefix="fas" | ||||
|             data-icon="file-alt" | ||||
|             class="svg-inline--fa fa-file-alt fa-w-12" | ||||
|             role="img" | ||||
|             xmlns="http://www.w3.org/2000/svg" | ||||
|           > | ||||
|             <path | ||||
|               fill="#55547A" | ||||
|               d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm64 236c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-64c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-72v8c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm96-114.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z" | ||||
|             ></path> | ||||
|           </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.convertToInvoice(id) | ||||
|           this.selectAllField = false | ||||
|  | ||||
|             if (res.data) { | ||||
|               window.toastr['success'](this.$t('estimates.conversion_message')) | ||||
|               this.$router.push(`invoices/${res.data.invoice.id}/edit`) | ||||
|             } else if (res.data.error) { | ||||
|               window.toastr['error'](res.data.message) | ||||
|             } | ||||
|           if (res.data) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$t('estimates.conversion_message'), | ||||
|             }) | ||||
|             this.$router.push(`invoices/${res.data.invoice.id}/edit`) | ||||
|           } else if (res.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsSent(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|               status: 'SENT', | ||||
|             } | ||||
|  | ||||
|             let response = await this.markEstimateAsSent(data) | ||||
|             this.refreshEstTable() | ||||
|  | ||||
|             if (response.data) { | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('estimates.mark_as_sent_successfully') | ||||
|               ) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_mark_as_sent'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'SENT', | ||||
|           } | ||||
|         }) | ||||
|  | ||||
|           let response = await this.markEstimateAsSent(data) | ||||
|           this.refreshEstTable() | ||||
|  | ||||
|           if (response.data) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.mark_as_sent_successfully'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeInvoice(id) { | ||||
|       this.id = id | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: this.$tc('invoices.confirm_delete'), | ||||
|           icon: '/assets/icon/trash-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (willDelete) => { | ||||
|           if (willDelete) { | ||||
|             let res = await this.deleteInvoice({ ids: [this.id] }) | ||||
|             if (res.data.success) { | ||||
|               window.toastr['success'](this.$tc('invoices.deleted_message')) | ||||
|               this.refreshInvTable() | ||||
|             } else if (res.data.error) { | ||||
|               window.toastr['error'](res.data.message) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('invoices.confirm_delete'), | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteInvoice({ ids: [this.id] }) | ||||
|           if (res.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.deleted_message'), | ||||
|             }) | ||||
|             this.refreshInvTable() | ||||
|           } else if (res.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async sendInvoice(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|             } | ||||
|             let response = await this.sendEmail(data) | ||||
|             this.refreshInvTable() | ||||
|  | ||||
|             if (response.data.success) { | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('invoices.send_invoice_successfully') | ||||
|               ) | ||||
|               return true | ||||
|             } | ||||
|  | ||||
|             if (response.data.error === 'user_email_does_not_exist') { | ||||
|               window.toastr['error']( | ||||
|                 this.$tc('invoices.user_email_does_not_exist') | ||||
|               ) | ||||
|               return false | ||||
|             } | ||||
|             window.toastr['error'](this.$tc('invoices.something_went_wrong')) | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.confirm_send'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             focusable="false" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|           } | ||||
|         }) | ||||
|           let response = await this.sendEmail(data) | ||||
|           this.refreshInvTable() | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.send_invoice_successfully'), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (response.data.error === 'user_email_does_not_exist') { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: this.$tc('invoices.user_email_does_not_exist'), | ||||
|             }) | ||||
|             return false | ||||
|           } | ||||
|           this.showToaster({ | ||||
|             type: 'error', | ||||
|             message: this.$tc('invoices.something_went_wrong'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async sentInvoice(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|               status: 'SENT', | ||||
|             } | ||||
|             let response = await this.markAsSent(data) | ||||
|  | ||||
|             this.refreshInvTable() | ||||
|             if (response.data) { | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('invoices.mark_as_sent_successfully') | ||||
|               ) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.invoice_mark_as_sent'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'SENT', | ||||
|           } | ||||
|         }) | ||||
|           let response = await this.markAsSent(data) | ||||
|  | ||||
|           this.refreshInvTable() | ||||
|           if (response.data) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.mark_as_sent_successfully'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsAccepted(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|             } | ||||
|             let response = await this.markAsAccepted(data) | ||||
|             this.refreshEstTable() | ||||
|  | ||||
|             if (response.data) { | ||||
|               this.refreshEstTable() | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('estimates.marked_as_accepted_message') | ||||
|               ) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_mark_as_accepted'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|           } | ||||
|         }) | ||||
|           let response = await this.markAsAccepted(data) | ||||
|           this.refreshEstTable() | ||||
|  | ||||
|           if (response.data) { | ||||
|             this.refreshEstTable() | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.marked_as_accepted_message'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsRejected(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|             } | ||||
|             let response = await this.markAsRejected(data) | ||||
|             this.refreshEstTable() | ||||
|  | ||||
|             if (response.data) { | ||||
|               this.refreshEstTable() | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('estimates.marked_as_rejected_message') | ||||
|               ) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_mark_as_rejected'), | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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="#DC2626" | ||||
|               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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|           } | ||||
|         }) | ||||
|           let response = await this.markAsRejected(data) | ||||
|           this.refreshEstTable() | ||||
|  | ||||
|           if (response.data) { | ||||
|             this.refreshEstTable() | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.marked_as_rejected_message'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async sendEstimate(id) { | ||||
|       window | ||||
|         .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 = { | ||||
|               id: id, | ||||
|             } | ||||
|             let response = await this.sendEstimateEmail(data) | ||||
|             this.refreshEstTable() | ||||
|  | ||||
|             if (response.data.success) { | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('estimates.send_estimate_successfully') | ||||
|               ) | ||||
|               return true | ||||
|             } | ||||
|  | ||||
|             if (response.data.error === 'user_email_does_not_exist') { | ||||
|               window.toastr['error']( | ||||
|                 this.$tc('estimates.user_email_does_not_exist') | ||||
|               ) | ||||
|               return true | ||||
|             } | ||||
|             window.toastr['error'](this.$tc('estimates.something_went_wrong')) | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_send_estimate'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             focusable="false" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|           } | ||||
|         }) | ||||
|           let response = await this.sendEstimateEmail(data) | ||||
|           this.refreshEstTable() | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.send_estimate_successfully'), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (response.data.error === 'user_email_does_not_exist') { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: this.$tc('estimates.user_email_does_not_exist'), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|           this.showToaster({ | ||||
|             type: 'error', | ||||
|             message: this.$tc('estimates.something_went_wrong'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
|  | ||||
| @ -720,6 +720,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('customFields', ['fetchCustomFields']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     selectFixed() { | ||||
|       if (this.newEstimate.discount_type === 'fixed') { | ||||
|         return | ||||
| @ -921,7 +923,10 @@ export default { | ||||
|         .then((res) => { | ||||
|           if (res.data) { | ||||
|             this.$router.push(`/admin/estimates/${res.data.estimate.id}/view`) | ||||
|             window.toastr['success'](this.$t('estimates.created_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('estimates.created_message'), | ||||
|             }) | ||||
|           } | ||||
|  | ||||
|           this.isLoading = false | ||||
| @ -937,7 +942,10 @@ export default { | ||||
|           this.isLoading = false | ||||
|           if (res.data) { | ||||
|             this.$router.push(`/admin/estimates/${res.data.estimate.id}/view`) | ||||
|             window.toastr['success'](this.$t('estimates.updated_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('estimates.updated_message'), | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         .catch((err) => { | ||||
|  | ||||
| @ -2,11 +2,11 @@ | ||||
|   <base-page> | ||||
|     <sw-page-header :title="$t('estimates.title')"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="dashboard" /> | ||||
|  | ||||
|         <sw-breadcrumb-item | ||||
|           to="#" | ||||
|           :title="$tc('estimates.estimate', 2)" | ||||
|           to="#" | ||||
|           active | ||||
|         /> | ||||
|       </sw-breadcrumb> | ||||
| @ -277,12 +277,12 @@ | ||||
|         > | ||||
|           <template slot-scope="row"> | ||||
|             <span> {{ $t('estimates.action') }} </span> | ||||
|             <sw-dropdown containerClass="w-56"> | ||||
|             <sw-dropdown container-class="w-56"> | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`estimates/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
| @ -294,8 +294,8 @@ | ||||
|               </sw-dropdown-item> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`estimates/${row.id}/view`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <eye-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.view') }} | ||||
| @ -481,6 +481,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     refreshTable() { | ||||
|       this.$refs.table.refresh() | ||||
|     }, | ||||
| @ -536,14 +538,30 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsAccepted(id) { | ||||
|       swal({ | ||||
|       this.$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) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'ACCEPTED', | ||||
| @ -553,23 +571,40 @@ export default { | ||||
|  | ||||
|           if (response.data) { | ||||
|             this.$refs.table.refresh() | ||||
|             window.toastr['success']( | ||||
|               this.$tc('estimates.marked_as_accepted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.marked_as_accepted_message'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsRejected(id) { | ||||
|       swal({ | ||||
|       this.$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) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             focusable="false" | ||||
|             class="w-6 h-6" | ||||
|             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="#DC2626" | ||||
|               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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'REJECTED', | ||||
| @ -579,9 +614,10 @@ export default { | ||||
|  | ||||
|           if (response.data) { | ||||
|             this.$refs.table.refresh() | ||||
|             window.toastr['success']( | ||||
|               this.$tc('estimates.marked_as_rejected_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.marked_as_rejected_message'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
| @ -624,65 +660,104 @@ export default { | ||||
|  | ||||
|     async removeEstimate(id) { | ||||
|       this.id = id | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('estimates.confirm_delete', 1), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteEstimate({ ids: [this.id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             this.$refs.table.refresh() | ||||
|             this.resetSelectedEstimates() | ||||
|             window.toastr['success'](this.$tc('estimates.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.deleted_message', 1), | ||||
|             }) | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async convertInToinvoice(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_conversion'), | ||||
|         icon: '/assets/icon/file-alt-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willConvertInToinvoice) => { | ||||
|         if (willConvertInToinvoice) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             viewBox="0 0 384 512" | ||||
|             class="w-6 h-6" | ||||
|             data-prefix="fas" | ||||
|             data-icon="file-alt" | ||||
|             class="svg-inline--fa fa-file-alt fa-w-12" | ||||
|             role="img" | ||||
|             xmlns="http://www.w3.org/2000/svg" | ||||
|           > | ||||
|             <path | ||||
|               fill="#55547A" | ||||
|               d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm64 236c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-64c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-72v8c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm96-114.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z" | ||||
|             ></path> | ||||
|           </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.convertToInvoice(id) | ||||
|  | ||||
|           if (res.data) { | ||||
|             window.toastr['success'](this.$t('estimates.conversion_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('estimates.conversion_message'), | ||||
|             }) | ||||
|             this.$router.push(`invoices/${res.data.invoice.id}/edit`) | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleEstimates() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('estimates.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteMultipleEstimates() | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             this.$refs.table.refresh() | ||||
|             this.resetSelectedEstimates() | ||||
|             window.toastr['success'](this.$tc('estimates.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.deleted_message', 2), | ||||
|             }) | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
| @ -699,14 +774,30 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async onMarkAsSent(id) { | ||||
|       swal({ | ||||
|       this.$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) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'SENT', | ||||
| @ -716,9 +807,10 @@ export default { | ||||
|           this.refreshTable() | ||||
|  | ||||
|           if (response.data) { | ||||
|             window.toastr['success']( | ||||
|               this.$tc('estimates.mark_as_sent_successfully') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.mark_as_sent_successfully'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -310,6 +310,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     hasActiveUrl(id) { | ||||
|       return this.$route.params.id == id | ||||
|     }, | ||||
| @ -342,8 +344,10 @@ export default { | ||||
|       let pdfUrl = `${window.location.origin}/estimates/pdf/${this.estimate.unique_hash}` | ||||
|  | ||||
|       let response = this.$utils.copyTextToClipboard(pdfUrl) | ||||
|  | ||||
|       window.toastr['success'](this.$tc('general.copied_pdf_url_clipboard')) | ||||
|       this.showNotification({ | ||||
|         type: 'success', | ||||
|         message: this.$tc('general.copied_pdf_url_clipboard'), | ||||
|       }) | ||||
|     }, | ||||
|     async onSearched() { | ||||
|       let data = '' | ||||
| @ -386,30 +390,45 @@ export default { | ||||
|       return true | ||||
|     }, | ||||
|     async onMarkAsSent() { | ||||
|       window | ||||
|         .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 (value) => { | ||||
|           if (value) { | ||||
|             this.isMarkAsSent = true | ||||
|             let response = await this.markAsSent({ | ||||
|               id: this.estimate.id, | ||||
|               status: 'SENT', | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_mark_as_sent'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           this.isMarkAsSent = true | ||||
|           let response = await this.markAsSent({ | ||||
|             id: this.estimate.id, | ||||
|             status: 'SENT', | ||||
|           }) | ||||
|           this.isMarkAsSent = false | ||||
|           if (response.data) { | ||||
|             this.estimate.status = 'SENT' | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.mark_as_sent_successfully'), | ||||
|             }) | ||||
|             this.isMarkAsSent = false | ||||
|             if (response.data) { | ||||
|               this.estimate.status = 'SENT' | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('estimates.mark_as_sent_successfully') | ||||
|               ) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     async onSendEstimate(id) { | ||||
|       this.openModal({ | ||||
| @ -423,29 +442,38 @@ export default { | ||||
|       let pdfUrl = `${window.location.origin}/estimates/pdf/${this.estimate.unique_hash}` | ||||
|  | ||||
|       let response = this.$utils.copyTextToClipboard(pdfUrl) | ||||
|  | ||||
|       window.toastr['success'](this.$tc('general.copied_pdf_url_clipboard')) | ||||
|       this.showNotification({ | ||||
|         type: 'success', | ||||
|         message: this.$tc('general.copied_pdf_url_clipboard'), | ||||
|       }) | ||||
|     }, | ||||
|     async removeEstimate(id) { | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: 'you will not be able to recover this estimate!', | ||||
|           icon: '/assets/icon/trash-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (value) => { | ||||
|           if (value) { | ||||
|             let request = await this.deleteEstimate({ ids: [id] }) | ||||
|             if (request.data.success) { | ||||
|               window.toastr['success'](this.$tc('estimates.deleted_message', 1)) | ||||
|               this.$router.push('/admin/estimates') | ||||
|             } else if (request.data.error) { | ||||
|               window.toastr['error'](request.data.message) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: 'you will not be able to recover this estimate!', | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deleteEstimate({ ids: [id] }) | ||||
|           if (request.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('estimates.deleted_message', 1), | ||||
|             }) | ||||
|             this.$router.push('/admin/estimates') | ||||
|           } else if (request.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
|  | ||||
| @ -417,6 +417,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('customer', ['fetchCustomers']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     openCategoryModal() { | ||||
|       this.openModal({ | ||||
|         title: this.$t('settings.expense_category.add_category'), | ||||
| @ -532,22 +534,34 @@ export default { | ||||
|  | ||||
|         if (response.data.success) { | ||||
|           this.isLoading = false | ||||
|           window.toastr['success'](this.$t('expenses.updated_message')) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('expenses.updated_message'), | ||||
|           }) | ||||
|           this.$router.push('/admin/expenses') | ||||
|           return true | ||||
|         } | ||||
|         window.toastr['error'](response.data.error) | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: response.data.error, | ||||
|         }) | ||||
|       } else { | ||||
|         this.isLoading = true | ||||
|         let response = await this.addExpense(data) | ||||
|         this.isLoading = false | ||||
|  | ||||
|         if (response.data.success) { | ||||
|           window.toastr['success'](this.$t('expenses.created_message')) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('expenses.created_message'), | ||||
|           }) | ||||
|           this.$router.push('/admin/expenses') | ||||
|           return true | ||||
|         } | ||||
|         window.toastr['success'](response.data.success) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: response.data.success, | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -3,9 +3,9 @@ | ||||
|     <!-- Page Header --> | ||||
|     <sw-page-header :title="$t('expenses.title')"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="dashboard" /> | ||||
|  | ||||
|         <sw-breadcrumb-item to="#" :title="$tc('expenses.expense', 2)" active /> | ||||
|         <sw-breadcrumb-item :title="$tc('expenses.expense', 2)" to="#" active /> | ||||
|       </sw-breadcrumb> | ||||
|  | ||||
|       <template slot="actions"> | ||||
| @ -208,7 +208,9 @@ | ||||
|         > | ||||
|           <template slot-scope="row"> | ||||
|             <span>{{ $t('expenses.customer') }}</span> | ||||
|             <span> {{ row.user_name ? row.user_name : $t('expenses.not_selected') }} </span> | ||||
|             <span> | ||||
|               {{ row.user_name ? row.user_name : $t('expenses.not_selected') }} | ||||
|             </span> | ||||
|           </template> | ||||
|         </sw-table-column> | ||||
|  | ||||
| @ -248,8 +250,8 @@ | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`expenses/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
| @ -374,6 +376,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('category', ['fetchCategories']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         user_id: this.filters.user ? this.filters.user.id : null, | ||||
| @ -454,43 +458,61 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeExpense(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('expenses.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteExpense({ ids: [id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('expenses.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('expenses.deleted_message', 1), | ||||
|             }) | ||||
|             this.refreshTable() | ||||
|             return true | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleExpenses() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('expenses.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deleteMultipleExpenses() | ||||
|  | ||||
|           if (request.data.success) { | ||||
|             window.toastr['success'](this.$tc('expenses.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('expenses.deleted_message', 2), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|           } else if (request.data.error) { | ||||
|             window.toastr['error'](request.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -722,6 +722,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('customFields', ['fetchCustomFields']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     selectFixed() { | ||||
|       if (this.newInvoice.discount_type === 'fixed') { | ||||
|         return | ||||
| @ -918,8 +920,10 @@ export default { | ||||
|         .then((res) => { | ||||
|           if (res.data) { | ||||
|             this.$router.push(`/admin/invoices/${res.data.invoice.id}/view`) | ||||
|  | ||||
|             window.toastr['success'](this.$t('invoices.created_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('invoices.created_message'), | ||||
|             }) | ||||
|           } | ||||
|  | ||||
|           this.isLoading = false | ||||
| @ -935,13 +939,17 @@ export default { | ||||
|           this.isLoading = false | ||||
|           if (res.data.success) { | ||||
|             this.$router.push(`/admin/invoices/${res.data.invoice.id}/view`) | ||||
|             window.toastr['success'](this.$t('invoices.updated_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('invoices.updated_message'), | ||||
|             }) | ||||
|           } | ||||
|  | ||||
|           if (res.data.error === 'invalid_due_amount') { | ||||
|             window.toastr['error']( | ||||
|               this.$t('invoices.invalid_due_amount_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('invoices.invalid_due_amount_message'), | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         .catch((err) => { | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
|   <base-page> | ||||
|     <sw-page-header :title="$t('invoices.title')"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item to="#" :title="$tc('invoices.invoice', 2)" active /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="dashboard" /> | ||||
|         <sw-breadcrumb-item :title="$tc('invoices.invoice', 2)" to="#" active /> | ||||
|       </sw-breadcrumb> | ||||
|  | ||||
|       <template slot="actions"> | ||||
| @ -93,8 +93,8 @@ | ||||
|  | ||||
|         <label | ||||
|           class="absolute text-sm leading-snug text-black cursor-pointer" | ||||
|           @click="clearFilter" | ||||
|           style="top: 10px; right: 15px" | ||||
|           @click="clearFilter" | ||||
|           >{{ $t('general.clear_all') }}</label | ||||
|         > | ||||
|       </sw-filter-wrapper> | ||||
| @ -258,7 +258,9 @@ | ||||
|               :bg-color="$utils.getBadgeStatusColor(row.status).bgColor" | ||||
|               :color="$utils.getBadgeStatusColor(row.status).color" | ||||
|             > | ||||
|               {{ $utils.getStatusTranslation(row.paid_status.replace('_', ' ')) }} | ||||
|               {{ | ||||
|                 $utils.getStatusTranslation(row.paid_status.replace('_', ' ')) | ||||
|               }} | ||||
|             </sw-badge> | ||||
|           </template> | ||||
|         </sw-table-column> | ||||
| @ -289,16 +291,16 @@ | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`invoices/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
|               </sw-dropdown-item> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`invoices/${row.id}/view`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <eye-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('invoices.view') }} | ||||
| @ -334,8 +336,8 @@ | ||||
|                   row.status === 'VIEWED' || | ||||
|                   row.status === 'OVERDUE' | ||||
|                 " | ||||
|                 tag-name="router-link" | ||||
|                 :to="`/admin/payments/${row.id}/create`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <credit-card-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('payments.record_payment') }} | ||||
| @ -510,6 +512,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async sendInvoice(invoice) { | ||||
|       this.openModal({ | ||||
|         title: this.$t('invoices.send_invoice'), | ||||
| @ -521,14 +525,30 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async markInvoiceAsSent(id) { | ||||
|       swal({ | ||||
|       this.$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 (value) => { | ||||
|         if (value) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           const data = { | ||||
|             id: id, | ||||
|             status: 'SENT', | ||||
| @ -536,29 +556,49 @@ export default { | ||||
|           let response = await this.markAsSent(data) | ||||
|           this.refreshTable() | ||||
|           if (response.data) { | ||||
|             window.toastr['success']( | ||||
|               this.$tc('invoices.mark_as_sent_successfully') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.mark_as_sent_successfully'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async onCloneInvoice(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.confirm_clone'), | ||||
|         icon: '/assets/icon/check-circle-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.cloneInvoice({ id }) | ||||
|  | ||||
|           this.refreshTable() | ||||
|  | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('invoices.cloned_successfully')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.cloned_successfully'), | ||||
|             }) | ||||
|             this.$router.push( | ||||
|               `/admin/invoices/${response.data.invoice.id}/edit` | ||||
|             ) | ||||
| @ -665,31 +705,43 @@ export default { | ||||
|  | ||||
|     async removeInvoice(id) { | ||||
|       this.id = id | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('invoices.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteInvoice({ ids: [id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('invoices.deleted_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (res.data.error === 'payment_attached') { | ||||
|             window.toastr['error']( | ||||
|               this.$t('invoices.payment_attached_message'), | ||||
|               this.$t('general.action_failed') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: | ||||
|                 (this.$t('invoices.payment_attached_message'), | ||||
|                 this.$t('general.action_failed')), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](res.data.error) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: res.data.error, | ||||
|           }) | ||||
|  | ||||
|           return true | ||||
|         } | ||||
|         this.resetSelectedInvoices() | ||||
| @ -697,30 +749,41 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleInvoices() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('invoices.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteMultipleInvoices() | ||||
|  | ||||
|           if (res.data.error === 'payment_attached') { | ||||
|             window.toastr['error']( | ||||
|               this.$t('invoices.payment_attached_message'), | ||||
|               this.$t('general.action_failed') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: | ||||
|                 (this.$t('invoices.payment_attached_message'), | ||||
|                 this.$t('general.action_failed')), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (res.data) { | ||||
|             this.$refs.table.refresh() | ||||
|             this.resetSelectedInvoices() | ||||
|             window.toastr['success'](this.$tc('invoices.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.deleted_message', 2), | ||||
|             }) | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -323,6 +323,7 @@ export default { | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     hasActiveUrl(id) { | ||||
|       return this.$route.params.id == id | ||||
| @ -393,30 +394,45 @@ export default { | ||||
|       return true | ||||
|     }, | ||||
|     async onMarkAsSent() { | ||||
|       window | ||||
|         .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 (value) => { | ||||
|           if (value) { | ||||
|             this.isMarkingAsSent = true | ||||
|             let response = await this.markAsSent({ | ||||
|               id: this.invoice.id, | ||||
|               status: 'SENT', | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.invoice_mark_as_sent'), | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           this.isMarkingAsSent = true | ||||
|           let response = await this.markAsSent({ | ||||
|             id: this.invoice.id, | ||||
|             status: 'SENT', | ||||
|           }) | ||||
|           this.isMarkingAsSent = false | ||||
|           if (response.data) { | ||||
|             this.invoice.status = 'SENT' | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.marked_as_sent_message'), | ||||
|             }) | ||||
|             this.isMarkingAsSent = false | ||||
|             if (response.data) { | ||||
|               this.invoice.status = 'SENT' | ||||
|               window.toastr['success']( | ||||
|                 this.$tc('invoices.marked_as_sent_message') | ||||
|               ) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     async onSendInvoice() { | ||||
|       this.openModal({ | ||||
| @ -430,29 +446,38 @@ export default { | ||||
|       let pdfUrl = `${window.location.origin}/invoices/pdf/${this.invoice.unique_hash}` | ||||
|  | ||||
|       let response = this.$utils.copyTextToClipboard(pdfUrl) | ||||
|  | ||||
|       window.toastr['success'](this.$t('general.copied_pdf_url_clipboard')) | ||||
|       this.showNotification({ | ||||
|         type: 'success', | ||||
|         message: this.$t('general.copied_pdf_url_clipboard'), | ||||
|       }) | ||||
|     }, | ||||
|     async removeInvoice(id) { | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: 'you will not be able to recover this invoice!', | ||||
|           icon: '/assets/icon/trash-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (value) => { | ||||
|           if (value) { | ||||
|             let request = await this.deleteInvoice({ ids: [id] }) | ||||
|             if (request.data.success) { | ||||
|               window.toastr['success'](this.$tc('invoices.deleted_message', 1)) | ||||
|               this.$router.push('/admin/invoices') | ||||
|             } else if (request.data.error) { | ||||
|               window.toastr['error'](request.data.message) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: 'you will not be able to recover this invoice!', | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deleteInvoice({ ids: [id] }) | ||||
|           if (request.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('invoices.deleted_message', 1), | ||||
|             }) | ||||
|             this.$router.push('/admin/invoices') | ||||
|           } else if (request.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
|  | ||||
| @ -312,6 +312,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async setTaxPerItem() { | ||||
|       let response = await this.fetchCompanySettings(['tax_per_item']) | ||||
|  | ||||
| @ -385,15 +387,24 @@ export default { | ||||
|         this.isLoading = false | ||||
|  | ||||
|         if (!this.isEdit) { | ||||
|           window.toastr['success'](this.$tc('items.created_message')) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$tc('items.created_message'), | ||||
|           }) | ||||
|           this.$router.push('/admin/items') | ||||
|           return true | ||||
|         } else { | ||||
|           window.toastr['success'](this.$tc('items.updated_message')) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$tc('items.updated_message'), | ||||
|           }) | ||||
|           this.$router.push('/admin/items') | ||||
|           return true | ||||
|         } | ||||
|         window.toastr['error'](response.data.error) | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: response.data.error, | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
| @ -348,6 +348,8 @@ export default { | ||||
|       'fetchItemUnits', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     refreshTable() { | ||||
|       this.$refs.table.refresh() | ||||
|     }, | ||||
| @ -397,52 +399,71 @@ export default { | ||||
|  | ||||
|     async removeItems(id) { | ||||
|       this.id = id | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('items.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteItem({ ids: [id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('items.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('items.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (res.data.error === 'item_attached') { | ||||
|             window.toastr['error']( | ||||
|               this.$tc('items.item_attached_message'), | ||||
|               this.$t('general.action_failed') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: | ||||
|                 (this.$tc('items.item_attached_message'), | ||||
|                 this.$t('general.action_failed')), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](res.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: res.data.message, | ||||
|           }) | ||||
|           return true | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleItems() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('items.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteMultipleItems() | ||||
|  | ||||
|           if (res.data.success || res.data.items) { | ||||
|             window.toastr['success'](this.$tc('items.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('items.deleted_message', 2), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| <template> | ||||
|   <div v-if="isAppLoaded" class="h-full"> | ||||
|     <base-modal /> | ||||
|     <base-notification /> | ||||
|     <site-header /> | ||||
|     <div class="flex h-screen pt-16 pb-10 overflow-hidden"> | ||||
|       <site-sidebar /> | ||||
| @ -20,6 +21,7 @@ import SiteSidebar from './partials/TheSiteSidebar.vue' | ||||
| import BaseModal from '../../components/base/modal/BaseModal' | ||||
| import { RefreshIcon } from '@vue-hero-icons/solid' | ||||
| import { mapActions, mapGetters } from 'vuex' | ||||
| import BaseNotification from '../../components/base/BaseNotification.vue' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @ -28,6 +30,7 @@ export default { | ||||
|     SiteFooter, | ||||
|     BaseModal, | ||||
|     RefreshIcon, | ||||
|     BaseNotification, | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <template> | ||||
|   <div class="grid h-full grid-cols-12 overflow-y-hidden bg-gray-100"> | ||||
|     <base-notification /> | ||||
|     <div | ||||
|       class="flex items-center justify-center w-full max-w-sm col-span-12 p-4 mx-auto text-gray-900 md:p-8 md:col-span-6 lg:col-span-4 flex-2 md:pb-48 md:pt-40" | ||||
|     > | ||||
|  | ||||
| @ -423,6 +423,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('customer', ['fetchCustomers']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     invoiceWithAmount({ invoice_number, due_amount }) { | ||||
|       return `${invoice_number} (${this.$utils.formatGraphMoney( | ||||
|         due_amount, | ||||
| @ -561,25 +563,38 @@ export default { | ||||
|             this.$router.push( | ||||
|               `/admin/payments/${response.data.payment.id}/view` | ||||
|             ) | ||||
|             window.toastr['success'](this.$t('payments.updated_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('payments.updated_message'), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (response.data.error === 'invalid_amount') { | ||||
|             window.toastr['error'](this.$t('invalid_amount_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('invalid_amount_message'), | ||||
|             }) | ||||
|             return false | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](response.data.error) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: response.data.error, | ||||
|           }) | ||||
|         } catch (err) { | ||||
|           this.isLoading = false | ||||
|  | ||||
|           if (err.response.data.errors.payment_number) { | ||||
|             window.toastr['error'](err.response.data.errors.payment_number) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: err.response.data.errors.payment_number, | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](err.response.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: err.response.data.message, | ||||
|           }) | ||||
|         } | ||||
|       } else { | ||||
|         let data = { | ||||
| @ -599,26 +614,39 @@ export default { | ||||
|             this.$router.push( | ||||
|               `/admin/payments/${response.data.payment.id}/view` | ||||
|             ) | ||||
|             window.toastr['success'](this.$t('payments.created_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('payments.created_message'), | ||||
|             }) | ||||
|             this.isLoading = true | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (response.data.error === 'invalid_amount') { | ||||
|             window.toastr['error'](this.$t('invalid_amount_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('invalid_amount_message'), | ||||
|             }) | ||||
|             return false | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](response.data.error) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: response.data.error, | ||||
|           }) | ||||
|         } catch (err) { | ||||
|           this.isLoading = false | ||||
|  | ||||
|           if (err.response.data.errors.payment_number) { | ||||
|             window.toastr['error'](err.response.data.errors.payment_number) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: err.response.data.errors.payment_number, | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](err.response.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: err.response.data.message, | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
|   <base-page class="payments"> | ||||
|     <sw-page-header :title="$t('payments.title')"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item to="#" :title="$tc('payments.payment', 2)" active /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="dashboard" /> | ||||
|         <sw-breadcrumb-item :title="$tc('payments.payment', 2)" to="#" active /> | ||||
|       </sw-breadcrumb> | ||||
|  | ||||
|       <template slot="actions"> | ||||
| @ -202,7 +202,11 @@ | ||||
|           <template slot-scope="row"> | ||||
|             <span>{{ $t('payments.payment_mode') }}</span> | ||||
|             <span> | ||||
|               {{ row.payment_mode ? row.payment_mode : $t('payments.not_selected') }} | ||||
|               {{ | ||||
|                 row.payment_mode | ||||
|                   ? row.payment_mode | ||||
|                   : $t('payments.not_selected') | ||||
|               }} | ||||
|             </span> | ||||
|           </template> | ||||
|         </sw-table-column> | ||||
| @ -216,7 +220,11 @@ | ||||
|           <template slot-scope="row"> | ||||
|             <span>{{ $t('invoices.invoice_number') }}</span> | ||||
|             <span> | ||||
|               {{ row.invoice_number ? row.invoice_number : $t('payments.no_invoice') }} | ||||
|               {{ | ||||
|                 row.invoice_number | ||||
|                   ? row.invoice_number | ||||
|                   : $t('payments.no_invoice') | ||||
|               }} | ||||
|             </span> | ||||
|           </template> | ||||
|         </sw-table-column> | ||||
| @ -239,16 +247,16 @@ | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`payments/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
|               </sw-dropdown-item> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`payments/${row.id}/view`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <eye-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.view') }} | ||||
| @ -371,6 +379,8 @@ export default { | ||||
|       'fetchPaymentModes', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         customer_id: this.filters.customer ? this.filters.customer.id : '', | ||||
| @ -433,43 +443,60 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removePayment(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('payments.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deletePayment({ ids: [id] }) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('payments.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('payments.deleted_message', 1), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](res.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: res.data.message, | ||||
|           }) | ||||
|           return true | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultiplePayments() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('payments.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deleteMultiplePayments() | ||||
|           if (request.data.success) { | ||||
|             window.toastr['success'](this.$tc('payments.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('payments.deleted_message', 2), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|           } else if (request.data.error) { | ||||
|             window.toastr['error'](request.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -282,6 +282,7 @@ export default { | ||||
|       'searchPayment', | ||||
|     ]), | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     hasActiveUrl(id) { | ||||
|       return this.$route.params.id == id | ||||
| @ -364,30 +365,39 @@ export default { | ||||
|       let pdfUrl = `${window.location.origin}/payments/pdf/${this.payment.unique_hash}` | ||||
|  | ||||
|       let response = this.$utils.copyTextToClipboard(pdfUrl) | ||||
|  | ||||
|       window.toastr['success'](this.$t('general.copied_pdf_url_clipboard')) | ||||
|       this.showNotification({ | ||||
|         type: 'success', | ||||
|         message: this.$t('general.copied_pdf_url_clipboard'), | ||||
|       }) | ||||
|     }, | ||||
|     async removePayment(id) { | ||||
|       this.id = id | ||||
|       window | ||||
|         .swal({ | ||||
|           title: this.$t('general.are_you_sure'), | ||||
|           text: 'you will not be able to recover this payment!', | ||||
|           icon: '/assets/icon/trash-solid.svg', | ||||
|           buttons: true, | ||||
|           dangerMode: true, | ||||
|         }) | ||||
|         .then(async (value) => { | ||||
|           if (value) { | ||||
|             let request = await this.deletePayment({ ids: [id] }) | ||||
|             if (request.data.success) { | ||||
|               window.toastr['success'](this.$tc('payments.deleted_message', 1)) | ||||
|               this.$router.push('/admin/payments') | ||||
|             } else if (request.data.error) { | ||||
|               window.toastr['error'](request.data.message) | ||||
|             } | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: 'you will not be able to recover this payment!', | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let request = await this.deletePayment({ ids: [id] }) | ||||
|           if (request.data.success) { | ||||
|             this.showToaster({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('payments.deleted_message', 1), | ||||
|             }) | ||||
|             this.$router.push('/admin/payments') | ||||
|           } else if (request.data.error) { | ||||
|             this.showToaster({ | ||||
|               type: 'error', | ||||
|               message: request.data.message, | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
|  | ||||
| @ -58,8 +58,8 @@ | ||||
|             :options="reportTypes" | ||||
|             :allow-empty="false" | ||||
|             :show-labels="false" | ||||
|             class="mt-2" | ||||
|             :placeholder="$t('reports.sales.report_type')" | ||||
|             class="mt-2" | ||||
|             @input="getInitialReport" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
| @ -79,7 +79,7 @@ | ||||
|         class="hidden w-full h-screen border-gray-100 border-solid rounded md:flex" | ||||
|       /> | ||||
|       <a | ||||
|         class="flex items-center justify-center h-10 px-5 py-1 text-sm font-medium leading-none text-center text-white whitespace-nowrap rounded md:hidden bg-primary-500" | ||||
|         class="flex items-center justify-center h-10 px-5 py-1 text-sm font-medium leading-none text-center text-white rounded whitespace-nowrap md:hidden bg-primary-500" | ||||
|         @click="viewReportsPDF" | ||||
|       > | ||||
|         <document-text-icon /> | ||||
|  | ||||
| @ -33,18 +33,18 @@ | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.disk.select_disk')" | ||||
|             :allow-empty="false" | ||||
|             :custom-label="getCustomLabel" | ||||
|             track-by="id" | ||||
|             label="name" | ||||
|             :custom-label="getCustomLabel" | ||||
|             @select="refreshTable" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|       <sw-table-component | ||||
|         ref="table" | ||||
|         variant="gray" | ||||
|         :show-filter="false" | ||||
|         :data="fetchBackupsData" | ||||
|         variant="gray" | ||||
|       > | ||||
|         <sw-table-column :label="$t('settings.backup.path')" show="path"> | ||||
|           <template slot-scope="row"> | ||||
| @ -119,6 +119,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     getCustomLabel({ driver, name }) { | ||||
|       if (!name) { | ||||
|         return | ||||
| @ -127,14 +129,17 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async onRemoveBackup(backup) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.backup.backup_confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let data = { | ||||
|             disk: this.filters.selected_disk.driver, | ||||
|             file_disk_id: this.filters.selected_disk.id, | ||||
| @ -142,7 +147,10 @@ export default { | ||||
|           } | ||||
|           let response = await this.removeBackup(data) | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success'](this.$t('settings.backup.deleted_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.backup.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
| @ -170,9 +178,10 @@ export default { | ||||
|       let response = await this.fetchBackups(data) | ||||
|  | ||||
|       if (response.data.error) { | ||||
|         window.toastr['error']( | ||||
|           this.$t('settings.backup.' + response.data.error) | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: this.$t('settings.backup.' + response.data.error), | ||||
|         }) | ||||
|       } | ||||
|  | ||||
|       this.isRequestOngoing = false | ||||
| @ -225,7 +234,10 @@ export default { | ||||
|         }) | ||||
|         .catch((e) => { | ||||
|           this.isRequestOngoing = false | ||||
|           window.toastr['error'](e.response.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: e.response.data.message, | ||||
|           }) | ||||
|         }) | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="updateCompanyData" class="relative h-full"> | ||||
|   <form class="relative h-full" @submit.prevent="updateCompanyData"> | ||||
|     <base-loader v-if="isRequestOnGoing" :show-bg-overlay="true" /> | ||||
|     <sw-card variant="setting-card"> | ||||
|       <template slot="header"> | ||||
| @ -41,8 +41,8 @@ | ||||
|           </div> | ||||
|  | ||||
|           <sw-avatar | ||||
|             trigger="#logo-box" | ||||
|             :preview-avatar="previewLogo" | ||||
|             trigger="#logo-box" | ||||
|             @changed="onChange" | ||||
|             @uploadHandler="onUploadHandler" | ||||
|             @handleUploadError="onHandleUploadError" | ||||
| @ -74,8 +74,8 @@ | ||||
|         <sw-input-group :label="$tc('settings.company_info.phone')"> | ||||
|           <sw-input | ||||
|             v-model="formData.phone" | ||||
|             class="mt-2" | ||||
|             :placeholder="$t('settings.company_info.phone')" | ||||
|             class="mt-2" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
| @ -153,9 +153,9 @@ | ||||
|       </div> | ||||
|  | ||||
|       <sw-button | ||||
|         class="mt-4" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         class="mt-4" | ||||
|         variant="primary" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="mr-2 -ml-1" /> | ||||
| @ -269,13 +269,17 @@ export default { | ||||
|   methods: { | ||||
|     ...mapActions('company', ['updateCompany', 'updateCompanyLogo']), | ||||
|     ...mapActions('user', ['fetchCurrentUser']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewLogo = cropper | ||||
|         .getCroppedCanvas() | ||||
|         .toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: 'Oops! Something went wrong...', | ||||
|       }) | ||||
|     }, | ||||
|     onChange(file) { | ||||
|       this.cropperOutputMime = file.type | ||||
| @ -322,13 +326,17 @@ export default { | ||||
|           await this.updateCompanyLogo(logoData) | ||||
|         } | ||||
|         this.isLoading = false | ||||
|         window.toastr['success']( | ||||
|           this.$t('settings.company_info.updated_message') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('settings.company_info.updated_message'), | ||||
|         }) | ||||
|         return true | ||||
|       } | ||||
|       this.isLoading = false | ||||
|       window.toastr['error'](response.data.error) | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: response.data.error, | ||||
|       }) | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -23,9 +23,9 @@ | ||||
|  | ||||
|     <sw-table-component | ||||
|       ref="table" | ||||
|       variant="gray" | ||||
|       :show-filter="false" | ||||
|       :data="fetchData" | ||||
|       variant="gray" | ||||
|     > | ||||
|       <sw-table-column | ||||
|         :sortable="true" | ||||
| @ -118,6 +118,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('modal', ['openModal']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -138,26 +140,31 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeCustomField(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.custom_fields.custom_field_confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteCustomFields(id) | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.custom_fields.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.custom_fields.deleted_message'), | ||||
|             }) | ||||
|             this.id = null | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error']( | ||||
|             this.$t('settings.custom_fields.already_in_use') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.custom_fields.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -110,6 +110,8 @@ export default { | ||||
|       'deleteCategory', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -132,26 +134,31 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeExpenseCategory(id, index) { | ||||
|       swal({ | ||||
|       this.$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) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>s`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteCategory(id) | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$tc('settings.expense_category.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('settings.expense_category.deleted_message'), | ||||
|             }) | ||||
|             this.id = null | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error']( | ||||
|             this.$t('settings.expense_category.already_in_use') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.expense_category.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -27,9 +27,9 @@ | ||||
|  | ||||
|       <sw-table-component | ||||
|         ref="table" | ||||
|         variant="gray" | ||||
|         :show-filter="false" | ||||
|         :data="fetchData" | ||||
|         variant="gray" | ||||
|         table-class="table tax-table" | ||||
|         class="mt-0 mb-3" | ||||
|       > | ||||
| @ -173,6 +173,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('company', ['updateCompanySettings', 'fetchCompanySettings']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -243,20 +245,39 @@ export default { | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|  | ||||
|       if (response.data.success) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|       this.$refs.table.refresh() | ||||
|     }, | ||||
|  | ||||
|     async setDefaultDiskData(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.disk.set_default_disk_confirm'), | ||||
|         icon: '/assets/icon/check-circle-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg | ||||
|             aria-hidden="true" | ||||
|             class="w-6 h-6" | ||||
|             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>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           this.loading = true | ||||
|           let data = { | ||||
|             set_as_default: true, | ||||
| @ -266,26 +287,33 @@ export default { | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             this.refreshTable() | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.disk.success_set_default_disk') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.disk.success_set_default_disk'), | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeDisk(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.disk.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteFileDisk(id) | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success'](this.$t('settings.disk.deleted_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.disk.deleted_message'), | ||||
|             }) | ||||
|             this.refreshTable() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
| @ -76,6 +76,7 @@ export default { | ||||
|       'fetchMailConfig', | ||||
|       'updateMailConfig', | ||||
|     ]), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async loadData() { | ||||
|       this.isRequestOnGoing = true | ||||
| @ -100,17 +101,22 @@ export default { | ||||
|         let response = await this.updateMailConfig(mailConfigData) | ||||
|         if (response.data.success) { | ||||
|           this.isLoading = false | ||||
|           window.toastr['success']( | ||||
|             this.$t('wizard.success.' + response.data.success) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('wizard.success.' + response.data.success), | ||||
|           }) | ||||
|         } else { | ||||
|           window.toastr['error']( | ||||
|             this.$t('wizard.errors.' + response.data.error) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('wizard.errors.' + response.data.error), | ||||
|           }) | ||||
|         } | ||||
|         return true | ||||
|       } catch (e) { | ||||
|         window.toastr['error']('Something went wrong') | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: 'Something went wrong', | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
| @ -27,9 +27,9 @@ | ||||
|  | ||||
|     <sw-table-component | ||||
|       ref="table" | ||||
|       variant="gray" | ||||
|       :show-filter="false" | ||||
|       :data="fetchData" | ||||
|       variant="gray" | ||||
|     > | ||||
|       <sw-table-column | ||||
|         :label="$t('settings.customization.notes.name')" | ||||
| @ -93,6 +93,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('notes', ['fetchNotes', 'deleteNote']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -112,26 +114,31 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|     removeNote(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.customization.notes.note_confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteNote(id) | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.customization.notes.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.customization.notes.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error']( | ||||
|             this.$t('settings.customization.notes.already_in_use') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.customization.notes.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -133,6 +133,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('company', ['fetchCompanySettings', 'updateCompanySettings']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData() { | ||||
|       this.isRequestOnGoing = true | ||||
| @ -176,9 +177,10 @@ export default { | ||||
|       if (response.data.success) { | ||||
|         this.isLoading = false | ||||
|  | ||||
|         window.toastr['success']( | ||||
|           this.$tc('settings.notification.email_save_message') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$tc('settings.notification.email_save_message'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -199,7 +201,10 @@ export default { | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|  | ||||
|       if (response.data.success) { | ||||
|         window.toastr['success'](this.$tc('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$tc('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -220,7 +225,10 @@ export default { | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|  | ||||
|       if (response.data) { | ||||
|         window.toastr['success'](this.$tc('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$tc('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -22,9 +22,9 @@ | ||||
|  | ||||
|     <sw-table-component | ||||
|       ref="table" | ||||
|       variant="gray" | ||||
|       :show-filter="false" | ||||
|       :data="fetchData" | ||||
|       variant="gray" | ||||
|     > | ||||
|       <sw-table-column | ||||
|         :label="$t('settings.customization.payments.mode_name')" | ||||
| @ -79,6 +79,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('payment', ['deletePaymentMode', 'fetchPaymentModes']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -117,29 +119,36 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     removePaymentMode(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t( | ||||
|           'settings.customization.payments.payment_mode_confirm_delete' | ||||
|         ), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deletePaymentMode(id) | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.customization.payments.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t( | ||||
|                 'settings.customization.payments.deleted_message' | ||||
|               ), | ||||
|             }) | ||||
|             this.id = null | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error']( | ||||
|             this.$t('settings.customization.payments.already_in_use') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.customization.payments.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="updatePreferencesData" class="relative"> | ||||
|   <form action="" class="relative" @submit.prevent="updatePreferencesData"> | ||||
|     <base-loader v-if="isRequestOnGoing" :show-bg-overlay="true" /> | ||||
|     <sw-card variant="setting-card"> | ||||
|       <template slot="header"> | ||||
| @ -113,11 +113,11 @@ | ||||
|       </div> | ||||
|  | ||||
|       <sw-button | ||||
|         :disabled="isLoading" | ||||
|         :loading="isLoading" | ||||
|         class="mt-6" | ||||
|         variant="primary" | ||||
|         type="submit" | ||||
|         :disabled="isLoading" | ||||
|         :loading="isLoading" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="mr-2 -ml-1" /> | ||||
|         {{ $tc('settings.company_info.save') }} | ||||
| @ -267,6 +267,8 @@ export default { | ||||
|       'fetchTimeZones', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     currencyNameWithCode({ name, code }) { | ||||
|       return `${code} - ${name}` | ||||
|     }, | ||||
| @ -340,12 +342,16 @@ export default { | ||||
|         this.isLoading = false | ||||
|         // window.i18n.locale = this.formData.language.code | ||||
|         this.setDefaultCurrency(this.formData.currency) | ||||
|         window.toastr['success']( | ||||
|           this.$t('settings.preferences.updated_message') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('settings.preferences.updated_message'), | ||||
|         }) | ||||
|         return true | ||||
|       } | ||||
|       window.toastr['error'](response.data.error) | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: response.data.error, | ||||
|       }) | ||||
|       return true | ||||
|     }, | ||||
|  | ||||
| @ -357,7 +363,10 @@ export default { | ||||
|       } | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|       if (response.data.success) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -160,6 +160,8 @@ export default { | ||||
|     ]), | ||||
|     ...mapActions('company', ['fetchCompanySettings', 'updateCompanySettings']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -194,28 +196,38 @@ export default { | ||||
|       } | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|       if (response.data) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     async removeTax(id, index) { | ||||
|       swal({ | ||||
|       this.$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 (value) => { | ||||
|         if (value) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteTaxType(id) | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.tax_types.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.tax_types.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error'](this.$t('settings.tax_types.already_in_use')) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.tax_types.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -58,9 +58,9 @@ | ||||
|         </label> | ||||
|         <table class="w-1/2 mt-2 border-2 border-gray-200 table-fixed"> | ||||
|           <tr | ||||
|             class="p-2 border-2 border-gray-200" | ||||
|             v-for="(ext, i) in requiredExtentions" | ||||
|             :key="i" | ||||
|             class="p-2 border-2 border-gray-200" | ||||
|           > | ||||
|             <td width="70%" class="p-2 text-sm truncate"> | ||||
|               {{ i }} | ||||
| @ -106,8 +106,8 @@ | ||||
|       <!--  --> | ||||
|       <ul v-if="isUpdating" class="w-full p-0 list-none"> | ||||
|         <li | ||||
|           class="flex justify-between w-full py-3 border-b border-gray-200 border-solid last:border-b-0" | ||||
|           v-for="step in updateSteps" | ||||
|           class="flex justify-between w-full py-3 border-b border-gray-200 border-solid last:border-b-0" | ||||
|         > | ||||
|           <p class="m-0 text-sm leading-8">{{ $t(step.translationKey) }}</p> | ||||
|           <div class="flex flex-row items-center"> | ||||
| @ -115,8 +115,8 @@ | ||||
|               {{ step.time }} | ||||
|             </span> | ||||
|             <span | ||||
|               class="block py-1 text-sm text-center uppercase rounded-full" | ||||
|               :class="statusClass(step)" | ||||
|               class="block py-1 text-sm text-center uppercase rounded-full" | ||||
|               style="width: 88px" | ||||
|             > | ||||
|               {{ getStatus(step) }} | ||||
| @ -130,7 +130,7 @@ | ||||
|  | ||||
| <script> | ||||
| import LoadingIcon from '../../components/icon/LoadingIcon' | ||||
|  | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   components: { | ||||
|     LoadingIcon, | ||||
| @ -228,6 +228,8 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     getStatus(step) { | ||||
|       if (step.started && step.completed) { | ||||
|         return 'finished' | ||||
| @ -266,7 +268,11 @@ export default { | ||||
|         this.isCheckingforUpdate = false | ||||
|  | ||||
|         if (!response.data.version) { | ||||
|           window.toastr['info'](this.$t('settings.update_app.latest_message')) | ||||
|           this.showNotification({ | ||||
|             title: 'Info!', | ||||
|             type: 'info', | ||||
|             message: this.$t('settings.update_app.latest_message'), | ||||
|           }) | ||||
|           return | ||||
|         } | ||||
|  | ||||
| @ -283,16 +289,21 @@ export default { | ||||
|       } catch (e) { | ||||
|         this.isUpdateAvailable = false | ||||
|         this.isCheckingforUpdate = false | ||||
|         window.toastr['error']('Something went wrong') | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: 'Something went wrong', | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     async onUpdateApp() { | ||||
|       let path = null | ||||
|       if (!this.allowToUpdate) { | ||||
|         window.toastr['error']( | ||||
|           'Your current configuration does not match the update requirements. Please try again after all the requirements are fulfilled.  ' | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: | ||||
|             'Your current configuration does not match the update requirements. Please try again after all the requirements are fulfilled.', | ||||
|         }) | ||||
|         return true | ||||
|       } | ||||
|       for (let index = 0; index < this.updateSteps.length; index++) { | ||||
| @ -321,9 +332,10 @@ export default { | ||||
|             currentStep.translationKey == 'settings.update_app.finishing_update' | ||||
|           ) { | ||||
|             this.isUpdating = false | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.update_app.update_success') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.update_app.update_success'), | ||||
|             }) | ||||
|  | ||||
|             setTimeout(() => { | ||||
|               location.reload() | ||||
| @ -332,7 +344,10 @@ export default { | ||||
|         } catch (error) { | ||||
|           currentStep.started = false | ||||
|           currentStep.completed = true | ||||
|           window.toastr['error'](this.$t('validation.something_went_wrong')) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('validation.something_went_wrong'), | ||||
|           }) | ||||
|           this.onUpdateFailed(currentStep.translationKey) | ||||
|           return false | ||||
|         } | ||||
| @ -341,7 +356,7 @@ export default { | ||||
|  | ||||
|     onUpdateFailed(translationKey) { | ||||
|       let stepName = this.$t(translationKey) | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('settings.update_app.update_failed'), | ||||
|         text: this.$tc('settings.update_app.update_failed_text', stepName, { | ||||
|           step: stepName, | ||||
|  | ||||
| @ -264,6 +264,8 @@ export default { | ||||
|  | ||||
|     ...mapActions(['fetchLanguages']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewAvatar = cropper | ||||
|         .getCroppedCanvas() | ||||
| @ -271,7 +273,10 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: 'Oops! Something went wrong...', | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChange(file) { | ||||
| @ -348,10 +353,10 @@ export default { | ||||
|  | ||||
|             this.uploadAvatar(avatarData) | ||||
|           } | ||||
|  | ||||
|           window.toastr['success']( | ||||
|             this.$t('settings.account_settings.updated_message') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('settings.account_settings.updated_message'), | ||||
|           }) | ||||
|  | ||||
|           this.formData.password = '' | ||||
|           this.formData.confirm_password = '' | ||||
|  | ||||
| @ -56,6 +56,7 @@ | ||||
|   </transition> | ||||
| </template> | ||||
| <script> | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
| @ -134,13 +135,17 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async updateAddressSetting() { | ||||
|       let data = { type: 'ADDRESSES', ...this.addresses, large: true } | ||||
|  | ||||
|       // if (this.updateSetting(data)) { | ||||
|       window.toastr['success']( | ||||
|         this.$t('settings.customization.addresses.address_setting_updated') | ||||
|       ) | ||||
|       this.showNotification({ | ||||
|         type: 'success', | ||||
|         message: this.$t( | ||||
|           'settings.customization.addresses.address_setting_updated' | ||||
|         ), | ||||
|       }) | ||||
|       // } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -107,9 +107,7 @@ | ||||
|       </div> | ||||
|       <div class="ml-4"> | ||||
|         <p class="p-0 mb-1 text-base leading-snug text-black"> | ||||
|           {{ | ||||
|             $t('settings.customization.estimates.estimate_email_attachment') | ||||
|           }} | ||||
|           {{ $t('settings.customization.estimates.estimate_email_attachment') }} | ||||
|         </p> | ||||
|  | ||||
|         <p | ||||
| @ -117,7 +115,9 @@ | ||||
|           style="max-width: 480px" | ||||
|         > | ||||
|           {{ | ||||
|             $t('settings.customization.estimates.estimate_email_attachment_setting_description') | ||||
|             $t( | ||||
|               'settings.customization.estimates.estimate_email_attachment_setting_description' | ||||
|             ) | ||||
|           }} | ||||
|         </p> | ||||
|       </div> | ||||
| @ -126,7 +126,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapActions, mapGetters } from 'vuex' | ||||
| import { mapActions } from 'vuex' | ||||
| const { required, maxLength, alpha } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
| @ -244,7 +244,7 @@ export default { | ||||
|  | ||||
|   methods: { | ||||
|     ...mapActions('company', ['updateCompanySettings']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async setEstimateSetting() { | ||||
|       let data = { | ||||
|         settings: { | ||||
| @ -254,7 +254,10 @@ export default { | ||||
|       } | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|       if (response.data) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -286,9 +289,12 @@ export default { | ||||
|       } | ||||
|  | ||||
|       if (this.updateSetting(data)) { | ||||
|         window.toastr['success']( | ||||
|           this.$t('settings.customization.estimates.estimate_setting_updated') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t( | ||||
|             'settings.customization.estimates.estimate_setting_updated' | ||||
|           ), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
| @ -113,9 +113,7 @@ | ||||
|  | ||||
|       <div class="ml-4"> | ||||
|         <p class="p-0 mb-1 text-base leading-snug text-black"> | ||||
|           {{ | ||||
|             $t('settings.customization.invoices.invoice_email_attachment') | ||||
|           }} | ||||
|           {{ $t('settings.customization.invoices.invoice_email_attachment') }} | ||||
|         </p> | ||||
|  | ||||
|         <p | ||||
| @ -123,7 +121,9 @@ | ||||
|           style="max-width: 480px" | ||||
|         > | ||||
|           {{ | ||||
|             $t('settings.customization.invoices.invoice_email_attachment_setting_description') | ||||
|             $t( | ||||
|               'settings.customization.invoices.invoice_email_attachment_setting_description' | ||||
|             ) | ||||
|           }} | ||||
|         </p> | ||||
|       </div> | ||||
| @ -240,6 +240,7 @@ export default { | ||||
|  | ||||
|   methods: { | ||||
|     ...mapActions('company', ['updateCompanySettings']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async setInvoiceSetting() { | ||||
|       let data = { | ||||
| @ -252,7 +253,10 @@ export default { | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|  | ||||
|       if (response.data) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -283,9 +287,12 @@ export default { | ||||
|       } | ||||
|  | ||||
|       if (this.updateSetting(data)) { | ||||
|         window.toastr['success']( | ||||
|           this.$t('settings.customization.invoices.invoice_setting_updated') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t( | ||||
|             'settings.customization.invoices.invoice_setting_updated' | ||||
|           ), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
| @ -9,9 +9,9 @@ | ||||
|  | ||||
|     <sw-table-component | ||||
|       ref="table" | ||||
|       variant="gray" | ||||
|       :data="fetchData" | ||||
|       :show-filter="false" | ||||
|       variant="gray" | ||||
|     > | ||||
|       <sw-table-column | ||||
|         :sortable="true" | ||||
| @ -66,6 +66,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('item', ['deleteItemUnit', 'fetchItemUnits']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async fetchData({ page, filter, sort }) { | ||||
|       let data = { | ||||
|         orderByField: sort.fieldName || 'created_at', | ||||
| @ -104,26 +106,31 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async removeItemUnit(id) { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('settings.customization.items.item_unit_confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (value) => { | ||||
|         if (value) { | ||||
|         icon: 'question', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let response = await this.deleteItemUnit(id) | ||||
|  | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success']( | ||||
|               this.$t('settings.customization.items.deleted_message') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$t('settings.customization.items.deleted_message'), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|           window.toastr['error']( | ||||
|             this.$t('settings.customization.items.already_in_use') | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('settings.customization.items.already_in_use'), | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
| @ -102,9 +102,7 @@ | ||||
|  | ||||
|       <div class="ml-4"> | ||||
|         <p class="p-0 mb-1 text-base leading-snug text-black"> | ||||
|           {{ | ||||
|             $t('settings.customization.payments.payment_email_attachment') | ||||
|           }} | ||||
|           {{ $t('settings.customization.payments.payment_email_attachment') }} | ||||
|         </p> | ||||
|  | ||||
|         <p | ||||
| @ -112,7 +110,9 @@ | ||||
|           style="max-width: 480px" | ||||
|         > | ||||
|           {{ | ||||
|             $t('settings.customization.payments.payment_email_attachment_setting_description') | ||||
|             $t( | ||||
|               'settings.customization.payments.payment_email_attachment_setting_description' | ||||
|             ) | ||||
|           }} | ||||
|         </p> | ||||
|       </div> | ||||
| @ -228,6 +228,8 @@ export default { | ||||
|  | ||||
|     ...mapActions('company', ['updateCompanySettings']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     changeToUppercase(currentTab) { | ||||
|       if (currentTab === 'PAYMENTS') { | ||||
|         this.payments.payment_prefix = this.payments.payment_prefix.toUpperCase() | ||||
| @ -244,7 +246,10 @@ export default { | ||||
|       } | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|       if (response.data) { | ||||
|         window.toastr['success'](this.$t('general.setting_updated')) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t('general.setting_updated'), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -266,9 +271,12 @@ export default { | ||||
|       } | ||||
|  | ||||
|       if (this.updateSetting(data)) { | ||||
|         window.toastr['success']( | ||||
|           this.$t('settings.customization.payments.payment_setting_updated') | ||||
|         ) | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: this.$t( | ||||
|             'settings.customization.payments.payment_setting_updated' | ||||
|           ), | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
| @ -1,19 +1,19 @@ | ||||
| <template> | ||||
|   <base-page v-if="isSuperAdmin" class="item-create"> | ||||
|     <sw-page-header class="mb-3" :title="pageTitle"> | ||||
|     <sw-page-header :title="pageTitle" class="mb-3"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="/admin/dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item to="/admin/users" :title="$tc('users.user', 2)" /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="/admin/dashboard" /> | ||||
|         <sw-breadcrumb-item :title="$tc('users.user', 2)" to="/admin/users" /> | ||||
|         <sw-breadcrumb-item | ||||
|           v-if="$route.name === 'users.edit'" | ||||
|           to="#" | ||||
|           :title="$t('users.edit_user')" | ||||
|           to="#" | ||||
|           active | ||||
|         /> | ||||
|         <sw-breadcrumb-item | ||||
|           v-else | ||||
|           to="#" | ||||
|           :title="$t('users.new_user')" | ||||
|           to="#" | ||||
|           active | ||||
|         /> | ||||
|       </sw-breadcrumb> | ||||
| @ -43,8 +43,8 @@ | ||||
|  | ||||
|             <sw-input-group | ||||
|               :label="$t('users.email')" | ||||
|               class="mt-4" | ||||
|               :error="emailError" | ||||
|               class="mt-4" | ||||
|               required | ||||
|             > | ||||
|               <sw-input | ||||
| @ -229,6 +229,8 @@ export default { | ||||
|   methods: { | ||||
|     ...mapActions('users', ['addUser', 'fetchUser', 'updateUser']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     async loadEditData() { | ||||
|       let response = await this.fetchUser(this.$route.params.id) | ||||
|  | ||||
| @ -251,12 +253,18 @@ export default { | ||||
|           response = await this.updateUser(this.formData) | ||||
|           let data | ||||
|           if (response.data.success) { | ||||
|             window.toastr['success'](this.$tc('users.updated_message')) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('users.updated_message'), | ||||
|             }) | ||||
|             this.$router.push('/admin/users') | ||||
|             this.isLoading = false | ||||
|           } | ||||
|           if (response.data.error) { | ||||
|             window.toastr['error'](this.$t('validation.email_already_taken')) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: this.$t('validation.email_already_taken'), | ||||
|             }) | ||||
|           } | ||||
|         } else { | ||||
|           response = await this.addUser(this.formData) | ||||
| @ -264,7 +272,10 @@ export default { | ||||
|           if (response.data.success) { | ||||
|             this.isLoading = false | ||||
|             if (!this.isEdit) { | ||||
|               window.toastr['success'](this.$tc('users.created_message')) | ||||
|               this.showNotification({ | ||||
|                 type: 'success', | ||||
|                 message: this.$tc('users.created_message'), | ||||
|               }) | ||||
|               this.$router.push('/admin/users') | ||||
|               return true | ||||
|             } | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
|   <base-page v-if="isSuperAdmin" class="items"> | ||||
|     <sw-page-header :title="$t('users.title')"> | ||||
|       <sw-breadcrumb slot="breadcrumbs"> | ||||
|         <sw-breadcrumb-item to="dashboard" :title="$t('general.home')" /> | ||||
|         <sw-breadcrumb-item to="#" :title="$tc('users.title', 2)" active /> | ||||
|         <sw-breadcrumb-item :title="$t('general.home')" to="dashboard" /> | ||||
|         <sw-breadcrumb-item :title="$tc('users.title', 2)" to="#" active /> | ||||
|       </sw-breadcrumb> | ||||
|  | ||||
|       <template slot="actions"> | ||||
| @ -91,7 +91,7 @@ | ||||
|       </sw-button> | ||||
|     </sw-empty-table-placeholder> | ||||
|  | ||||
|     <div class="relative table-container" v-show="!showEmptyScreen"> | ||||
|     <div v-show="!showEmptyScreen" class="relative table-container"> | ||||
|       <div | ||||
|         class="relative flex items-center justify-between h-10 mt-5 list-none border-b-2 border-gray-200 border-solid" | ||||
|       > | ||||
| @ -209,8 +209,8 @@ | ||||
|               <dot-icon slot="activator" /> | ||||
|  | ||||
|               <sw-dropdown-item | ||||
|                 tag-name="router-link" | ||||
|                 :to="`users/${row.id}/edit`" | ||||
|                 tag-name="router-link" | ||||
|               > | ||||
|                 <pencil-icon class="h-5 mr-3 text-gray-600" /> | ||||
|                 {{ $t('general.edit') }} | ||||
| @ -302,17 +302,17 @@ export default { | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     if (!this.isSuperAdmin) { | ||||
|       this.$router.push('/admin/dashboard') | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     filters: { | ||||
|       handler: 'setFilters', | ||||
|       deep: true, | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     if (!this.isSuperAdmin) { | ||||
|       this.$router.push('/admin/dashboard') | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   destroyed() { | ||||
|     if (this.selectAllField) { | ||||
| @ -330,6 +330,8 @@ export default { | ||||
|       'setSelectAllState', | ||||
|     ]), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|  | ||||
|     refreshTable() { | ||||
|       this.$refs.table.refresh() | ||||
|     }, | ||||
| @ -384,52 +386,71 @@ export default { | ||||
|       let user = [] | ||||
|       user.push(id) | ||||
|  | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('users.confirm_delete'), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteUser(user) | ||||
|  | ||||
|           if (res.data.success) { | ||||
|             window.toastr['success'](this.$tc('users.deleted_message', 1)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('users.deleted_message', 1), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           if (res.data.error === 'user_attached') { | ||||
|             window.toastr['error']( | ||||
|               this.$tc('users.user_attached_message'), | ||||
|               this.$t('general.action_failed') | ||||
|             ) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: | ||||
|                 (this.$tc('users.user_attached_message'), | ||||
|                 this.$t('general.action_failed')), | ||||
|             }) | ||||
|             return true | ||||
|           } | ||||
|  | ||||
|           window.toastr['error'](res.data.message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: res.data.message, | ||||
|           }) | ||||
|           return true | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeMultipleUsers() { | ||||
|       swal({ | ||||
|       this.$swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('users.confirm_delete', 2), | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true, | ||||
|       }).then(async (willDelete) => { | ||||
|         if (willDelete) { | ||||
|         icon: 'error', | ||||
|         iconHtml: `<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-red-600"fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                       <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | ||||
|                     </svg>`, | ||||
|         showCancelButton: true, | ||||
|         showConfirmButton: true, | ||||
|       }).then(async (result) => { | ||||
|         if (result.value) { | ||||
|           let res = await this.deleteMultipleUsers() | ||||
|  | ||||
|           if (res.data.success || res.data.users) { | ||||
|             window.toastr['success'](this.$tc('users.deleted_message', 2)) | ||||
|             this.showNotification({ | ||||
|               type: 'success', | ||||
|               message: this.$tc('users.deleted_message', 2), | ||||
|             }) | ||||
|             this.$refs.table.refresh() | ||||
|           } else if (res.data.error) { | ||||
|             window.toastr['error'](res.data.message) | ||||
|             this.showNotification({ | ||||
|               type: 'error', | ||||
|               message: res.data.message, | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -33,8 +33,8 @@ | ||||
|             </div> | ||||
|  | ||||
|             <sw-avatar | ||||
|               trigger="#logo-box" | ||||
|               :preview-avatar="previewLogo" | ||||
|               trigger="#logo-box" | ||||
|               @changed="onChange" | ||||
|               @uploadHandler="onUploadHandler" | ||||
|               @handleUploadError="onHandleUploadError" | ||||
| @ -156,7 +156,7 @@ const { required, maxLength } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     CloudUploadIcon | ||||
|     CloudUploadIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @ -197,12 +197,6 @@ export default { | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     country({ id }) { | ||||
|       this.companyData.country_id = id | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     companyNameError() { | ||||
|       if (!this.$v.companyData.name.$error) { | ||||
| @ -241,12 +235,18 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     country({ id }) { | ||||
|       this.companyData.country_id = id | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.fetchCountries() | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('company', ['setSelectedCompany']), | ||||
|  | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewLogo = cropper | ||||
|         .getCroppedCanvas() | ||||
| @ -254,7 +254,10 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: 'Oops! Something went wrong...', | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChange(file) { | ||||
|  | ||||
| @ -21,7 +21,7 @@ import Mysql from './database/MysqlDatabase' | ||||
| import Pgsql from './database/PgsqlDatabase' | ||||
| import Sqlite from './database/SqliteDatabase' | ||||
| import Sqlsrv from './database/SqlsrvDatabase' | ||||
|  | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   components: { | ||||
|     Mysql, | ||||
| @ -44,6 +44,7 @@ export default { | ||||
|     this.getDatabaseConfig(this.database_connection) | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async getDatabaseConfig(connection) { | ||||
|       this.isLoading = this.isFetching = true | ||||
|  | ||||
| @ -80,20 +81,28 @@ export default { | ||||
|  | ||||
|           this.$emit('next', 3) | ||||
|  | ||||
|           window.toastr['success']( | ||||
|             this.$t('wizard.success.' + response.data.success) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('wizard.success.' + response.data.success), | ||||
|           }) | ||||
|  | ||||
|           return true | ||||
|         } else if (response.data.error) { | ||||
|           window.toastr['error']( | ||||
|             this.$t('wizard.errors.' + response.data.error) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('wizard.errors.' + response.data.error), | ||||
|           }) | ||||
|         } else if (response.data.error_message) { | ||||
|           window.toastr['error'](response.data.error_message) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: response.data.error_message, | ||||
|           }) | ||||
|         } | ||||
|       } catch (e) { | ||||
|         window.toastr['error'](e.response.data.message) | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: e.response.data.message, | ||||
|         }) | ||||
|       } finally { | ||||
|         this.isLoading = this.isFetching = false | ||||
|       } | ||||
|  | ||||
| @ -24,7 +24,7 @@ import Smtp from './mail-driver/SmtpMailDriver' | ||||
| import Mailgun from './mail-driver/MailgunMailDriver' | ||||
| import Ses from './mail-driver/SesMailDriver' | ||||
| import Basic from './mail-driver/BasicMailDriver' | ||||
|  | ||||
| import { mapActions } from 'vuex' | ||||
| export default { | ||||
|   components: { | ||||
|     Smtp, | ||||
| @ -48,6 +48,7 @@ export default { | ||||
|     this.getMailDrivers() | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     async getMailDrivers() { | ||||
|       this.isLoading = this.isFetching = true | ||||
|  | ||||
| @ -67,19 +68,24 @@ export default { | ||||
|         ) | ||||
|         if (response.data.success) { | ||||
|           this.$emit('next', 4) | ||||
|           window.toastr['success']( | ||||
|             this.$t('wizard.success.' + response.data.success) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'success', | ||||
|             message: this.$t('wizard.success.' + response.data.success), | ||||
|           }) | ||||
|         } else { | ||||
|           window.toastr['error']( | ||||
|             this.$t('wizard.errors.' + response.data.error) | ||||
|           ) | ||||
|           this.showNotification({ | ||||
|             type: 'error', | ||||
|             message: this.$t('wizard.errors.' + response.data.error), | ||||
|           }) | ||||
|         } | ||||
|         this.isLoading = this.isFetching = false | ||||
|         return true | ||||
|       } catch (e) { | ||||
|         this.isLoading = this.isFetching = false | ||||
|         window.toastr['error']('Something went wrong') | ||||
|         this.showNotification({ | ||||
|           type: 'error', | ||||
|           message: 'Something went wrong', | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| @ -75,14 +75,14 @@ export default { | ||||
|         let self = this | ||||
|  | ||||
|         if (this.errors) { | ||||
|           swal({ | ||||
|           this.$swal({ | ||||
|             title: this.$t('wizard.permissions.permission_confirm_title'), | ||||
|             text: this.$t('wizard.permissions.permission_confirm_desc'), | ||||
|             icon: 'warning', | ||||
|             buttons: true, | ||||
|             dangerMode: true, | ||||
|           }).then(async (willConfirm) => { | ||||
|             if (willConfirm) { | ||||
|             showCancelButton: true, | ||||
|             showConfirmButton: true, | ||||
|           }).then(async (result) => { | ||||
|             if (result.value) { | ||||
|               self.isLoading = this.isFetching = false | ||||
|             } | ||||
|           }) | ||||
|  | ||||
| @ -211,6 +211,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('company', ['updateCompanySettings', 'setSelectedCompany']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     ...mapActions([ | ||||
|       'fetchLanguages', | ||||
|       'fetchCurrencies', | ||||
| @ -288,7 +289,10 @@ export default { | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.$emit('next', 'COMPLETED') | ||||
|         window.toastr['success']('Login Successful') | ||||
|         this.showNotification({ | ||||
|           type: 'success', | ||||
|           message: 'Login Successful', | ||||
|         }) | ||||
|         this.$router.push('/admin/dashboard') | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -208,13 +208,17 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('user', ['uploadAvatar']), | ||||
|     ...mapActions('notification', ['showNotification']), | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewAvatar = cropper | ||||
|         .getCroppedCanvas() | ||||
|         .toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|       this.showNotification({ | ||||
|         type: 'error', | ||||
|         message: 'Oops! Something went wrong...', | ||||
|       }) | ||||
|     }, | ||||
|     onChange(file) { | ||||
|       this.cropperOutputMime = file.type | ||||
|  | ||||
		Reference in New Issue
	
	Block a user