mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-30 21:21:09 -04:00 
			
		
		
		
	Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into recurring-index-refresh
This commit is contained in:
		| @ -23,9 +23,11 @@ | ||||
|       @click.stop | ||||
|     > | ||||
|       <div class="flex relative justify-between mb-2"> | ||||
|         <label class="flex-1 text-base font-medium text-left text-gray-900"> | ||||
|           {{ selectedCustomer.name }} | ||||
|         </label> | ||||
|         <BaseText | ||||
|           :text="selectedCustomer.name" | ||||
|           :length="30" | ||||
|           class="flex-1 text-base font-medium text-left text-gray-900" | ||||
|         /> | ||||
|         <div class="flex"> | ||||
|           <a | ||||
|             class=" | ||||
| @ -302,8 +304,10 @@ | ||||
|                   </span> | ||||
|  | ||||
|                   <div class="flex flex-col justify-center text-left"> | ||||
|                     <label | ||||
|                     <BaseText | ||||
|                       v-if="customer.name" | ||||
|                       :text="customer.name" | ||||
|                       :length="30" | ||||
|                       class=" | ||||
|                         m-0 | ||||
|                         text-base | ||||
| @ -311,12 +315,11 @@ | ||||
|                         leading-tight | ||||
|                         cursor-pointer | ||||
|                       " | ||||
|                     > | ||||
|                       {{ customer.name }} | ||||
|                     </label> | ||||
|  | ||||
|                     <label | ||||
|                     /> | ||||
|                     <BaseText | ||||
|                       v-if="customer.contact_name" | ||||
|                       :text="customer.contact_name" | ||||
|                       :length="30" | ||||
|                       class=" | ||||
|                         m-0 | ||||
|                         text-sm | ||||
| @ -324,9 +327,7 @@ | ||||
|                         text-gray-400 | ||||
|                         cursor-pointer | ||||
|                       " | ||||
|                     > | ||||
|                       {{ customer.contact_name }} | ||||
|                     </label> | ||||
|                     /> | ||||
|                   </div> | ||||
|                 </li> | ||||
|                 <div | ||||
|  | ||||
							
								
								
									
										31
									
								
								resources/scripts/components/base/BaseText.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								resources/scripts/components/base/BaseText.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| <template> | ||||
|   <BaseCustomTag :tag="tag" :title="text"> | ||||
|     {{ displayText }} | ||||
|   </BaseCustomTag> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { computed } from "vue" | ||||
|  | ||||
| const props = defineProps({ | ||||
|   tag: { | ||||
|     type: String, | ||||
|     default: 'div', | ||||
|   }, | ||||
|  | ||||
|   text: { | ||||
|     type: String, | ||||
|     default: '', | ||||
|   }, | ||||
|  | ||||
|   length: { | ||||
|     type: Number, | ||||
|     default: 0, | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const displayText = computed(() => { | ||||
|  | ||||
|   return props.text.length < props.length ?  props.text : `${props.text.substring(0 , props.length)}...` | ||||
| }) | ||||
| </script> | ||||
| @ -45,7 +45,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { watch, computed, ref, onMounted } from 'vue' | ||||
| import { watch, computed, ref, onBeforeUnmount } from 'vue' | ||||
| import { useGlobalStore } from '@/scripts/stores/global' | ||||
| import { useCompanyStore } from '@/scripts/stores/company' | ||||
| import { useExchangeRateStore } from '@/scripts/stores/exchange-rate' | ||||
| @ -110,7 +110,8 @@ watch( | ||||
|   () => props.store[props.storeProp].currency_id, | ||||
|   (v) => { | ||||
|     onChangeCurrency(v) | ||||
|   } | ||||
|   }, | ||||
|   { immediate: true } | ||||
| ) | ||||
| watch( | ||||
|   () => props.customerCurrency, | ||||
| @ -144,7 +145,7 @@ function setCustomerCurrency(v) { | ||||
|  | ||||
| async function onChangeCurrency(v) { | ||||
|   if (v !== companyCurrency.value.id) { | ||||
|     if (!props.isEdit) { | ||||
|     if (!props.isEdit && v) { | ||||
|       await getCurrenctExchangeRate(v) | ||||
|     } | ||||
|  | ||||
| @ -170,4 +171,8 @@ function getCurrenctExchangeRate(v) { | ||||
|       isFetching.value = false | ||||
|     }) | ||||
| } | ||||
|  | ||||
| onBeforeUnmount(() => { | ||||
|   props.store.showExchangeRate = false | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| @ -140,6 +140,10 @@ export const showError = (error) => { | ||||
|       showToaster('errors.not_allowed') | ||||
|       break | ||||
|  | ||||
|     case 'Email could not be sent to this email address.': | ||||
|       showToaster('errors.email_could_not_be_sent') | ||||
|       break | ||||
|  | ||||
|     default: | ||||
|       showToaster(error, false) | ||||
|       break | ||||
|  | ||||
| @ -1383,7 +1383,8 @@ | ||||
|     "invalid_credentials": "Invalid  Credentials.", | ||||
|     "not_allowed": "Not Allowed", | ||||
|     "login_invalid_credentials": "These credentials do not match our records.", | ||||
|     "enter_valid_cron_format": "Please enter a valid cron format" | ||||
|     "enter_valid_cron_format": "Please enter a valid cron format", | ||||
|     "email_could_not_be_sent": "Email could not be sent to this email address." | ||||
|   }, | ||||
|   "pdf_estimate_label": "Estimate", | ||||
|   "pdf_estimate_number": "Estimate Number", | ||||
|  | ||||
| @ -278,6 +278,14 @@ export const useInvoiceStore = (useWindow = false) => { | ||||
|           axios | ||||
|             .post(`/api/v1/invoices/${data.id}/status`, data) | ||||
|             .then((response) => { | ||||
|               let pos = this.invoices.findIndex( | ||||
|                 (invoices) => invoices.id === data.id | ||||
|               ) | ||||
|  | ||||
|               if (this.invoices[pos]) { | ||||
|                 this.invoices[pos].status = 'SENT' | ||||
|               } | ||||
|  | ||||
|               notificationStore.showNotification({ | ||||
|                 type: 'success', | ||||
|                 message: global.t('invoices.mark_as_sent_successfully'), | ||||
|  | ||||
| @ -149,14 +149,19 @@ | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-name="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `customers/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500 flex flex-col" | ||||
|           > | ||||
|             {{ row.data.name }} | ||||
|             <span class="text-xs text-gray-400"> | ||||
|               {{ row.data.contact_name ? row.data.contact_name : '' }}</span | ||||
|             > | ||||
|           <router-link :to="{ path: `customers/${row.data.id}/view` }"> | ||||
|             <BaseText | ||||
|               :text="row.data.name" | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="font-medium text-primary-500 flex flex-col" | ||||
|             /> | ||||
|             <BaseText | ||||
|               :text="row.data.contact_name ? row.data.contact_name : ''" | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="text-xs text-gray-400" | ||||
|             /> | ||||
|           </router-link> | ||||
|         </template> | ||||
|  | ||||
|  | ||||
| @ -131,7 +131,9 @@ | ||||
|           style="border-top: 1px solid rgba(185, 193, 209, 0.41)" | ||||
|         > | ||||
|           <div> | ||||
|             <div | ||||
|             <BaseText | ||||
|               :text="customer.name" | ||||
|               :length="30" | ||||
|               class=" | ||||
|                 pr-2 | ||||
|                 text-sm | ||||
| @ -142,11 +144,12 @@ | ||||
|                 capitalize | ||||
|                 truncate | ||||
|               " | ||||
|             > | ||||
|               {{ customer.name }} | ||||
|             </div> | ||||
|             <div | ||||
|             /> | ||||
|              | ||||
|             <BaseText | ||||
|               v-if="customer.contact_name" | ||||
|               :text="customer.contact_name" | ||||
|               :length="30" | ||||
|               class=" | ||||
|                 mt-1 | ||||
|                 text-xs | ||||
| @ -155,9 +158,7 @@ | ||||
|                 leading-5 | ||||
|                 text-gray-600 | ||||
|               " | ||||
|             > | ||||
|               {{ customer.contact_name }} | ||||
|             </div> | ||||
|             /> | ||||
|           </div> | ||||
|           <div class="flex-1 font-bold text-right whitespace-nowrap"> | ||||
|             <BaseFormatMoney | ||||
|  | ||||
| @ -184,7 +184,7 @@ | ||||
|  | ||||
|         <!-- Estimate date  --> | ||||
|         <template #cell-estimate_date="{ row }"> | ||||
|             {{ row.data.formatted_estimate_date }} | ||||
|           {{ row.data.formatted_estimate_date }} | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-estimate_number="{ row }"> | ||||
| @ -197,9 +197,7 @@ | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-name="{ row }"> | ||||
|           <div> | ||||
|             {{ row.data.customer.name }} | ||||
|           </div> | ||||
|           <BaseText :text="row.data.customer.name" :length="30" /> | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-status="{ row }"> | ||||
| @ -209,7 +207,10 @@ | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-total="{ row }"> | ||||
|           <BaseFormatMoney :amount="row.data.total" /> | ||||
|           <BaseFormatMoney | ||||
|             :amount="row.data.total" | ||||
|             :currency="row.data.customer.currency" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|         <!-- Actions --> | ||||
|  | ||||
| @ -180,7 +180,9 @@ | ||||
|             style="border-bottom: 1px solid rgba(185, 193, 209, 0.41)" | ||||
|           > | ||||
|             <div class="flex-2"> | ||||
|               <div | ||||
|               <BaseText | ||||
|                 :text="estimate.customer.name" | ||||
|                 :length="30" | ||||
|                 class=" | ||||
|                   pr-2 | ||||
|                   mb-2 | ||||
| @ -192,10 +194,8 @@ | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                 " | ||||
|               > | ||||
|                 {{ estimate.customer.name }} | ||||
|               </div> | ||||
|  | ||||
|               /> | ||||
|                | ||||
|               <div | ||||
|                 class=" | ||||
|                   mt-1 | ||||
|  | ||||
| @ -422,14 +422,21 @@ async function searchCustomer(search) { | ||||
| } | ||||
|  | ||||
| async function loadData() { | ||||
|   expenseStore.currentExpense.currency_id = companyStore.selectedCompanyCurrency.id | ||||
|   expenseStore.currentExpense.selectedCurrency = companyStore.selectedCompanyCurrency | ||||
|   if (!isEdit.value) { | ||||
|     expenseStore.currentExpense.currency_id = | ||||
|       companyStore.selectedCompanyCurrency.id | ||||
|     expenseStore.currentExpense.selectedCurrency = | ||||
|       companyStore.selectedCompanyCurrency | ||||
|   } | ||||
|  | ||||
|   isFetchingInitialData.value = true | ||||
|   await expenseStore.fetchPaymentModes({ limit: 'all' }) | ||||
|  | ||||
|   if (isEdit.value) { | ||||
|     await expenseStore.fetchExpense(route.params.id) | ||||
|  | ||||
|     expenseStore.currentExpense.currency_id = | ||||
|       expenseStore.currentExpense.selectedCurrency.id | ||||
|   } else if (route.query.customer) { | ||||
|     expenseStore.currentExpense.customer_id = route.query.customer | ||||
|   } | ||||
|  | ||||
| @ -181,12 +181,15 @@ | ||||
|         <template #cell-amount="{ row }"> | ||||
|           <BaseFormatMoney | ||||
|             :amount="row.data.amount" | ||||
|             :currency="companyStore.selectedCompanyCurrency" | ||||
|             :currency="row.data.currency" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-user_name="{ row }"> | ||||
|           {{ row.data.customer ? row.data.customer.name : '-' }} | ||||
|           <BaseText | ||||
|             :text="row.data.customer ? row.data.customer.name : '-'" | ||||
|             :length="30" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-notes="{ row }"> | ||||
|  | ||||
| @ -179,7 +179,10 @@ | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-name="{ row }"> | ||||
|           {{ row.data.customer.name }} | ||||
|          <BaseText | ||||
|             :text="row.data.customer.name" | ||||
|             :length="30" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|         <!-- Invoice Number  --> | ||||
| @ -194,7 +197,7 @@ | ||||
|  | ||||
|         <!-- Invoice date  --> | ||||
|         <template #cell-invoice_date="{ row }"> | ||||
|             {{ row.data.formatted_invoice_date }} | ||||
|           {{ row.data.formatted_invoice_date }} | ||||
|         </template> | ||||
|  | ||||
|         <!-- Invoice Total  --> | ||||
|  | ||||
| @ -381,7 +381,9 @@ onSearched = debounce(onSearched, 500) | ||||
|             style="border-bottom: 1px solid rgba(185, 193, 209, 0.41)" | ||||
|           > | ||||
|             <div class="flex-2"> | ||||
|               <div | ||||
|               <BaseText | ||||
|                 :text="invoice.customer.name" | ||||
|                 :length="30" | ||||
|                 class=" | ||||
|                   pr-2 | ||||
|                   mb-2 | ||||
| @ -393,9 +395,7 @@ onSearched = debounce(onSearched, 500) | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                 " | ||||
|               > | ||||
|                 {{ invoice.customer.name }} | ||||
|               </div> | ||||
|               /> | ||||
|  | ||||
|               <div | ||||
|                 class=" | ||||
|  | ||||
| @ -161,9 +161,11 @@ | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-name="{ row }"> | ||||
|           <span> | ||||
|             {{ row.data.customer.name }} | ||||
|           </span> | ||||
|           <BaseText | ||||
|             :text="row.data.customer.name" | ||||
|             :length="30" | ||||
|             tag="span" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|         <template #cell-payment_mode="{ row }"> | ||||
| @ -185,7 +187,7 @@ | ||||
|         <template #cell-amount="{ row }"> | ||||
|           <BaseFormatMoney | ||||
|             :amount="row.data.amount" | ||||
|             :currency="companyStore.selectedCompanyCurrency" | ||||
|             :currency="row.data.customer.currency" | ||||
|           /> | ||||
|         </template> | ||||
|  | ||||
|  | ||||
| @ -162,7 +162,9 @@ | ||||
|             style="border-bottom: 1px solid rgba(185, 193, 209, 0.41)" | ||||
|           > | ||||
|             <div class="flex-2"> | ||||
|               <div | ||||
|               <BaseText | ||||
|                 :text="payment?.customer?.name " | ||||
|                 :length="30" | ||||
|                 class=" | ||||
|                   pr-2 | ||||
|                   mb-2 | ||||
| @ -174,9 +176,7 @@ | ||||
|                   capitalize | ||||
|                   truncate | ||||
|                 " | ||||
|               > | ||||
|                 {{ payment?.customer?.name }} | ||||
|               </div> | ||||
|               /> | ||||
|  | ||||
|               <div | ||||
|                 class=" | ||||
|  | ||||
| @ -124,7 +124,11 @@ | ||||
|         " | ||||
|       > | ||||
|         <!-- Tabs --> | ||||
|         <BaseTabGroup class="-mb-5" @change="setStatusFilter"> | ||||
|         <BaseTabGroup | ||||
|           class="-mb-5" | ||||
|           :default-index="currentStatusIndex" | ||||
|           @change="setStatusFilter" | ||||
|         > | ||||
|           <BaseTab :title="$t('recurring_invoices.active')" filter="ACTIVE" /> | ||||
|           <BaseTab :title="$t('recurring_invoices.on_hold')" filter="ON_HOLD" /> | ||||
|           <BaseTab :title="$t('recurring_invoices.all')" filter="ALL" /> | ||||
| @ -189,24 +193,29 @@ | ||||
|  | ||||
|         <!-- Starts at  --> | ||||
|         <template #cell-starts_at="{ row }"> | ||||
|             {{ row.data.formatted_starts_at }} | ||||
|           {{ row.data.formatted_starts_at }} | ||||
|         </template> | ||||
|  | ||||
|         <!-- Customer  --> | ||||
|         <template #cell-customer="{ row }"> | ||||
|           <router-link | ||||
|             :to="{ path: `recurring-invoices/${row.data.id}/view` }" | ||||
|             class="font-medium text-primary-500 flex flex-col" | ||||
|           > | ||||
|             {{ row.data.customer.name }} | ||||
|           <router-link :to="{ path: `recurring-invoices/${row.data.id}/view` }"> | ||||
|             <BaseText | ||||
|               :text="row.data.customer.name" | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="font-medium text-primary-500 flex flex-col" | ||||
|             /> | ||||
|  | ||||
|             <span class="text-xs text-gray-400"> | ||||
|               {{ | ||||
|             <BaseText | ||||
|               :text=" | ||||
|                 row.data.customer.contact_name | ||||
|                   ? row.data.customer.contact_name | ||||
|                   : '' | ||||
|               }} | ||||
|             </span> | ||||
|               " | ||||
|               :length="30" | ||||
|               tag="span" | ||||
|               class="text-xs text-gray-400" | ||||
|             /> | ||||
|           </router-link> | ||||
|         </template> | ||||
|  | ||||
| @ -331,6 +340,10 @@ onUnmounted(() => { | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const currentStatusIndex = computed(() => { | ||||
|   return statusList.value.findIndex((status) => status === filters.status) | ||||
| }) | ||||
|  | ||||
| function canViewActions() { | ||||
|   return userStore.hasAbilities([ | ||||
|     abilities.DELETE_RECURRING_INVOICE, | ||||
|  | ||||
| @ -238,7 +238,9 @@ onSearched = debounce(onSearched, 500) | ||||
|           style="border-bottom: 1px solid rgba(185, 193, 209, 0.41)" | ||||
|         > | ||||
|           <div class="flex-2"> | ||||
|             <div | ||||
|             <BaseText | ||||
|               :text="invoice.customer.name" | ||||
|               :length="30" | ||||
|               class=" | ||||
|                 pr-2 | ||||
|                 mb-2 | ||||
| @ -250,10 +252,8 @@ onSearched = debounce(onSearched, 500) | ||||
|                 capitalize | ||||
|                 truncate | ||||
|               " | ||||
|             > | ||||
|               {{ invoice.customer.name }} | ||||
|             </div> | ||||
|  | ||||
|             /> | ||||
|              | ||||
|             <div | ||||
|               class=" | ||||
|                 mt-1 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user